Subroutines
Subroutines and methods are the
basic building blocks of larger programs. At the heart of every
subroutine call are two fundamental actions: it has to store the
current location so it can come back to it, and it has to transfer
control to the subroutine. The
bsr
opcode does both. It pushes the address
of the next instruction onto the control stack, and then branches to
a label that marks the subroutine:
print "in main\n" bsr _sub print "and back\n" end _sub: print "in sub\n" ret
At the end of the subroutine, the ret instruction
pops a location back off the control stack and goes there, returning
control to the caller. The jsr opcode pushes the
current location onto the call stack and jumps to a subroutine. Just
like the jump opcode, it takes an
absolute address
in an integer register, so the address has to be calculated first
with the set_addr
opcode:
print "in main\n" set_addr I0, _sub jsr I0 print "and back\n" end _sub: print "in sub\n" ret
Calling Conventions
A bsr or jsr is fine for
a
simple subroutine call, but few subroutines are quite that simple. The biggest issues revolve around register usage. Parrot has 32 registers of each type, and the caller and the subroutine share the same set of registers. How does the subroutine keep from destroying the caller’s values? More importantly, who is responsible for saving and restoring registers? Where are arguments for the subroutine stored? Where are the subroutine’s return values stored? A number of different answers ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access