62 lines
3.3 KiB
Markdown
62 lines
3.3 KiB
Markdown
---
|
|
layout: news
|
|
author: Torsten
|
|
---
|
|
|
|
I was just reading my ruby book, wondering about functions and blocks and the like, as one does when implementing
|
|
a vm. Actually the topic i was struggling with was receivers, the pesty self, when i got the exception.
|
|
|
|
And while they say two setps forward, one step back, this goes the other way around.
|
|
|
|
### One step back
|
|
|
|
As I just learnt assembler, it is the first time i am really considering how functions are implemented, and how the stack is
|
|
used in that. Sure i heard about it, but the details were vague.
|
|
|
|
Off course a function must know where to return to. I mean the memory-address, as this can't very well be fixed at compile
|
|
time. In effect this must be passed to the function. But as programmers we don't want to have to do that all the time and
|
|
so it is passed implicitly.
|
|
|
|
##### The missing link
|
|
|
|
The arm architecture makes this nicely explicit. There, a call is actually called branch with link. This almost rubbed me
|
|
for a while as it struck me as an exceedingly bad name. Until i "got it", that is. The link is the link back, well that
|
|
was simple. But the thing is that the "link" is put into the link register.
|
|
|
|
This never struck me as meaningful, until now. Off course it means that "leaf" functions do not need to touch it. Leaf
|
|
functions are functions that do not call other functions, though they may do syscalls as the kernel restores all registers.
|
|
In other cpu's the return address is pushed on the stack, but in arm you have to do that yourself. Or not and save the
|
|
instruction if you're so inclined.
|
|
|
|
##### The hidden argument
|
|
|
|
But the point here is, that this makes it very explicit. The return address is in effect just another argument. It usually
|
|
gets passed automatically by compiler generated code, but never the less. It is an argument.
|
|
|
|
The "step back" is to make this argument explicit in the vm code. Thus making it's handling, ie passing or saving explicit
|
|
too. And thus having less magic going on, because you can't understand magic (you gotta believe it).
|
|
|
|
### Two steps forward
|
|
|
|
And so the thrust becomes clear i hope. We are talking about exceptions after all.
|
|
|
|
Because to those who have not read the windows calling convention on exception handling or even heard of the dwarf specification thereof, i say don't. It melts the brain.
|
|
You have to be so good at playing computer in your head, it's not healthy.
|
|
|
|
Instead, we make things simple and explicit. An exception is after all just a different way for a function to return.
|
|
So we need an address for it to return too.
|
|
|
|
And as we have just made the normal return address an explicit argument, we just make the exception return address
|
|
and argument too. And presto.
|
|
|
|
Even just the briefest of considerations of how we generate those exception return addresses (landing pads?
|
|
what a strange name), leads to the conclusion that if a function does not do any exception handling, it just passes
|
|
the same addess on, that it got itself. Thus a generated excetion would jump clear over such a function.
|
|
|
|
Since we have now got the exceptions to be normal code (alas with an exceptional name :-)) control flow to and from
|
|
it becomes quite normal too.
|
|
|
|
To summarize each function has now a minimum of three arguments: the self, the return address and the exception address.
|
|
|
|
We have indeed taken a step forward.
|