Page 1 of 1

Question about Hex

Posted: Mon May 14, 2018 1:20 pm
by DefenderL
Hey OSDev!

For a long time now I am reading about Kernel Development and i got it really well in my brain...
But what I can't understand right is what actually 0xffffffff80000000 or/and 0xC000000... really mean...
Well, they're offsets in the RAM, aren't they? If so, from where we know it?

Do people look up what 0xffffffff80000000 and 0xC0000 and so on mean on a provided information table or
how do you know that 0xC000.. is now at above/at 3GB????

An clear answer could really help me out alot :)

Greetings,
DefenderL

Re: Question about Hex

Posted: Mon May 14, 2018 9:12 pm
by StudlyCaps
If you are asking what hex is:
So hexadecimal is actually just another way of writing numbers. Regular numbers are decimal from the latin decimus meaning tenth. This means there are 10 different digits, 1 - 9 and 0. Hexadecimal is hex (six) and decimus (ten) or 16, there are 16 hexadecimal digits 1 - 9, 0 and A - F. A - F in hex represent the numbers 10 through 15 in decimal. If you remember your basic math, when we write numbers each digit in a number represents a power of 10. 123 is 1 x 100 or 1x10^2 plus 2 x 10 or 2x10^1 plus 3 x 1 or 3x10^0 (any number to a power of 0 = 1). So bringing it all around, a hex number is the same, except every place represents a power of 16 so 0xABC can be broken down into A in the 16^2 column, B in the 16^1 column and C in the 16^0 column, A is 10, B is 11 and C is 12 so we have 10x16^2 + 11x16^1 + 12x16^0 = 2748 = 0xABC (the "0x" just means that the number is a hex number sometimes it can be written with a 'h' at the end instead like "ABCh"). Often in computer engineering, we use hex instead of decimal to represent numbers. There are a number of reasons for this.
So! The simple answer to your question is 0xffffffff80000000 = 18446744071562067968 and 0xC000000 = 201326592.

If you already know what hex is, the answer to the rest of the question starts here:
The above, I think, doesn't fully answer the question. There are many hex numbers, where the numerical value is not as important as their binary value. In this case, it is more important to understand that 0xF, converted to binary, is 1111, all ones, or the largest number that can fit into 4 bits. Extrapolate, and you have 0xFF, the largest 8 bit integer and 0xFFFFFFFF the largest 32 bit integer! The cool thing is, no matter what the number is, the binary representation has exactly 4 bits for every hex digit, so to convert any sized number between binary and hex, you can just do it one digit at a time. This is important later!

Code: Select all

Binary |1011|0110|1001|
Hex    | B  | 6  | 9  |
So lets talk about higher half kernels, first what it is. The size of the virtual memory which a system can access is limited by the width of an address. For a 32 bit processor it's 32 bit, so all addresses that can ever possibly be used are between 0 and 0xFFFFFFFF (biggest 32-bit number). Now, the kernel of an OS must have it's data and code partitioned off from the data and code of user applications, for a number of reasons the usual way to do that is to say that the space from 0 to some offset is all user space, and from that offset to the end of virtual memory is all reserved for the kernel, and a user should assume that they can never use it. The most naive way to do this is a flat halving, from 0 to the half way point is user space, from the half way to the end is the kernel, hence the kernel is in the higher half.
So lets say I have a 32 bit address space and I want to quickly work out where the halfway mark is, well every address is a 32 bit binary number, from 0000 ... 0000 to 1111 .... 1111. Logically, if you take any 32 bit binary sequence starting with a 0, you can swap the starting 0 to a 1 and make a single, different, 32 bit number. This means that exactly half the possible 32 bit numbers start with 1 and half with 0. We can see simply that all numbers starting with a 1 are higher than all numbers of the same length starting with 0, so the midway point must be the binary number 1 followed by 31 0's. We can then very simply convert it to hex.
We know the hex number is a mystery digit representing 1000b, then 7 0's

Code: Select all

Binary |1000|0000|0000|0000|0000|0000|0000|0000|
Hex    | ?  | 0  | 0  | 0  | 0  | 0  | 0  | 0  |
All we need to do then is figure out what 1000b is, (1x2^3+0+0+0 = 1x8+0 = 8) so if I were to see 0x80000000 I would almost instantly understand it is the start of the second (higher) half of the set of possible 32 bit numbers. I know this almost as second nature, because I have been working with computers for a long time.

So how does this all fit together? Well when I see 0xC0000000 what I know is that it has 8 digits, so it's a 32 bit number,
the first 4 bits are unknown, and the rest are all 0's. I'll skip working it out, but 0xC = 1100b. That means it has two leading 1's. We know one leading 1 is the halfway point, well, lets say we ignore the leading 1, then we have another 31 bit binary number, also with a leading 1, followed by 0s. What does this mean? Well it means we are in the higher half of the higher half! The highest quarter of the address space. Basically to give user applications more space, it is more common to put higher half kernels well above the actual halfway mark in a 32 bit address space in this case you have 3/4s of the space for users, and 1/4th for the kernel. So if we know that a 32-bit address space gives us 4GiB of address space, we can then reason that 3GiB is for users.

Now, 0xFFFFFFFF80000000 is a 64 bit number, and you may well say, there are lots of digits before the trailing 0s! What the heck is this supposed to represent?! Well let's see, we have a 64 bit number, it starts with 8 Fs though, we know that 0xF = 1111b so we have 32 bits worth of binary 1s, the 8 (as we know already, 0x8 is 1000) gives us one final 1, then all 0s. So if we apply the same logic as before we're right at the top of a 64 bit address space with all leading 1's, but a 1 and 31 0's in the less significant 32 places gives us the mid point of a 32 bit number, in address space terms then, this is the start of the highest 2GiB, in a 64 bit address space.

This is a lot of text, but hopefully, it helps you to develop an intuition for the meaning of hexadecimal addresses.

Re: Question about Hex

Posted: Tue May 15, 2018 9:18 am
by DefenderL
This is an awesome clarification!
I appreciate it a lot, thanks for sharing your knowledge :)
Much respect for that text!

I began writing my own 64-Bit Kernel a few weeks ago and
those hexdecimal addresses really burned my head...
Finally someone brought light into this dark chapter :mrgreen:

Thank you! :)

Re: Question about Hex

Posted: Tue May 15, 2018 9:52 pm
by StudlyCaps
Glad to help! Hex is one of those things where that's fairly simple to learn, but challenging to really get to grips with. I think a good analogy is that knowing long division is great, but in practice recognising the patterns in numbers that lets you know, for example, 2500 is half of 5000 is far more useful.