What is the best way to create/call procedures? Which argument-passing-styles are available?
Thanks in advance,
Jules
What is the best way to create/call procedures? Which argument-passing-styles are available?
Thanks in advance,
Jules
A few practical clarifications and a recommended pattern for a stack-based language, tying into points from and .
Don’t implement a runtime that scans down the data stack for a return marker on every return. That is fragile, O(n) per return, and breaks easily when locals or temporaries get pushed. Instead choose one of two well-tested models: (A) single data stack with explicit stack frames, or (B) separate return stack for control data (Forth style). Both avoid scanning and make return addresses appear at known offsets.
A simple, robust frame convention (common on VMs) looks like this in words: caller pushes arguments; call pushes the return address; callee saves the previous frame pointer, sets the frame pointer to the current stack top, then reserves space for locals by adjusting the stack pointer. The callee accesses args/locals via fixed offsets from the frame pointer. On return the callee restores the frame pointer, restores the stack pointer (freeing locals) and executes ret which consumes the stored return address and jumps. This gives constant-time returns and clear rules for caller vs callee cleanup, and it also makes GC and exception handlers easier because frames are well-formed and addressable.
Two-stack approach: valid and often faster for tiny VMs (use a protected return stack for return addresses and loop counters). The return stack must be disciplined: only control-flow ops can touch it, it needs its own overflow checks, and it complicates first-class continuations. Tagging entries (mark bits) is workable for dynamic typing or GC, but costs space and bit-twiddling and is unnecessary if frames/return-stack separate control and data.
Practical tips: pick caller- or callee-cleanup and be consistent; define which registers (if any) are caller-saved vs callee-saved; always check for stack overflow on push/call; if you need continuations/closures move frames to the heap or provide a stack-capture mechanism; implement a tail-call form to avoid growth on tail recursion. These choices trade safety, simplicity, and performance—choose the one that matches expected language features.
Jump to Post— Narue 5,707>Which argument-passing-styles are available?
Um, all of them.>What is the best way to create/call procedures?
It depends on your needs. It could be as simple as a jmp there and back to a full call/ret pair with a stack frame and all of the glitz and glitter that …
>Which argument-passing-styles are available?
Um, all of them.
>What is the best way to create/call procedures?
It depends on your needs. It could be as simple as a jmp there and back to a full call/ret pair with a stack frame and all of the glitz and glitter that high level languages provide.
What are you trying to do?
I'm trying to find out what the best method is for a stack based language. I have a book about assebly that says that the best way is to save registers on the stack, call procedure, and when it's done, pop the registers back. I don't think this is good for me because most data isn't in the registers, but on the stack.
I thought about the "marking return addresses" method you said in the other post, but I don't what's the best way to do it.
For example if the stack is:
bottom => top
data:6 addr:234 data:3
And we're at the end of a procedure, should I move down the stack pointer until there is an address (so skip data:3, and move to addr:234), and jmp? Then the data above needs to be restored so the stack should look like this now:
data:6 data:3
(the addr:234 should be taken out)
I don't know if this is a good/natural way to do it because it looks really ugly.
Also, I assume that you meant that I reserve the first bit of everything on the stack to indicate if this is an addr or data. (so 1 means addr and 0 means data for example).
Thats the assembly language game, keeping track of what is on the stack and where it is. Oh yea, the stack is only so big. No stack overflows allowed or you are in trouble.
Narue said that I should mark the address of return values on the stack. I'm not sure if this is a good way, but couldn't I just use 2 stacks, and change the stack pointer to switch to the other stack? (I would need to store the other stack pointer in an other register then). Or this it better to mark the values? (eg, set the first bit to 0 if it is a return address, set it to 1 if it is a value/pointer).
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.