Почему мой код Masm615/Win32 не выводит на консоль результат или ошибку?

Я просто изучаю это за короткий семестр, всего за 6 недель. все еще не понимаю, что такое язык ассемблера, этот код также используется

вот как это выглядит, когда я запускаю код Вывод кода

TITLE AssignmentP2 (Mult.asm)
; This program calculates the value using the following data
; Val1 = 340d
; Val2 = A3Ch
; Val3 = 45h
; FinalVal = -(Val1 – Val3) + 1 + (Val2 * 3) + 1 + 1 – 2 -1– (Val1 / 2)

INCLUDE Irvine32.inc
INCLUDE macros.inc  ; Include macros for WriteDec and Crlf

.data
Val1 dword 340d
Val2 dword 0A3Ch
Val3 dword 45h

.code
main proc
    mov eax, [Val1]  ; Load Val1 into eax
    sub eax, [Val3]  ; Subtract Val3 from eax
    neg eax          ; Negate eax (2's complement)
    inc eax          ; Add 1 to eax
    mov ebx, [Val2]  ; Load Val2 into ebx
    imul ebx, 3      ; Multiply ebx by 3
    add eax, ebx     ; Add ebx to eax
    inc eax          ; Add 1 to eax
    inc eax          ; Add 1 to eax
    sub eax, 2       ; Subtract 2 from eax
    dec eax          ; Subtract 1 from eax

    mov edx, eax     ; Preserve the result in edx
    mov ebx, [Val1]  ; Load Val1 into ebx
    mov ecx, 2       ; Divisor (2)
    div ecx          ; Divide eax by ecx (Val1 / 2)
    mov ecx, eax     ; Store the result (Val1 / 2) in ecx
    mov eax, edx     ; Restore the preserved result into eax

    call WriteDec    ; Call WriteDec to print the result

main endp

end main

ответ, который я ожидаю в десятичном виде, — 12417.

Из вашего вопроса неясно, какие команды вы запускали для сборки и связывания вашего кода.

Michael 05.10.2023 16:18

При ссылке вы использовали /subsystem:console ? Вам также не хватает ret в конце main

Michael Petch 05.10.2023 17:03

Причина, по которой он ничего не печатает, скорее всего, заключается в том, что DIV ECX — это настоящий EDX:EAX, разделенный на ECX. EDX следует обнулить перед DIV, поскольку EDX является частью делимого, и вычисление приводит к исключению целочисленного переполнения (которое преждевременно завершает работу программы). Поскольку EDX является частью расчета DIV, вам придется сохранить предыдущее значение в регистре, отличном от EDX (т. е. ESI). Вам также не хватает вычитания в конце. Я также считаю, что результат должен быть 7419 (десятичный). Примечание. Деление на 2 также можно выполнить путем сдвига значения вправо на 1 бит.

Michael Petch 06.10.2023 00:41

Если это единственная ошибка, дублируйте Почему EDX должен быть равен 0 перед использованием инструкции DIV? (за исключением того факта, что степени 2 следует просто использовать сдвиг.)

Peter Cordes 06.10.2023 01:32

Целочисленная математика ассоциативна, 1 + 1 + 1 - 2 - 1 — это 0, поэтому вы можете отбросить все инструкции inc/dec и sub eax,2, если хотите. Конечно, есть много других упрощений, которые мог бы сделать компилятор, например, -(x - y) становится y-x, и оптимизация глазка, например, использование lea edx, [edx + edx*2] для умножения на 3. (Компиляторы будут избегать EBX, потому что он зарезервирован для вызова: если main возвращается к вызывающему объекту, он должен восстановить входящее значение EBX или избегать его использования.) godbolt.org/z/xdh8cY5Tb показывает фактический ассемблерный вывод GCC и MSVC, а также неоптимизированный MSVC с использованием imul reg, mem, 3

Peter Cordes 06.10.2023 02:18

Если предположить, что это связано с исключением разделения, очень плохо, что вам об этом ничего не говорит. Если вы написали ту же программу под Linux, оболочка сообщит вам, что ваша программа завершилась с арифметическим исключением (на самом деле там написано «исключение с плавающей запятой», поскольку POSIX требует SIGFPE, если математические вычисления приводят к сбою, даже целочисленные математические вычисления, так что все не так). Это не идеально с точки зрения простоты понимания, какую проблему искать, но, по крайней мере, есть что погуглить). Если вы запустите это под отладчиком, покажет ли это вам проблему?

