0

I have next problem: when I try to do divide a smaller number to a bigger one I get the quotient very high and I cannot understand why. Here is the program where I am trying to divide 1 to 5 and the result is 256. (also the variables 'a' and 'b' must be of type db) Can someone help me? Thank you in advance

.model small 
afisareanr macro nr
local m11
local m
xor ax, ax
mov ax, nr
push ax             
mov si, 10          
mov di, 5           

mov dx, 0           
cmp ax, 0           
jge m               
neg ax              

m:div si            
add dl, 30h         

mov s[di],dl        

xor dx,dx           
dec di              
cmp ax, 0           

jne m               

pop ax              

cmp ax, 0           
jge m11             
mov s[di], '-'      

m11: 
mov ah, 9           
lea dx, s
int 21h
endm

.stack 
.data 
a db 5
b db 1
s    db 6 dup(" "), '$'

.code 
mov ax, @data 
mov ds, ax

xor ax, ax
xor bx, bx
mov al, b
idiv a
mov bx, ax
afisareanr bx

mov ax, 4c00h
int 21h

end
Marina M
  • 43
  • 4

1 Answers1

1

Seems to be duplicate of all those "why DIV does not work" questions, but somewhat specific and answering it is easier for me than searching for good dupe (will delete answer if somebody else marks one good).

mov al, b     ; AL = b (1) .. and i prefer squared bracket Intel style
              ; like mov al,[b]  - to see easily memory is accessed
idiv a

Now this is getting compiled without error only because you are using TASM in the MASM quirk mode, in TASM "ideal" mode this would be syntax error IIRC (did use TASM in ~1994-1999, so I may remember it wrong).

Problem is, that it's not clear, what is data size.. in assembly experienced programmers prefer the source to be very precise and clear about intent, i.e. idiv byte ptr [a], that makes reading the source and looking for bugs much easier.

So that idiv by byte value 5 is executed. If you will check IDIV description, you should be able to recognize, that you are using the ax / "r/m8" variant, so result is stored into al (quotient) and ah (remainder).

1/5 = 0, remainder 1 ... so al = 0, ah = 1. But that means, that the ax as whole 16 bit register now contains value 0100h = 256.

mov bx, ax

And guess what's getting printed stored into bx here. (print is done by next line using that ugly macro, I would personally prefer to move that macro into code as subroutine and rather call that ... but it looks like you just started now with asm, so for the moment focus on basics, moving macro code to subroutine is simple, but can go wrong if you don't know anything about asm).

BTW, if you have TASM installed, you have also TD (Turbo Debugger). Use that to take a look yourself, what is happening in the CPU after each instruction. It's making learning the ASM much much easier.

Ped7g
  • 16,236
  • 3
  • 26
  • 63
  • thank you so much, I understood what is happening and how appears 256, and yes you are right that I am a novice, we have just started to learn asm at university. – Marina M Nov 11 '17 at 11:02
  • To find the canonical dup-targets for division, look in the [x86 tag wiki](https://stackoverflow.com/tags/x86/info) and search for `idiv`. That's part of why I added the FAQ section. (Hmm, this isn't an *exact* duplicate, because the problem here is not realizing that the remainder goes in AH, rather than failure to clear the upper half of the dividend. But Michael's answer on the linked dup about 8-bit operand size division does mention that part of how it works. Different question same answer.) Anyway, I wouldn't recommend deleting this answer, it's fine. – Peter Cordes Nov 11 '17 at 17:11