AMD64 sizeof(long) = 4? WTF?
AMD64 sizeof(long) = 4? WTF?
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
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
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:
As you can see, it's moving 5 into eax but then adding two to rax. WTF is with that?
Cheers,
Lee[/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);
}
Cheers,
Lee[/code]
- thepowersgang
- Member
- Posts: 734
- Joined: Tue Dec 25, 2007 6:03 am
- Libera.chat IRC: thePowersGang
- Location: Perth, Western Australia
- Contact:
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]
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]
Don't mind me, I'm an idiot. Or perhaps gcc is illogical-- who knows? Consider the following code:
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
Code: Select all
i64 bin;
if (bin & (1<<63))
printf("Negative.\n");
else
printf("Positive.\n");
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
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.zerosum wrote:As you can see, it's moving 5 into eax but then adding two to rax
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^^)
21 is only half the truth...
Re: AMD64 sizeof(long) = 4? WTF?
-Wno-long-long fixes thatzerosum 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.
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.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
Yes, consider it. Especially the parenthesis telling it to calculate "1 << 63" first.zerosum wrote:Or perhaps gcc is illogical-- who knows? Consider the following code:
Code: Select all
bin & (1<<63)
Every good solution is obvious once you've found it.
1 is an integer literal.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.
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?
Every good solution is obvious once you've found it.
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?
Can we retire the flamethrowers?
Every good solution is obvious once you've found it.