Peter Cordes 06.10.2023 21:52

@PeterCordes ожидается, когда в программе нет обработки исключений. Если бы он запустил это в отладчике, отладчик поймал бы необработанные исключения и показал бы ошибку.

Michael Petch 07.10.2023 03:08

@MichaelPetch: Другие ошибки, такие как ошибки недопустимых страниц (неверные указатели) или #GP (например, из-за неправильной загрузки/сохранения SSE), также просто автоматически завершают программу под Windows по умолчанию? (По крайней мере, для консольного приложения? Кажется, я видел скриншоты диалоговых окон при недопустимом доступе.) Еще одна причина, по которой необходимо использовать отладчик!

Peter Cordes 07.10.2023 03:41

@PeterCordes: Да, любая программа, которая не перехватывает исключения, автоматически завершится, и оболочка ничего не отобразит. Код, который вы видите, отображающий ошибку исключения, обычно окружен обработкой исключений (в языках высокого уровня есть необходимый код) и перехватывается приложением. Консольные приложения с правильной обработкой исключений будут отображать полезные сообщения об ошибках.

Michael Petch 07.10.2023 03:47

@MichaelPetch: Может ли лучшая оболочка обнаружить выход дочернего процесса с неперехваченным исключением SEH(?), например Cygwin или MinGW bash, или теоретически, если это не так?

Peter Cordes 07.10.2023 03:49

Оболочка MinGW, запускающая программу Windows в этом примере, не отображает необработанные исключения. Windows PowerShell тоже этого не делает.

Michael Petch 07.10.2023 04:00

На самом деле я понимаю это сразу после того, как вижу комментарий @PeterCordes, поскольку он действительно очень помогает, хотя на Youtube и Google все еще требуется некоторое время, чтобы понять концепцию, но в конце концов я ее понимаю. Спасибо большое 👍

Nicholas Tam 08.10.2023 15:41
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
12
103
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После моего последнего ответа (который оказался не очень хорошим) я решил вернуться к идее из первого поста. Расчеты + вывод. Печатает 7419.

TITLE AssignmentP2 (Mult.asm)
; This program calculates the value using the following data
; Val1 = 340d
; Val2 = A3Ch
; Val3 = 45h
; FinalVal = -(Val1 – Val3) + 1 + (Val2 * 3) + 1 + 1 – 2 -1– (Val1 / 2)
                    
include \masm32\include\Irvine32.inc
includelib \masm32\lib\Irvine32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib


.data
Val1 dword 340d  
Val2 dword 0A3Ch  ; 2620       
Val3 dword 45h    ; 69             

