Page 1 of 1

Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 5:17 pm
by PearOs
*edited*

Hey gusy, I have a annoying issue where I am getting signed values in Assembly when I shouldn't.

Example:

mov eax, 2830106624
cmp eax, 0
jl .bad
mov byte[0xB8000], 'G'
jmp $
.bad:
mov byte[0xB8000], 'B'
jmp $

Take that x86 Assembly for example, the value put into eax is a unsinged number. If signed it would be negative.
When you run that it prints out B for bad because its less than 0. That should print out G because there is no sign.
Now if I do neg eax after I move the value into eax I get G because obviously if it was negative it now isn't. How do I
move a value like that into eax without having it signed?

That was compiled with Nasm btw.

Thanks guys,

Matt


- Wanting to shoot my brains out

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 5:41 pm
by Nable
> my constant habit of using int's for everything
So java'ish. Or pythonic. Or C++. Anyway, this is too weird, because type limits (such as unsigned modifier) gives you the way to check your code better but you ignore this obvious nice thing.

Ok, let's move to assembly. I didn't look at your code but here are some related ideas:
although we operate with machine words, there are some things to support signed and unsigned semantics.
For example:

Code: Select all

CONDITIONAL OPERATIONS
----------------------
(NOTE: The values listed for CC are in octal).
 
CC   Condition(s)  Definition       Descriptions
07   A  NBE        !CF && !ZF       x > y   x > 0  (unsigned)
03   AE NB         !CF              x >= y  x >= 0 (unsigned)
02   B  NAE         CF              x < y   x < 0  (unsigned)
06   BE NA          CF || ZF        x <= y  x <= 0 (unsigned)
17   G  NLE         SF == OF && !ZF x > y   x > 0  (signed)
15   GE NL          SF == OF        x >= y  x >= 0 (signed)
14   L  NGE         SF != OF        x < y   x < 0  (signed)
16   LE NG          SF != OF || ZF  x <= y  x <= 0 (signed)
04   E  Z           ZF              x == y  x == 0
05   NE NZ         !ZF              x != y  x != 0
00   O              OF              Overflow (signed overflow)
01   NO            !OF              No overflow (signed overflow)
02   C              CF              Carry (unsigned overflow)
03   NC            !CF              No carry (unsigned overflow)
10   S              SF              (Negative) sign
11   NS            !SF              No (negative) sign
12   P  PE          PF              Parity [even]
13   NP PO         !PF              No parity (parity odd)
So, 'cmp' sets flags in a unified way but then you can interpet
them according to your idea about signedness of operands.

Next thing: there are some operations that have signed variant and unsigned.
For example, compare 'mul' and 'imul' or 'shr' and 'sar' x86 instructions.
So, wrong type can bring you wrong semantics.
Use right type and compiler will (or at least should) emit right instructions.

I hope that you can find some sense in my late-night message.

Upd: you've changed your message very much while I was typing.
Ok, look at the table above and at your code:

Code: Select all

jl .bad
jl - this is signed interpetation of comparison results! Use appropriate condition code with unsigned interpetation.
Another way to express the same idea: EAX and values in it is not the thing that is signed, signed is your intepretation of operations above the data.

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 5:50 pm
by PearOs
Nable wrote:> my constant habit of using int's for everything
So java'ish. Or pythonic. Or C++. Anyway, this is too weird, because type limits (such as unsigned modifier) gives you the way to check your code better but you ignore this obvious nice thing.

Ok, let's move to assembly. I didn't look at your code but here are some related ideas:
although we operate with machine words, there are some things to support signed and unsigned semantics.
For example:

Code: Select all

CONDITIONAL OPERATIONS
----------------------
(NOTE: The values listed for CC are in octal).
 
CC   Condition(s)  Definition       Descriptions
07   A  NBE        !CF && !ZF       x > y   x > 0  (unsigned)
03   AE NB         !CF              x >= y  x >= 0 (unsigned)
02   B  NAE         CF              x < y   x < 0  (unsigned)
06   BE NA          CF || ZF        x <= y  x <= 0 (unsigned)
17   G  NLE         SF == OF && !ZF x > y   x > 0  (signed)
15   GE NL          SF == OF        x >= y  x >= 0 (signed)
14   L  NGE         SF != OF        x < y   x < 0  (signed)
16   LE NG          SF != OF || ZF  x <= y  x <= 0 (signed)
04   E  Z           ZF              x == y  x == 0
05   NE NZ         !ZF              x != y  x != 0
00   O              OF              Overflow (signed overflow)
01   NO            !OF              No overflow (signed overflow)
02   C              CF              Carry (unsigned overflow)
03   NC            !CF              No carry (unsigned overflow)
10   S              SF              (Negative) sign
11   NS            !SF              No (negative) sign
12   P  PE          PF              Parity [even]
13   NP PO         !PF              No parity (parity odd)
So, 'cmp' sets flags in a unified way but then you can interpet
them according to your idea about signedness of operands.

