Простое сложение и вычитание в ассемблере и вывод в окно результата

Вопрос или проблема

Почему выводится только результат сложения, а вычитание не отображается?

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                       ; Возвращаемся из функции

Объяснение изменений:

  1. Разделение строк формата:
    Я создал две разные строки формата: одну для результата сложения (mathResultAdd), и другую для результата вычитания (mathResultSub). Это позволяет нам четко указать, какой результат мы выводим.

  2. Передача строк формата:
    Перед каждым вызовом display_result значение rcx обновляется соответственно на нужную строку формата для сложения или вычитания.

  3. Упрощенное управление потоками:
    Теперь при вызове display_result каждый раз после вычисления результата программа корректно возвращается из функции и выполняет следующий блок кода, обеспечивая, что оба результата будут изображены в выходном окне.

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

Оцените материал
Добавить комментарий

Капча загружается...