Author Topic: How does the 'div' instruction work?  (Read 11173 times)

Offline BenjaminD

  • Jr. Member
  • *
  • Posts: 4
How does the 'div' instruction work?
« on: September 25, 2010, 10:40:52 AM »
Hi, fellow programmers!
I'm writing a function in real mode, (yes you guessed it, it's for an OS bootloader ;)), that'll print the integer stored in AX.
This is the approach that I have chosen, and it should work (to my understading, even though it might not be the best way to do it)..
1)Divide the integer in AX by 10, if the results of the prior computations isn't 0.
2)Push the remainder onto the stack.
3)Increase CX.
4)Do it again.
5)When the result is 0, and all of the remainders are pushed to the stack, pop CX amount of integers off of the stack, in a loop.
6)In each cycle add 0x30 to the popped value, and print it using INT 0x10, AH=0xE.
I have tried writing this function myself A LOT of times, but I've never succeded.. probably because I'm unsure of how the 'div' instruction works in NASM.
So could someone please try to explain to me, where the instruction expects the value to be divided to be, in which register (or parameter) it'll expect the divisor, and finally where the results and remainders are stored?
Oh and one more thing, how can I increase the literal value of CX?

Best regards,
-Benjamin.
« Last Edit: September 25, 2010, 10:43:48 AM by BenjaminD »

Offline cm

  • Jr. Member
  • *
  • Posts: 65
Re: How does the 'div' instruction work?
« Reply #1 on: September 25, 2010, 06:12:25 PM »
Quote
This is the approach that I have chosen, and it should work (to my understading, even though it might not be the best way to do it)..

Right, it should work. True, it's not optimal, but don't aim for optimization until you get to know the basics ;-)

Quote
I have tried writing this function myself A LOT of times, but I've never succeded.. probably because I'm unsure of how the 'div' instruction works in NASM.

See here. This is an older NASM manual, but the part I linked you to is an extensive x86 instruction reference that is still useful and correct for the not so recent instruction sets.

In your case, you'll want to use some 16-bit register (di, si, or bx) or memory operand as divisor which you'll set to 10 before the loop. For example, the instruction "div bx" implicitly divides dx:ax by bx and stores the result in ax, while the remainder is in dx. This means you have to set dx to 0 before the div (but inside the loop), because your input is just ax. A byte divisor would implicitly divide ax by the divisor, but can't be used in your case because then large initial values for ax would overflow the result that implicitly would be stored in al. (If ax is > 2559, the result is > 255.)

Quote
Oh and one more thing, how can I increase the literal value of CX?

I'm not sure what you mean with "literal value", but increasing the value stored in cx by 1 can be done either by inc cx or by add cx, 1. These instructions differ in some specifics; in this case, inc is better as it's a shorter instruction and you don't need add's behaviour of setting CF (the Carry Flag).
C. Masloch

Offline BenjaminD

  • Jr. Member
  • *
  • Posts: 4
Re: How does the 'div' instruction work?
« Reply #2 on: September 25, 2010, 09:29:19 PM »
Quote
This is the approach that I have chosen, and it should work (to my understading, even though it might not be the best way to do it)..

Right, it should work. True, it's not optimal, but don't aim for optimization until you get to know the basics ;-)

Quote
I have tried writing this function myself A LOT of times, but I've never succeded.. probably because I'm unsure of how the 'div' instruction works in NASM.

See here. This is an older NASM manual, but the part I linked you to is an extensive x86 instruction reference that is still useful and correct for the not so recent instruction sets.

In your case, you'll want to use some 16-bit register (di, si, or bx) or memory operand as divisor which you'll set to 10 before the loop. For example, the instruction "div bx" implicitly divides dx:ax by bx and stores the result in ax, while the remainder is in dx. This means you have to set dx to 0 before the div (but inside the loop), because your input is just ax. A byte divisor would implicitly divide ax by the divisor, but can't be used in your case because then large initial values for ax would overflow the result that implicitly would be stored in al. (If ax is > 2559, the result is > 255.)

Quote
Oh and one more thing, how can I increase the literal value of CX?

I'm not sure what you mean with "literal value", but increasing the value stored in cx by 1 can be done either by inc cx or by add cx, 1. These instructions differ in some specifics; in this case, inc is better as it's a shorter instruction and you don't need add's behaviour of setting CF (the Carry Flag).
Thanks, I'll  try to see if I can get it working :).
And by literal value, I meant the value that it actually stored in CX, and not just the address it points to.
EDIT: YES!! I got it working! Thanks for pointing me in the right direction ;).
« Last Edit: September 26, 2010, 08:10:23 AM by BenjaminD »