Подпись без деления в насм
Я пытался отладить небольшую программу сборки, где я запрашиваю дивиденд и делитель, и мне нужно вывести частное и остаток. Однако по некоторым причинам мои частное и остаток не выводятся на экран. Вот мой код:
segment .data
prompt db "Please enter a number: ", 10
promptLen equ $-prompt
prompt2 db "Please enter the divisor: ", 10
prompt2Len equ $-prompt2
prompt3 db "Your quotient is: ", 10
prompt3Len equ $-prompt3
prompt4 db "Your remainder is: ", 10
prompt4Len equ $-prompt4
segment .bss
inputNum resb 2
inputDiv resb 2
quotient resb 2
remainder resb 2
segment .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, prompt
mov edx, promptLen
int 80h
mov eax, 3
mov ebx, 0
mov ecx, inputNum
mov edx, 2
int 80h
mov eax, 4
mov ebx, 1
mov ecx, prompt2
mov edx, prompt2Len
int 80h
mov eax, 3
mov ebx, 0
mov ecx, inputDiv
mov edx, 2
int 80h
xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
sub ax, '0'
sub bx, '0'
div bx
add ax, '0'
add dx, '0'
mov [quotient], ax
mov [remainder], dx
mov eax, 4
mov ebx, 1
mov ecx, prompt3
mov edx, prompt3Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, [quotient]
mov edx, 2
int 80h
mov eax, 4
mov ebx, 1
mov ecx, prompt4
mov edx, prompt4Len
int 80h
mov eax, 4
mov ebx, 1
mov ecx, [remainder]
mov edx, 2
int 80h
jmp exit
exit:
mov eax, 1
xor ebx, ebx
int 80h
Буду признателен, если кто-нибудь поможет мне понять, что я делаю неправильно.
1 ответ
Системный вызов 4 (запись) требует char *
для его адреса буфера в ecx
, С вашим кодом:
mov eax, 4 ; sys_write
mov ebx, 1 ; standard output
mov ecx, [quotient] ; here, ecx <- your character code
mov edx, 2 ; two bytes (hmmm)
int 80h
вы загружаете ecx
с фактическими данными, которые были введены, а не адресом этого.
Что вам нужно сделать, это загрузить ecx
с адресом персонажа, который, вероятно, будет просто что-то вроде:
mov ecx, quotient ; here, ecx <- your character address
Вы также можете уменьшить количество байтов до одного, а не до двух. То, как вы превращаете целые числа в символы (добавление '0'
) в любом случае будет работать только с односимвольными числами, поэтому вам нужен только младший байт (тот, который имеет самый низкий адрес памяти для x86).
То же самое для остатка.
Кроме того, когда вы исправите это, вы все равно получите забавный результат. Разделив 5 на 2, вы получите коэффициент 1 и остаток 3, что явно неверно.
Это связано с тем, как вы вводите данные и загружаете значения в ax
а также bx
,
Так как вы читаете два байта для каждого числа, память загружается самой цифрой '5'
, или же 0x35
сопровождаемый символом новой строки 0x0a
,
Затем, когда вы загружаете двухбайтовое слово в ax
, это заканчивается 0x0a35
,
После вычитания 0x0030
('0'
) от каждого, вы в конечном итоге 0x0a05
а также 0x0a02
который в десятичном виде, 2565
а также 2562
, Когда вы делите эти числа, вы действительно получаете частное 1
и остаток от 3
,
Чтобы это исправить, вы можете просто выбросить 0x0a00
но при загрузке значения, изменив:
xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
sub ax, '0'
sub bx, '0'
в:
xor edx, edx
mov ax, [inputNum]
mov bx, [inputDiv]
and ax, 0xff ; add these
and bx, 0xff ; two lines.
sub ax, '0'
sub bx, '0'