Беззнаково деление в насм

Опитвам се да отстраня грешки в малка асемблерна програма, в която питам за дивидент и делител и трябва да изведа частното и остатъка. По някаква причина обаче частното и остатъкът ми не се извеждат на екрана. Ето моят код:

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

Ще съм благодарен, ако някой може да ми помогне да разбера какво правя грешно.


person O.A.    schedule 20.10.2014    source източник
comment
Какви данни въвеждате?   -  person paxdiablo    schedule 20.10.2014
comment
@paxdiablo, тествах го с моя дивидент 5 и делител 2   -  person O.A.    schedule 20.10.2014
comment
@paxdiablo, Това проработи! Благодаря ти! Но използвайки същите данни, получавам 1 като частно и 3 като остатък. Някаква идея защо?   -  person O.A.    schedule 20.10.2014


Отговори (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'
person paxdiablo    schedule 20.10.2014
comment
Това проработи! Благодаря ти! Но използвайки същите данни, получавам 1 като частно и 3 като остатък. Някаква идея защо? - person O.A.; 20.10.2014
comment
Някакво предложение как да направя десетичното преобразуване, така че да не бъда ограничен само до числа с един знак? - person O.A.; 20.10.2014
comment
@user116317, актуализирах отговора защо получавате странния резултат. Що се отнася до това как да се справя с повече от една цифра, това вероятно трябва да е различен въпрос за SO. По този начин ще получите повече отговор, вместо да питате в полето за коментари. - person paxdiablo; 20.10.2014