Вопрос или проблема
Почему выводится только результат сложения, а вычитание не отображается?
section .data
num1 dq 5 ; Первое число (64-битное целое)
num2 dq 2 ; Второе число (64-битное целое)
mathResult db 'Результат математики: %d', 0ah, 0
section .text
global main ; Определяем основную функцию (точка входа)
extern printf ; Связываемся с printf из MSVCRT
extern ExitProcess ; Связываемся с ExitProcess из Kernel32
main:
sub rsp, 40 ; Выровнять стек (ABI Windows требует выравнивание на 16 байт)
; Сложение
mov rax, [num1]
add rax, [num2]
call display_result
; Вычитание
mov rax, [num1]
sub rax, [num2]
call display_result
display_result:
mov rcx, mathResult ; Используем одно и то же сообщение для обеих операций
mov rdx, rax
call printf
ret
exit_program:
xor ecx, ecx ; Устанавливаем код выхода в 0 (ECX = 0)
call ExitProcess ; Вызываем ExitProcess для завершения программы
Ответ или решение
Ваше наблюдение о том, что выводится только результат сложения, а не вычитания, связано с тем, что после вызова функции display_result
для сложения программа не возвращается в main
, а продолжает выполнение, потенциально теряя управление потоком. Давайте исправим вашу программу, чтобы оба результата корректно отображались.
Вот исправленный код на ассемблере, который выводит результаты как сложения, так и вычитания:
section .data
num1 dq 5 ; Первое число (64-битное целое)
num2 dq 2 ; Второе число (64-битное целое)
mathResultAdd db 'Результат сложения: %d', 0ah, 0 ; Формат для сложения
mathResultSub db 'Результат вычитания: %d', 0ah, 0 ; Формат для вычитания
section .text
global main ; Определяем точку входа - функцию main
extern printf ; Ссылка на функцию printf из MSVCRT
extern ExitProcess ; Ссылка на функцию ExitProcess из Kernel32
main:
sub rsp, 40 ; Выравнивание стека (Windows ABI требует 16-байтовое выравнивание)
; Сложение
mov rax, [num1]
add rax, [num2]
mov rcx, mathResultAdd ; Используем строку для отображения сложения
call display_result
; Вычитание
mov rax, [num1]
sub rax, [num2]
mov rcx, mathResultSub ; Используем строку для отображения вычитания
call display_result
; Завершение программы
xor ecx, ecx ; Устанавливаем код выхода в 0 (ECX = 0)
call ExitProcess ; Вызываем ExitProcess для завершения программы
display_result:
mov rdx, rax ; Передаем результат (rax) в rdx
call printf ; Вызов printf для отображения результата
ret ; Возвращаемся из функции
Объяснение изменений:
-
Разделение строк формата:
Я создал две разные строки формата: одну для результата сложения (mathResultAdd
), и другую для результата вычитания (mathResultSub
). Это позволяет нам четко указать, какой результат мы выводим. -
Передача строк формата:
Перед каждым вызовомdisplay_result
значениеrcx
обновляется соответственно на нужную строку формата для сложения или вычитания. -
Упрощенное управление потоками:
Теперь при вызовеdisplay_result
каждый раз после вычисления результата программа корректно возвращается из функции и выполняет следующий блок кода, обеспечивая, что оба результата будут изображены в выходном окне.
Таким образом, с помощью этих исправлений ваша ассемблерная программа теперь будет правильно выводить и результаты сложения, и вычитания в консоль.