64-bit type (2xlong)

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Candamir

64-bit type (2xlong)

Post by Candamir »

I'm trying to get a memory map from grub, and there you have two addresses (base_low and base_high) and both are unsigned long. When trying to combine these two, I get the following compiler exception:

Code: Select all

warning: left shift count >= width of type
This is the code:

Code: Select all

       puts("Map entry:\n\tBase address = ");
      puthex((mmap->base_addr_high << 32) ^ mmap->base_addr_low);
      puts(          "\n\tLength      = ");
      puthex((mmap->length_high << 32) ^ mmap->length_low);
      puts(          "\n\tType        = ");
      puthex(mmap->type);
      puts("\n");
I know the output functions are a little bit archaic as I haven't finished my console driver (printf, scanf, basically) ;)

I understand the meaning of the warning, but AFAIK, there isn't any bigger operator than long (?). So is there any easy way round it?
paulbarker

Re:64-bit type (2xlong)

Post by paulbarker »

There's 32 bits in a long, so left or right shifting by 32 bits will always shift you're data completely out of the variable.

You want a 64bit value, for GCC use:

Code: Select all

unsigned long long ll = ((unsigned long long)mmap->base_addr_high) << 32) ^ mmap->base_addr_low)
Notice the typecast to long long before the shift, just to make absolutely sure the compiler knows what we want (I'm usually more pedantic than the compiler).
Candamir

Re:64-bit type (2xlong)

Post by Candamir »

Thanks! BTW, is this also possible for greater sizes? (unsigned long long long long, e.g.) or is it possible to combine it (long int char)?
paulbarker

Re:64-bit type (2xlong)

Post by paulbarker »

64bit values are the largest that GCC supports natively, I think. They're certainly the largest required by the C standard (#include <stdint.h> and use the types int64_t and uint64_t if you can).

On the x86, you'll have problems with integers greater than 64bits since you get 4 core registers of 32bits each. A 128bit value would use all 4 registers (eax-edx). Larger size integers are usually supported by a 'big int' or 'big num' software library, for situations like cryptography where 1024bit (or more) arithmatic is needed.

I don't think the phrase 'int char' will work but I've never tried it. If 'int char' works, I'd assume 'long int char' works.

Lastly, anything ending 'long' or 'short' implicitly has 'int' on the end. 'long' is really just an alias for 'long int', etc.
Rob

Re:64-bit type (2xlong)

Post by Rob »

Is there a reason you are using XOR (^) instead of OR (|) ?
Candamir

Re:64-bit type (2xlong)

Post by Candamir »

Good question. There's no reason at all. Which one would be faster, though?
RetainSoftware

Re:64-bit type (2xlong)

Post by RetainSoftware »

XOR is totally wrong/unclear here, though it might work it should be either OR or an addition of the lo and hi values.

And for the speed requirement. It doesn't matter because the time to execute XOR or OR is nothing compared to the put functions.
Post Reply