So I have found numerous answers for this on Stack Overflow but I still cannot get it to work. What is wrong with my code?
mov al, 12
mov bl, 12
mul bl ; answer in ax
aam
mov bx, 10 ; Divisor constant
xor cx, cx ; Clear counter
.a: xor dx, dx ; Clear dx
div bx ; Divide ax with bx, quotient in al, remainder in ah
mov dh, ah ; Move ah to dh, so we can push the 16 bit register of dx
push dx ; Push dx which contains the remainder
inc cx ; Increment counter
test al, al ; If al (the quotient) is not zero, loop again.
jnz .a
.b: pop dx ; Pop the last remainder to dx from stack
add dx, '0' ; Add '0' to make it into character
push cx ; Push loop counter to stack so printing wont interfere with it
mov eax, 4 ;
mov ebx, 1 ;
mov ecx, edx ; Print last popped character
mov edx, 1 ;
int 0x80 ;
pop cx ; Pop the loop counter back to cx
loop .b ; loop for as long as cx is not 0
CodePudding user response:
The AAM
instruction could be useful for cases where the result would have at most 2 digits. In your case 12 x 12 = 144, so that's a no-go.
The conversion loop that you use is almost correct, but you are mixing sizes in relation to the DIV
instruction. If you give a byte-sized operand to DIV
then the operation will divide AX
by that byte and the remainder will be in AH
. If you give a word-sized operand to DIV
then the operation will divide DX:AX
by that word and the remainder will be in DX
.
Because you're writing 32-bit code, better also write the conversion using 32-bit registers.
Instead of using a digits counter, use a sentinel on the stack. No need to preserve ECX
while displaying.
The display function expects a pointer in ECX
. Just use the stackpointer for this and pop the value post-printing.
mov al, 12
mov bl, 12
mul bl ; answer in AX
movzx eax, ax
mov ebx, 10 ; Divisor constant
push ebx ; Sentinel
.a: xor edx, edx
div ebx ; Divide EDX:EAX with EBX, quotient EAX, remainder EDX
add edx, '0' ; Add '0' to make it into character
push edx
test eax, eax ; If EAX (the quotient) is not zero, loop again.
jnz .a
.b: mov eax, 4
mov ebx, 1
mov ecx, esp
mov edx, 1
int 0x80
pop eax
cmp dword [esp], 10 ; Is it the sentinel ?
jne .b ; No, it's a digit
pop eax ; Remove sentinel
Although not 32-code, Displaying numbers with DOS has more info about converting numbers into text.