Я не компилировал.
Просто зачем нужно:
mov al, 15
cbw; Это лишняя.
movsx bx, ax; А это неправильная команда.
Если можно:
movsx ax, BYTE PTR [a]; Вот тут синтаксис tasm не помню.
CBW, если правильно помню, расширяет al до ax, сохраняя знак.
MOVSX уже расширяет байт при копировании до слова, сохраняя знак.
Добавлено через 27 минут и 1 секунду:Потренировался я:
USE32
EXTERN _GetStdHandle@4
EXTERN _WriteConsoleA@20
EXTERN _ExitProcess@4
GLOBAL _start
SECTION .text
start:
call setup_console
mov eax, title_1
call print
; f = (a + b) * (c + d)
; Без проверок!
;a = -15
;b = 70
;c = -25
;d = 35
;f = (-15 + 70) * (-25 + 35) = 55 * 10 = 550 - это должно получиться.
movsx ax, BYTE [a]
movsx bx, BYTE [b]
add ax, bx
push ax
movsx ax, BYTE [c]
movsx bx, BYTE [d]
add ax, bx
pop bx
imul bx
mov WORD [f], ax
cwde
call print_num
mov eax, title_2
call print
push DWORD 0
call _ExitProcess@4
; Функция настройки stdout для вывода в консоль.
; ВХОД: без параметров.
; ВЫХОД: записывает значение stdout в глобальную переменную stdout.
; РЕГИСТРЫ: не изменяются.
setup_console:
push eax
push DWORD -11
call _GetStdHandle@4
mov [stdout], eax
pop eax
ret
; Функция определения длины строки по завершающему нулю.
; ВХОД: eax - указатель на исследуемую строку.
; ВЫХОД: записывает длину строки в глобальную переменную length.
; РЕГИСТРЫ: не изменяются.
strlen:
push eax
push esi
push edi
mov esi, eax
xor edi, edi
strlen_loop:
mov al, BYTE [esi]
test al, al
jz strlen_exit
inc esi
inc edi
jmp strlen_loop
strlen_exit:
mov DWORD [length], edi
pop edi
pop esi
pop eax
ret
; Функция выводит строку с завершающим нулём в консоль.
; ВХОД: eax - указатель на строку.
; ВЫХОД: без результатов.
; РЕГИСТРЫ: не изменяются.
print:
call strlen
push ecx
push DWORD 0
push DWORD written
push DWORD [length]
push eax
push DWORD [stdout]
call _WriteConsoleA@20
pop ecx
ret
; Функция выводит цифру в консоль.
; ВХОД: edx - значение выводимой цифры.
; ВЫХОД: без результатов.
; РЕГИСТРЫ: не изменяются.
print_digit:
push eax
push ecx
mov eax, DWORD line
add eax, edx
push DWORD 0
push DWORD written
push DWORD 1
push eax
push DWORD [stdout]
call _WriteConsoleA@20
pop ecx
pop eax
ret
; Функция выводит число со знаком в консоль.
; ВХОД: eax - значение числа со знаком.
; ВЫХОД: без результатов.
; РЕГИСТРЫ: не изменяются.
print_num:
push eax
push ebx
push ecx
push edx
xor ecx, ecx
mov ebx, 10
test eax, 0x80000000
jz print_num_plus
push eax
mov eax, DWORD minus
call print
pop eax
neg eax
print_num_plus:
xor edx, edx
div ebx
push edx
inc ecx
cmp eax, 10
jnc print_num_plus
mov edx, eax
call print_digit
cmp ecx, 1
jnz print_num_loop
pop edx
jmp print_num_exit
print_num_loop:
pop edx
call print_digit
loop print_num_loop
print_num_exit:
mov eax, DWORD line_end
call print
pop edx
pop ecx
pop ebx
pop eax
ret
SECTION .data
a DB -15
b DB 70
c DB -25
d DB 35
f DB 0
title_1 DB "Start.", 0x0A, 0x0D, 0
title_2 DB "Finish.", 0x0A, 0x0D, 0
stdout DD 0
length DD 0
written DD 0
minus DB "- ", 0
line DB "0123456789ABCDEF"
line_end DB 0x0A, 0x0D, 0
Start.
550
Finish.
Для продолжения нажмите любую клавишу . . .
Может где и накосячил, так как бегло набрал.