.code
main proc
    mov eax, [Val1]  ; Load Val1 into eax
  
    sub eax, [Val3]  ; Subtract Val3 from eax
    
    neg eax          ; Negate eax (2's complement)
    
    inc eax          ; Add 1 to eax
    
    mov ebx, [Val2]  ; Load Val2 into ebx
    
    imul ebx, 3      ; Multiply ebx by 3

    add eax, ebx     ; Add ebx to eax

    inc eax          ; Add 1 to eax
    
    inc eax          ; Add 1 to eax

    sub eax, 2       ; Subtract 2 from eax
    
    dec eax          ; Subtract 1 from eax

    mov ebx, [Val1]  ; Load Val1 into ebx

    shr ebx, 1       ; divide value in ebx by 2
   
    sub eax, ebx     ; Substract value in ebx from eax                      

    call WriteDec
    exit
    ret
main endp

end main

Что конкретно делает этот код, чтобы решить проблему(и) из вопроса? Почему этот код примерно в 4 раза больше кода в вопросе?

Michael 06.10.2023 15:43

Ничего особенного, просто шаг за шагом вычисляет это уравнение и показывает в окне консоли результат каждой инструкции. Линии mov [show_reg], X, call output можно легко удалить, как и output proc. В конце концов, вычислений WriteInt достаточно, потому что я думаю, что WriteDec не очень хорошо работает с отрицательными числами.

Nassau 06.10.2023 16:17

Огромный блок кода будет очень медленно читаться, особенно новичкам, особенно без текста, указывающего, какие изменения вы внесли. По поводу смены ключа даже комментариев нет, shr ebx, 1. Хорошие ответы должны содержать текст, который отвечает на вопрос о том, что не так с кодом, и объясняет, что показывает блок кода.

Peter Cordes 06.10.2023 19:43

Также ОП ожидает положительного результата. Скопировав/вставив исходное выражение в calc с помощью Val1=340/Val2=0xA3C/Val3 = 0x45, я получаю 7419, что отличается как от вашего результата, так и от результата, который они ожидали. :/ Выражение в комментарии (с исправленными не-ASCII-знаками -) равно -(Val1 - Val3) + 1 + (Val2 * 3) + 1 + 1 - 2 -1 - (Val1 / 2)

Peter Cordes 06.10.2023 19:46
Val1 340d или OP просто быстро набрали и вместо d должно быть h? 340h?
Nassau 06.10.2023 19:54

Я изменил значение на 340h и результат 6681. А выражение -(Val1 - Val3) + 1 + (Val2 * 3) + 1 + 1 - 2 - 1 - (Val1 / 2)?

Nassau 06.10.2023 20:00

Хорошо, если val1 равно 340, результат 7419, мой код показывает хороший результат.

Nassau 06.10.2023 20:16

Я предположил, что 340d намеренно указывает десятичное число, потому что суффикс d для него является допустимым синтаксисом MASM. (Сбивает с толку, поскольку похоже, что кто-то забыл конечную букву h при попытке написать 340Dh, но я видел, как многие люди писали десятичные числа «явно» таким образом в предыдущих вопросах SO.) Математический результат с Val2=0x340D равен -12058.5, а не целое число, так что это еще одна причина сомневаться в том, что это было задумано. Я не пытался выяснить, какие входные данные дадут «ожидаемый» результат ОП.

Peter Cordes 06.10.2023 20:17

Кстати, посмотрите недавнюю мета-дискуссию об ответах только на код, которые не объясняют сами себя: Как мы можем поощрять ответы, которые будут полезны не только спрашивающему? - широко распространено мнение, что объяснения намного лучше для всех, кто позже натыкается на вопросы и ответы (включая людей, ищущих дубликаты для будущих вопросов), а также для ОП. Ведутся серьезные споры о том, лучше ли публиковать только код, чем вообще не отвечать, если у вас нет времени написать хотя бы одно или два предложения о коде, который вы публикуете.

Peter Cordes 06.10.2023 20:20

Возможно, вы могли бы предварить этот ответ, сказав: «Я поигрался с этим из собственного любопытства», потому что именно так это выглядит. Если вы просто хотите увидеть, как значения изменяются по мере выполнения шагов, используйте отладчик, который выделяет последний регистр(ы), которые нужно изменить, по мере пошагового выполнения. Вот почему у нас есть отладчики, потому что, как показывает ваш ответ, написание отладочных отпечатков в asm требует гораздо больше кода, чем в C, где вы можете просто щелкнуть printf где-нибудь, не затрагивая другие переменные. (У Irvine32 есть call DumpReg, но это не подчеркивает последнее изменение.)

Peter Cordes 06.10.2023 20:24

Теперь в вашем ответе есть текст, но вы по-прежнему не упоминаете основную проблему с кодом в вопросе (что вообще мешало ему напечатать ответ): Почему EDX должен быть равен 0 перед использованием инструкции DIV ? . Это были только упоминания комментариев, а не реальных ответов. Тому, кто еще этого не знает, придется читать ваш ответ по одной строке за раз, чтобы сравнить его с вопросом и найти различия, чтобы увидеть, в чем они заключаются.

Peter Cordes 06.10.2023 21:14

Другие вопросы по теме