You and any other sane programmer should know how computer memory works so that's the next topic of this discussion. One of the most important concept in programming is knowing the memory structure and various ways of how it can be accessed, be written to and read from. In modern 32-bit CPUs a memory block contains 32-bits, so in a reset state a block of memory looks something like this:

Binary : 00000000000000000000000000000000
Hexadecimal : 0x00000000h

This is equivalent to a block of 32 memory cells in an â??offâ?? state. The binary is the "raw" representation of the memory cells. As I have explaied a few times already in the previous part of the KTM tutorials, a transistor and a capacitor are paired together to form a memory cell and can either contain an electric charge or not, so this is exactly why all of the data inside a chip or a memory stick stands as a 0 or a 1 and in no other way.

What about Hexadecimals? As you can see on a 32-bit machine the binary number gets too long, so it is more convenient for programmers to learn the hexadecimal (base 16) number system. In this base 16 system, the digits go from 0 to F. The digits that would have been 10 through 16 are substituted by letters A through F to the fact that there are not enough digits in our "native" Decimal (base 10) number system.

As a programmer it is important to understand the hex. In practically all programming software the hex is known to all of the humanity (well, the part that decided to become software programmers) as the common representation of an address in computer memory. Let's take a quick look at a relationship between the binary number and the same representation of it in the hex. Let's take the following binary number as an example:

111100001100111011110110000011010101

This binary number can be split into 8 parts to form a hex number like this:

1111 0000 1100 1110 1111 0110 0000 1101 0101
F 0 C E F 6 0 D 5

So the HEX (hexadecimal, or base-10) representation of this number is

F0CEF60D5

For convenience a 0x (or just an 0, without the x) in front and an H (either small or capital) at the end are added to identify this number as a hex number. So the full number in all of its hexadecimal glory would be written down as: 0xF0CEF60D5h. All of this is done of course for our own convenience only; the computer memory still remains binary in nature.

Protected mode and memory allignment

First, let me mention that theoretically on a 32-bit CPU there are 0x00000000 to 0xFFFFFFFF memory locations that can be directly accessed (in decimal, that means up to four gigabytes of memory). Logically (but not exactly technically as you will see in a moment), the gap between each consequent address is 32 bits. These 32-bit blocks of memory cells can be split logically further into blocks of 16 (a word) and further into blocks of 8 (a byte) bits. So a 32-bit memory block contains 8 bytes or... 2 words. Let me give you a quick review of these terms.

1 bit - a single value containing either 1 or 0
8 bits - a byte
16 bits - a word; two bytes together
32 bits - a double word; two words together
64 bits - a quad word; two double words together

You need to understand that each byte of memory on a memory storage device has its own unique address, even on the 32-bit, 64-bit or other CPU's that process data in a multi-byte fasion. So although you can access 32-bits (4 bytes) at a time on the 32-bit machine, each byte still has its own address. And now I will go on and talk about the memory space where all of these bytes reside.

If you're working in protected mode (under an OS), which is what you are probably doing, some of these memory blocks are "protected" by the operating system and you cannot read from them or write to them, but this isn't important at this point. What important is a 32-bit processor can directly address as many as 4 gigabytes (four billion bytes) in the main memory. The number looks like this 4,294,967,295 (also 0xFFFFFFFFh) -- and that's a lot of bytes to play with.

There are other modes of memory-access presented to you by various processors, and usually a modern CPU can let you play with those modes in the Assembly Language, however those modes can be considered obsolete as the majority of programmers now work in protected mode and are using the C/C++ compiler tools. To a C/C++ programmer of course none of this should matter because the C compiler takes care of the dirty parts and if you're one dirty programmer you don't really have to know this stuff.

However, the terminology of protected mode conflicts with the memory model explanation itself that I'm going to give you in this tutorial, and that is the only reason I mentioned it at all. Let's take a look at a way of how the memory of the entire CPU can be represented.

Pictured above is the Intel's Protected Mode flat model. All of the space between 00000000h and 0FFFFFFFFh is the 4 gigabytes of memory that can be accessed on a 32-bit computer. Usually, programming in a protected mode flat model memory space is associated with an operating system in service within it. I picked this model to explain how memory works because more than likely you're a Windows (or Linux; or both) user and this is what the majority of programmers are programming for today.

In this model, your program cannot "own" all of the space within the 4 Gigs. Why? The operating system must set it up and decide what your program can and cannot use. Due to this fact, some of the memory areas are "protected" and forbidden from accessing them from within your program. The true reasons of why it works that way are OS-specific and are beyond the scope of this tutorial.

In protected mode, you could specify virtually any address in a C-language pointer variable or an Assembly Language register but if you tried to read it or write to it you would get a memory read/write error, all of this is of course if that address was residing in the "protected" by the OS area. When you declare a C variable, an address at which the value of it will reside at is decided by the operating system so you don't really have to worry about accessing a protected part of memory.

Let's find out what's actually going on when you access and retrieve memory from the CPU or elsewhere. Also we will go over the techniques and use of memory pointers. For this purpose I will use the C language, as it is a more appropriate form of explaining this concept, than say the Assembly Language, which would confuse a less skilled programmer. When you declare a variable in C, a memory address is picked for you automatically and regularly all you have to work with is the value stored at that address or the address itself. This is where the concept of pointers comes from. A pointer is simply an address, at which a value in a form of a C variable is stored.

Let's see how a memory pointer can be created and accessed. I am not going to explain all the syntax behind declarations, you should already know that, I will only explain how all of this applies to what I've been describing above.

int iNumber = 10; // the compiler stores the number 10 (or 0x0000000Ah, shorter: 0xAh)
// at an address in memory
int *pAddr = &iNumber; // pAddr points to the address of where 0xAh is located