flat assembler
Message board for the users of flat assembler.

Index > Main > Syntax of immediate operand for div?

Author
Thread Post new topic Reply to topic
jkhjklhgl



Joined: 04 Mar 2016
Posts: 9
jkhjklhgl
div 2

gives Error: invalid operand
How should it be written?
Post 04 Mar 2016, 19:05
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17658
Location: In your JS exploiting you and your system
revolution
Code:
mov ecx,2
div ecx ;for dword
div ecx ;for word
idiv eax,ecx,2 ;for immediate only idiv is available    
Post 04 Mar 2016, 23:38
View user's profile Send private message Visit poster's website Reply with quote
Xorpd!



Joined: 21 Dec 2006
Posts: 161
Xorpd!
Are you sure about that? Intel's docs indicate a syntax like the above for IMUL, but not DIV nor IDIV. There is AAM imm8 which performs a divide of AH:AL by an immediate byte, but it doesn't work in 64-bit mode.
Post 05 Mar 2016, 09:06
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17658
Location: In your JS exploiting you and your system
revolution
Xorpd! wrote:
Are you sure about that? Intel's docs indicate a syntax like the above for IMUL, but not DIV nor IDIV. There is AAM imm8 which performs a divide of AH:AL by an immediate byte, but it doesn't work in 64-bit mode.
Your are correct, idiv doesn't have any immediate. I must have been confused with imul. Thanks for the correction.
Post 05 Mar 2016, 09:17
View user's profile Send private message Visit poster's website Reply with quote
taeyun



Joined: 12 Jan 2014
Posts: 42
Location: south korea
taeyun
you need register.
if you don't like this, you can trick your self with macro.

div register version:(you can replace div with idiv for signed value)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if you want to divide 0xff by 0x02(which is 1 byte divisor)
you need to
put 0xff to ax,
put 0x02 to other 1 byte register(such as bl),
div bl

now you have
quotient in al
remainder in ah

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if you want to divide with 2 byte divisor such as 0x0222,
you can divide 4 byte (such as 0xaabbccdd)
to do so,
put 0xaabb to dx
put 0xccdd to ax
put 0x0222 to other 2 byte register(such as bx),
div bx

now you have
quotient in ax
remainder in dx
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if you want to divide with 4 byte divisor such as 0x00112233,
you can divide 8 byte (such as 0xaaaabbbbccccdddd)
to do so,
put 0xaaaabbbb to edx
put 0xccccdddd to eax
put 0x00112233 to other 4 byte register(such as ebx),
div ebx

now you have
quotient in eax
remainder in edx

it is quiet handy to use CDQ instruction.
CDQ extend eax value to edx.
for instance, if you want to divide 0xaaaabbbb with 0xddddeeee, you can:
mov eax, 0xaaaabbbb
CDQ
mov ebx, 0xddddeeee
div ebx

now you have quotient in eax
and remainder in edx

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
div macro version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;;put value you want to divide into eax
macro mydiv reg
{
cdq
push ebx
mov ebx, reg
div ebx
pop ebx
}

and use it
mydiv 2
Post 07 Mar 2016, 06:10
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 1520
Furs
An alternative to division by a constant is to do a "inverse" multiplication, since a constant is "known" and can be converted to an inverse multiplication by another constant which is faster.

