Aug 12

Reapplying the Decal: Know your materials

Tag: Code, ProgrammingAdam Wright @ 8:00 pm

Now we know how the program exists on your computer, we’ll learn a little bit about how your CPU actually runs the instructions once they’re loaded. As usual, please make sure you’re up to date on the previous articles; It will be very hard to understand if you don’t. Also, if there’s something that’s not clear or you spot a mistake, please leave a comment – I don’t knowingly leave errors in, and would like everyone who’s playing along to get the most out of this series. Finally, note that will be the last “pure theory” article, so we can get back to the interesting Decal specific stuff. Let’s get to it!

Here’s a secret that will make our lives a lot easier. The big instruction list is actually subdivided! Inside the big list is actually lots of little lists, groups of instructions that are stored together. We call these groups “functions”, as they do just one thing. Rather than include each group everywhere it’s used, the compiler will only include the group once. After that, when it needs the “functionality” that the “function” provides, it will tell the CPU to stop executing the big list, and to start executing one of these groups. When the CPU is finished, it will go back to where it was in the list.

This is very useful to us, as the compiler will have created these functions for out of our original objects. We know our program prints “Hello” and “World”, so the odds are good that there are functions specifically for printing “Hello” and “World” inside the list. In fact, there is almost certainly a function for “Printing something”, and then our two functions which use the “Print something” function themselves.

Enough waffle – let’s role-play! Today, we’re going to be CPUs! Let’s set ourselves up with some memory, and then we’ll try and execute an instruction list.

State of memory after execution: Phase 1

I’ve put 3 things inside our memory. Coming first, we guess that “Add” is a function – it’s a list of instructions that can add two numbers together. Remember, as a function, we don’t have to copy “add” into the big list, we can just tell ourselves to execute it and watch what happens! We’ve also got 2 boxes of data – the number “2” and the number “5”. Above each box is the “memory address” of that box. This tells us where in memory that box is stored, and we’ll use it to uniquely identify the box in our instructions.

The scary tower on the right is the “Stack”. This is a sort of temporary memory that we’ll use when we’re executing our program. We can “push” data onto the stack, and it will go into the topmost free slot. We can also “pop” the stack, and the topmost item will come back into our memory.

So, without further ado, let’s run the following assembly “big list”, specially designed for our “Weblog Reader” processor.

push 02
push 03
call 01
pop 02

OK, jot that down on a piece of paper and put your finger on the first line. Your finger is the “execution cursor”. Every time we finish an instruction, move it down a line. Notice how each instruction is very simple, consisting of just one operation and that they take extra information in the form of “parameters” - basically additional information for the instruction to do it’s work. Let’s begin, and it should all become clear!

  1. push 02 – We need to take the box labelled 02, and push it onto the stack. Simple enough, and let’s see what we now look like.

    State of memory after execution: Phase 2

  2. push 03 – Basically the same again, except from a different address. Notice how the stack “builds up” as we push things onto it; it’s like a giant pile of plates!

    State of memory after execution: Phase 3

  3. call 01 – Hmm. We need to “call” the add function. It’s going to take all the data on the stack, add it together, and put the result on the stack for us. Great - We don’t need to do any work ourselves, our function is doing it for us.

    State of memory after execution: Phase 4

  4. pop 02 – Aha! We can now take the result we received from the stack, and put it back into box 02!

    State of memory after execution: Phase 5

Superb. In just 4 instructions, we’ve successfully executed our program, and worked out that 2 + 5 = 7. Our memory now reflects the result, our user is happy, and we’ve shown that Intel and AMD have nothing on us!

Back on earth, we’ve just played the part of a “Stack machine processor”. Using this technique, we can run basically every program we can think of! The slight dampener is that your CPU is not strictly the same, but don’t panic – what we’re dealing with will be close enough to finish our task in part 4, where we’ll make “Hello World” into “World Hello”!

So next time we’ll start by disassembling the helloWorld.exe file into a list of instructions similar to those we just executed. We’ll work out roughly what the instructions in the list do, find the functions and then determine what we need to edit in order to change the output. Then, with one fell swoop, we’ll modify Hello world to do our bidding! Mmmmm, we’re so close, one can almost taste it.

Oh, and because the last “advanced” bonus question was answered by Enolive with almost precognisant alacrity, here’s another: Can you tell me what alternative to stack based processing an x86 CPU uses, and name 2 virtual machines with widespread deployment that are purely stack based (before their code is JITed)?

3 Responses to “Reapplying the Decal: Know your materials”

  1. Adam Wright says:

    Sorry for putting out another long read so shortly after the previous one, but I’m off out this evening and this “memlocs” series has gone on rather longer than I thought. I’ll make up for it with a more easily accessible read after the last part.

  2. Eddie Williams says:

    I would think that register passing is the alternative, but I’m not a great student of x86.

    I know Java is purely stack-based. And your hint leads me to believe that the other answer is Microsoft’s Common Runtime Langugage thing; but that’s a wild guess.

  3. Adam Wright says:

    Yay! Another pretty much perfect answer. I guess my question was a bit ambiguous as x86 is not a register machine in the mathematical sense, but the instruction set design is optimised for register use over a purely stack based approach. As for commonly used stack VM’s, I was indeed hoping to see Sun’s Java and then Microsoft’s CLR.

    I’ll probably write an annex piece about MSIL (the assembly language that the CLR takes) one day, as it makes for a much more easily understood introduction to G1 languages (though I suppose it would be more G1.5).

    I tip my hat sir!

Leave a Reply