Last time I discussed why it is that we have all the .NET compilers target an "intermediate language", or "IL", and then have jitters that translate IL to machine code: because doing so ultimately reduces the costs of building a multi-language, multi-hardware platform. Today I want to talk a bit about why IL is the way it is; specifically, why is it a "stack machine"? To begin with, what is a "stack machine"? Let's consider how you might design a machine language that could describe the operation of adding together two integers to make a third. You could do it like this: add [address of first addend], [address of second addend], [address of sum]
When the machine encounters this instruction it looks up the values of the addends stored in the two addresses, somehow adds them together -- how it does so is its business -- and stores the result in the third address. You might instead say that there is a special region of memory called the "accumulator" which knows how to add a given value to itself:clear_accumulator
increase_accumulator [address of first addend]
increase_accumulator [address of second addend]
save_accumulator [address of sum]
Or, you could say that there is a special region of memory called the "stack" which can grow and shrink; you get access to the items on the top: push_value_at [address of first addend]
push_value_at [address of second addend]
add
pop_value_into [address of sum]
The "add" instruction takes the two values off the top of the stack, somehow adds them, and then puts the result back on the stack; the net result is that the stack shrinks by one. A virtual machine where most of the instructions are of this third form is called a "stack machine", for obvious reasons.IL specifies a stack machine, just like many other virtual machines. But most hardware instruction sets actually more closely resemble the second form: registers are just fancy accumulators. Why then are so many virtual machines specifying stack machines?
Read more: Fabulous Adventures In Coding
QR:
When the machine encounters this instruction it looks up the values of the addends stored in the two addresses, somehow adds them together -- how it does so is its business -- and stores the result in the third address. You might instead say that there is a special region of memory called the "accumulator" which knows how to add a given value to itself:clear_accumulator
increase_accumulator [address of first addend]
increase_accumulator [address of second addend]
save_accumulator [address of sum]
Or, you could say that there is a special region of memory called the "stack" which can grow and shrink; you get access to the items on the top: push_value_at [address of first addend]
push_value_at [address of second addend]
add
pop_value_into [address of sum]
The "add" instruction takes the two values off the top of the stack, somehow adds them, and then puts the result back on the stack; the net result is that the stack shrinks by one. A virtual machine where most of the instructions are of this third form is called a "stack machine", for obvious reasons.IL specifies a stack machine, just like many other virtual machines. But most hardware instruction sets actually more closely resemble the second form: registers are just fancy accumulators. Why then are so many virtual machines specifying stack machines?
Read more: Fabulous Adventures In Coding
QR: