3

Following code in emu8086 giving overflow error, all I want to do is to decide if the number is odd or even, so I'm dividing by 2. I can't figure out what's wrong.

CLC
MOV CX, 20d
MOV BX, 07200h    
MOV [07100h], 02h


loop:     
    JCXZ endloop   
    XOR DX, DX
    MOV AX, BX 
    DIV [07100h]              ; overflow error here
    CMP DX, 0001h
    JE even
    JMP odd
endloop:
ErTR
  • 863
  • 1
  • 14
  • 37
  • 4
    To test for odd/even, just isolate the least significant bit, don't use division. Anyway, `7200h/02h=3900h` and that indeed doesn't fit into 8 bit and you used a 8 bit division. Hence the overflow. – Jester Mar 13 '18 at 23:24
  • 1
    why was this downvoted? im not an assembly programmer but it looks like a decent question – Isaac Mar 13 '18 at 23:26
  • @Isaac I wish I can know -_- – ErTR Mar 13 '18 at 23:27
  • @Jester I'm dividing with 16-bit number [07100h], how can I tell it to do 16-bit division more explicitly? – ErTR Mar 13 '18 at 23:28
  • 4
    I guess try something like `DIV WORD [07100h]` or `DIV WORD PTR [07100h]` not sure about emu8086 syntax. But seriously, don't use division. Incidentally, you should fix your `MOV [07100h], 02h` too. – Jester Mar 13 '18 at 23:29
  • I could AND with 0000 0001 then CMP the result but this question's goal is using divide, this is what our instructor dreams. Thanks for your advice though, I know division must be evaded because of high CPU demand, I will keep your advice in mind. – ErTR Mar 13 '18 at 23:37
  • hmmm, you could and with say 7 then divide by 2...then compare, something that definitely wont overflow but also is not technically a bit test. – old_timer Mar 14 '18 at 01:47

1 Answers1

3

emu8086 is bad, and presumably assembles your ambiguous DIV [07100h] into DIV byte [07100h] instead of the DIV word [07100h] you were expecting, instead of giving you an error (ambiguous operand size) like most assemblers would.

Thus, you fault with #DE because 07200h / 2 overflows AL.


First of all, using div for 2 (or a power of 2) is horrible compared to test al, 1 / jnz odd. That's non-destructive, and doesn't modify DX, so you need far fewer registers. And div is much slower than test, as well as being much worse code-size.

But second, storing the divisor to memory and then using a memory source operand is also weird. Use mov si, 13 outside the loop, then div si inside the loop to test for divisibility by 13 or something. That will definitely make the operand-size 16-bit, so you get dx:ax / si into AX and DX, instead of ah:al / 1_byte into AL and AH.

Also, you don't need some extra static storage location, or the extra code-size to encode an address into the store and the div, or the extra cost of loading it from cache every time div runs. (Trivial on a modern CPU compared the cost of div, but actual 8086 didn't have cache, and had to load from memory.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Using WORD key did the trick, I thought since I'm trying to divide a 16-bit number it will handle the rest, thanks to high level language laziness. Storing divisor in memory is another habit of using variables, still trying to adapt in assembly approach. Thank you for your informative answer. – ErTR Mar 14 '18 at 07:18
  • 1
    @ErTR: When you say "variable", you're talking about a static memory location with a label? Try to think like an optimizing compiler: a "variable" is a high level concept, and it can be stored in a register, on the stack, or wherever else you want to put it. Many variables only need to exist in registers. Track them with comments. (Assembly language itself doesn't have variables, it just has symbols/labels. It's up to you to use the right operand-size with the right label, or to decide whether you even need static storage for something.) – Peter Cordes Mar 14 '18 at 08:27