Page 1 of 2
AMD64 sizeof(long) = 4? WTF?
Posted: Fri Apr 11, 2008 10:23 pm
by zerosum
Hi all,
Earlier I'd written a some code for i386. It wasn't so portable.
Now I'm trying to fix it up to work with x86-64 and I'm encountering a strange problem.
Should the size of a long not be 64-bits on amd64?
At the moment, I'm testing for the sign bit by bit-shifting 1<<63 (not portable, I know). g++ is telling me that the left shift is greater than the width of the type, which is a typedef'd long. It only ceases to tell me this when I try to shift only 31 bits, indicating that sizeof(long) = 4 instead of 8.
I've tried changing my typedef's so that my 'ui64' type is a long long instead (which it shouldn't be), but g++ won't compile it saying that the 'long long' type is illegal in ISO C++ 1998.
Further to this, my printf code (which is what I'm trying to port) is borked, even though I don't think it should be, with the changes I have made. I'm trying to printf("Blah %X\n",sizeof(long)) and I'm getting '4F4249544C550020' which is clearly not the sizeof(long).
Anyone got an idea as to what's going on?
Cheers,
Lee
Posted: Fri Apr 11, 2008 10:47 pm
by zerosum
I've just compiled some test code to see what gcc is doing with regard to long's in my 64-bit code. What follows is the c code and the disassembled code:
Code: Select all
4000b0: 55 push %rbp
4000b1: 48 89 e5 mov %rsp,%rbp
4000b4: b8 05 00 00 00 mov $0x5,%eax
4000b9: 48 83 c0 02 add $0x2,%rax
4000bd: c9 leaveq
4000be: c3 retq
Code: Select all
int main(void) {
register long x;
register long y;
x = 5;
y = x + 2;
return(y);
}
As you can see, it's moving 5 into
eax but then adding two to
rax. WTF is with that?
Cheers,
Lee[/code]
Posted: Sat Apr 12, 2008 12:48 am
by thepowersgang
As far as i know the "long" type is defined as a 32bit integer, "int" on the other hand is 32 on a 32bit machine and 64 on a 64bit machine. "long long" is a fixed 64bit integer.
Posted: Sat Apr 12, 2008 12:50 am
by zerosum
That's the opposite of everything I have read and understand. See this page for instance:
http://www.osdev.org/wiki/Long_Mode
I will modify the test code to change them to ints and see what happens.
Cheers,
Lee[/url]
Posted: Sat Apr 12, 2008 1:12 am
by zerosum
Don't mind me, I'm an idiot. Or perhaps gcc is illogical-- who knows? Consider the following code:
Code: Select all
i64 bin;
if (bin & (1<<63))
printf("Negative.\n");
else
printf("Positive.\n");
For some reason, gcc treats the 1<<63 as though it is an
int, which is just wrong as far as I'm concerned. Unless there's an explicit cast, it should treat it as being of the same type as the leftmost operand.
So yes, because it treats (1<<63) as an int, that actually equates to 0.
I've now done the obvious and sizeof(long) IS 8, not 4, it's just because of that strange auto-casting behaviour that that particular code was causing a warning/error.
Cheers,
Lee
Posted: Sat Apr 12, 2008 2:22 am
by Krox
zerosum wrote:As you can see, it's moving 5 into eax but then adding two to rax
Thats easy to explain: As you can read in the AMD64 Docs, whenever you put sth in a 32Bit Regsiter, the CPU will clear the upper 32Bit. Or maybe sign-extend. But anyway, it will be at a know state. So GCC is doing this simply for code-size minimizing.
And for the (bin & (1<<63)): Every literal without suffix is treated as "int", which is 32Bit on AMD64. Use (bin & (1L<<63)) instead. (And turn on all warnings, so GCC tells you about such stuff^^)
Posted: Sat Apr 12, 2008 2:47 am
by zerosum
Fair enough... thanks for clearing that up, Krox
I have -Wall -pedantic, so I saw the warning. I was trying to figure out why... took me a while, because I expected 1<<63 to work out to a long, since that's what the other operand was and I didn't explicitly cast.
Cheers,
Lee
Re: AMD64 sizeof(long) = 4? WTF?
Posted: Sat Apr 12, 2008 2:57 am
by bluecode
zerosum wrote:I've tried changing my typedef's so that my 'ui64' type is a long long instead (which it shouldn't be), but g++ won't compile it saying that the 'long long' type is illegal in ISO C++ 1998.
-Wno-long-long fixes that
Posted: Sat Apr 12, 2008 3:07 am
by zerosum
Thanks, bluecode
They say you learn something new every day, but oh, has today been a fun day.
Finally figured out why my printf function no longer works now that I'm using 64-bit code. I just assumed that all parameters would be passed on the stack, same as on x86
Posted: Sat Apr 12, 2008 6:34 am
by bluecode
zerosum wrote:Finally figured out why my printf function no longer works now that I'm using 64-bit code. I just assumed that all parameters would be passed on the stack, same as on x86
Yea, I also had to learn that the painfull way... you should really use the header provided by gcc. I also looked into the varargs convention for x64 and imho it is pretty unimplementable as a macro, at least far away from fun.
Posted: Mon Apr 14, 2008 1:27 am
by Solar
zerosum wrote:Or perhaps gcc is illogical-- who knows? Consider the following code:
Yes, consider it. Especially the parenthesis telling it to calculate "1 << 63" first.
Posted: Tue Apr 15, 2008 2:30 am
by zerosum
Solar wrote:
Yes, consider it. Especially the parenthesis telling it to calculate "1 << 63" first.
What's your point?
Posted: Tue Apr 15, 2008 3:51 am
by Solar
For some reason, gcc treats the 1<<63 as though it is an int, which is just wrong as far as I'm concerned. Unless there's an explicit cast, it should treat it as being of the same type as the leftmost operand.
1 is an integer literal.
63 is an integer literal.
1 << 63 yields an integer result.
Whatever type "bin" has does not have any effect on this. Why - or how - should it?
Posted: Tue Apr 15, 2008 4:56 am
by zerosum
Ahh, so the point of your post was to simply reiterate what had already been stated by Krox, but in a far more patronising manner. Very good, thanks for your input
Posted: Tue Apr 15, 2008 5:20 am
by Solar
Missed the smiley, apparently. Didn't want to sound patronizing, seldom do. I pointed the finger to the "think-o" in your reasoning, partly due to a slightly allergic reaction to "tool is broken" statements. Yes, the point had been cleared before. No, I didn't really realize that. No, it's not entirely wise to post in threads you haven't read calmly and completely.
Can we retire the flamethrowers?