Next thing: there are some operations that have signed variant and unsigned.
For example, compare 'mul' and 'imul' or 'shr' and 'sar' x86 instructions.
So, wrong type can bring you wrong semantics.
Use right type and compiler will (or at least should) emit right instructions.

I hope that you can find some sense in my late-night message.

Upd: you've changed your message very much while I was typing.
Ok, look at the table above and at your code:

Code: Select all

jl .bad
jl - this is signed interpetation of comparison results! Use appropriate condition code with unsigned interpetation.
Another way to express the same idea: EAX and values in it is not the thing that is signed, signed is your intepretation of operations above the data.
Ha! I'm an idiot. Thank you so much for your reply. When I was learning x86 assembly I guess I never thought to learn about the other comparison values. Now I think I know how to make this work. Thanks a ton, Matt

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 6:03 pm
by Nable
Ok, that's so nice.

Btw, (although that becomes looking like a shameless advertisment) here's my favorite x86 (80486, strictly speaking) opcode guide: ftp://mipt.cc/Opcode.txt
Yes, it's old and idea of octal opcode structure is not completely true for x86-64 but I think that this guide is written in a very nice way and it describes enough basic ideas (to do complex things, one should understand basic ones, am I right?) for a starter.
I hope that it'll help you (I also hope that I don't violate anything, when I distribute such materials).

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 9:17 pm
by PearOs
Nable wrote:Ok, that's so nice.

Btw, (although that becomes looking like a shameless advertisment) here's my favorite x86 (80486, strictly speaking) opcode guide: ftp://mipt.cc/Opcode.txt
Yes, it's old and idea of octal opcode structure is not completely true for x86-64 but I think that this guide is written in a very nice way and it describes enough basic ideas (to do complex things, one should understand basic ones, am I right?) for a starter.
I hope that it'll help you (I also hope that I don't violate anything, when I distribute such materials).
You should be fine. Thanks for that link. Ok so after some further testing I was able to figure a problem out that is the cause
for my issues now that I implemented uint support.

Look at this code:

mov eax, 2830106624
mov ebx, 1000000000
cdq
div ebx
jmp $

Everything looks fine. Div is used for unsigned division. Well both the values up there are not signed. Yet that code crashes the CPU. Now if you do IDiv, it runs just fine. Why is this? I don't understand what is wrong. Div should have worked because they weren't signed.

Thanks, Matt

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 9:38 pm
by Octocontrabass
It probably crashes because of whatever value you have in edx. Both div and idiv use edx as the high 32 bits of the dividend, and eax as the low 32 bits.

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 9:40 pm
by PearOs
Octocontrabass wrote:It probably crashes because of whatever value you have in edx. Both div and idiv use edx as the high 32 bits of the dividend, and eax as the low 32 bits.
cdq clears out edx. So I don't think that's it.

Edit: cdq does not work so never use that. Lol xor edx, edx works. Wow can't believe it was that simple.

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 10:04 pm
by Octocontrabass
Well, cdq would be correct if you were doing signed division.

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Fri Nov 29, 2013 10:35 pm
by PearOs
Octocontrabass wrote:Well, cdq would be correct if you were doing signed division.
Oh, I see. Thanks, Matt

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Sat Nov 30, 2013 2:32 am
by bluemoon
PearOs wrote:Take that x86 Assembly for example, the value put into eax is a unsigned number.
No, there is no sign concept for register. Assembler would only check if the constant would fit into the register (it warn if you put 0x100000000 into eax).
The sign form logically from the operations (e.g. cmp + jb vs cmp + jl)

Re: Uint and Int issue in x86 Assembly on a 64bit Computer?

Posted: Sat Nov 30, 2013 3:20 am
by bwat
As others have pointed out, microprocessors don't deal with numbers, they deal with representations of numbers, and different instructions will interpret these representations differently. Also, division is always the most interesting operation.