At the lowest programming level, you encounter machine code. This is the language of the processor itself. Machine code directs the processor to do things, such as read from or write to memory, store data, perform math, and other tasks. And if you dare to program a processor directly, you’ll encounter something called the stack pointer register.
In Figure 1, you see the Code::Blocks debugger showing the processor’s register dump. The Registers are storage areas in the processor; the values stored in each register are shown in the Hex and Integer columns.
Most of the registers store data or reference locations in memory. All-in-all, I find processor programming fascinating, but it’s all terribly trivial these days.
Of note for this Lesson, register esp
is the stack pointer register (The e
means that it’s 32-bits wide.) The register holds the memory location of the top of the stack.
Register ebp
is the base pointer register. It references the bottom or start of the stack.
As the processor churns through machine code, the various registers are manipulated. The stack pointer is also manipulated, but only under certain conditions.
For example, a push instruction sets a value onto the stack, either directly or the value stored in a register. The value is copied to the stack pointer’s memory location, then the stack pointer is incremented. Figure 2 illustrates this process.
A pop instruction removes a value from the stack. The value stored at the stack pointer’s location is transferred into a named register (typically eax
, known as the accumulator) and the stack pointer is decremented. Figure 3 illustrates this concept.
Stack storage is used in several ways. To directly manipulate the stack, you can use the Assembly language push and pop instructions. In the following chunk of Assembly code, the contents of register eax
and swapped with register ebx
:
push eax ;save register value on the stack
push ebx
pop eax ;put ebx into eax
pop ebx ;put eax into ebx
This operation succeeds because the last item sent (pushed) to the stack is the first item popped out — that’s LIFO or last-in, first-out. The result is that the register’s values are exchanged. And this operation is necessary because Assembly language lacks an assignment operator. (And even if the processor’s instruction set features a swap or similar instruction, using push-pop works faster.)
The other way the stack is used is for Assembly call and ret (return) instructions, which has direct application in C and other programming languages. I’ll cover more on this topic in next week’s Lesson.