The other reason to use div instead of mul is if you are using the highest bit-width available on your CPU mode for a division (for x86 32-bit, that is 64-bit, and for x86-64 64-bit, that is 128-bit; in both cases it's made of registers edx:eax and rdx:rax respectively). For example, dividing rdx:rax by a certain constant requires div.

But if you only want to divide eax in 32-bit, you can just treat it as a fixed point multiplication, do the 64-bit multiplication, and take edx as the result (not eax), aka the higher half.

Mathematically, it is equivalent to:

a * (b / 2^32)

You see b can be an integer but because it is divided by 2^32, you get a division. However the order of operations can be like this:

(a*b) / 2^32

The last division/bit shift isn't even needed since that simply means the 'edx' part of the edx:eax composite result.

Note that depending on the constant and its reciprocal, there may be round-off errors you'll have to compensate. For example, division by 3 has the "inverse mul" constant started from:

2^32 / 3 = 0x55555555

Turns out this isn't very precise due to roundoff errors, so what people did was to increase the range to 33 bits and round up, and then right shift 'edx' by 1 (to divide by 2^33 instead of 2^32). For example (the +1 is due to rounding up the .(6) fraction):

2^33 / 3 + 1 = 0xAAAAAAAB

Code:
; eax = your number
mov edx, 0xAAAAAAAB
mul edx
shr edx, 1
; edx = output, eax/3    
Post 08 Mar 2016, 15:14
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7795
Location: Kraków, Poland
Tomasz Grysztar
Furs wrote:
An alternative to division by a constant is to do a "inverse" multiplication, since a constant is "known" and can be converted to an inverse multiplication by another constant which is faster.
Thank you for bringing this up, this is one of the tricks that are very valuable to assembly programmer. This technique was discussed on the old Win32Asm community message board back in 2005 and I posted there about an additional variant. When you know that your number is divisible by your fixed divisor then you can perform division by multiplication without additional shifts, and this means that you can use IMUL instruction with immediate (and this perfectly fits the problem discussed here).

You can find that post (and the complete discussion) archived at http://www.asmcommunity.net/forums/topic/?id=21308#post-161744
I don't know if that archive is reliable, and it does not preserve the original formatting well, so I'm also copying my old post here:
Tomasz Grysztar in 2005 wrote:
If you want to divide by the odd number, and you know the number you want to divide is divisible without remainder, you can do this by multiplying by "magic" number and take the LOW half of the result, without need to do any shifts etc.

This approach is based on the theory of 2-adic numbers, if you need some elementary information on 2-adic number, you can find it in the Programming Tutorial I've once started.

For example, the 2-adic reciprocal of 3 is 110101010101... (infinite chain), if we multiply any integer N divisible by 3 by such infinite chain, we will get N/3. On computer we are able to operate only on finite chains, but note, that even when multiplying the infinite ones, the n first bits always depends only on the first n bits of both numbers we multiply. So if we take the first 32 bits of 2-adic 1/3 and multiply the 32-bit integer by it, the low 32 bits of the result will be the correct first 32 bits of the result, N/3 in this case.

The first 32 bits of infinite 1/3 expansion are 0AAAAAAABh (and the whole expansion goes as if we were adding infinite amount of A digits to the left), therefore this code:
Code:
mov eax,N
mov ebx,0AAAAAAABh
mul ebx    
will calculate the N/3 for us in EAX.

When you want to divide by even number, you can factorize it to some power of two and odd number, then make one multiplication like above and then shift by the amount of bits equal to the power of two from the factorization. Always operating on the lower half of the result! This means you can use this method also with the IMUL instruction variants, which give you only the lower half of the result, like:
Code:
imul eax,0AAAAAAABh ; divide by 3    


However this method has the substantial flow, that the number we want to divide has to be divisible by the value, whose reciprocal we use - otherwise we get the low bits of some infinite expansion of rational number.

The method discussed above doesn't have such disadvantage. But let's see how the two methods are related to each other. If you use Svin's tool to get the magic number for dividing by 3, you will see that it's actually the same as the low 32 bits of p-adic 1/3 we used above. But this time you are told to get the HIGH 32 bits of result and shift them right by one bit.

Indeed, if you check it, when you multiply by 0AAAAAAABh the 32-bit N divisible by 3, you will get N/3 in low 32 bits, and 2N/3 in the high 32 bits. To see how the 2-adic arithmetics can explain this, let's analyze in terms of p-adic rational numbers, what you exactly get, when you do such multiplication. The 0AAAAAAAB is incomplete 1/3, what we cut off is the infinite amount of A digits starting from ninth one (33rd bit), therefore:

N*0AAAAAAABh = N*(1/3 - ...AAA00000000h)

note now that ...AAA00000000h = ...AAAAh * 100000000h = ...AAAAh * (2^32)
but ...AAAAh = ...AAABh - 1 = 1/3 - 1 = -2/3, so:

N*0AAAAAAABh = N * (1/3 - (-2/3)*(2^32)) = N*3 + (2N/3)*(2^32)

so we get exactly what we expected - after multiplyng by 0AAAAAAABh we get N/3 in low 32 bits and 2N/3 in the high bits.

But how does it come, that even when N is not divisible by 3, we get the correct rounded value of N/3 starting from the 34th bit?
If N=M+r, where r<3, then we can split the N*0AAAAAAABh into sum of two products - for M we know we get 2M/3 in upper bits, so it suffices to show that r*0AAAAAAABh has zeros starting from the 34th bit - what is actually evident, since r is smaller than 2^2 and the 0AAAAAAABh is smaller than 2^32, so their product is smaller than 2^34. Well, there might be some overflow when M is very large, near to 2^32, but that's another story - I'm providing only very simplified analysis on single example, but I believe the analogous reasoning works for the general case.

Also, for the small values of M, the "middle" bits, just below the result in high bits, would even allow to recover the remainder from division - though I doubt it could be done efficiently. But if I design any nice algorithm for this, I'll let you know.

I hope I have not bored everyone with those theoretical divagations...
Post 08 Mar 2016, 15:54
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 1520
Furs
Well I learned something new, never heard of 2-adic numbers before this, thanks for the excellent post. It's superior to the fixed point multiplication since it doesn't need twice the bit width as the original so it can be used with IMUL like you said Smile
Post 08 Mar 2016, 16:18
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.