We're looking for your comments on how to best organize the wiki's content.
Subroutine
A subroutine or a procedure is a section of code that performs operations that can be executed multiple times. During a program's execution, if a specialized operation is needed, such as an advanced trigonometric function, the program can jump to the code, perform the function, and then return back to its original position with the result stored in a register. Effective use of subroutines is a staple for most nontrivial application programs.
Contents |
[edit] What Makes a Good Subroutine?
Any function that takes an input and gives an output has the potential to be a useful subroutine. Examples include:
- Cosine: Input, A in degrees
Output, cos(a) in register A. - Distance: Input, two points A,B and X,Y
Output, euclidean distance in register A. - Cross-Product: Input, two vectors A,B and X,Y
Output, the cross product vector in registers A,B. - Print String: Input, the address of the beginning of an ASCII string in memory
Output, that string to the terminal.
Because the subroutine is always called from the same piece of code, it will be easier to change or correct its functionality, compared to a function that is rewritten every time it is used. Subroutines also shorten the length of your code, and they can be shared between other programs. Large collections of useful subroutines are called libraries.
[edit] How to Use Them
A subroutine is called by pushing the current value of the program counter (PC) to the stack, and then setting the PC to the address of the subroutine.
Subroutines in DCPU-16 are called with the JSR opcode. For example, if the user wanted to calculate the distance between the two points 8,10 and 4,7:
SET A, 8 ; The first point. SET B, 10 SET X, 4 ; The second point. SET Y, 7 JSR distance ; This pushes the current location to the stack ; and begins executing the distance subroutine. ; At this point, A will be equal to the distance between those two points.
[edit] Designing Subroutines
Every subroutine should exhibit two important properties:
- It should not assume anything about the state of the machine. The only values it should use are those provided to it as input.
- When the subroutine ends, the machine should be in the exact same state as when it started, except for the return value(s).
A subroutine with these properties is considered reentrant code, which means that it is safe to call this subroutine within other subroutines. While the first property is easy to achieve, the second is trickier, but is made possible by effectively utilizing the stack.
When designing your subroutine, decide how many registers you will need to use to complete the operation - in this instance X, Y, and Z will be used. Push the required registers to the stack.
SET PUSH, X SET PUSH, Y SET PUSH, Z
The only registers you can change are the ones that were pushed to the stack and the registers that will hold the return values. After the subroutine has finished, pop the values from the stack in the reverse order, and then pop the program counter to restore the program to its previous state.
SET Z, POP SET Y, POP SET X, POP SET PC, POP
If the stack is popped in an incorrect order, it is called stack corruption, which will lead to undesirable side effects in the rest of the program.
[edit] Recursive Subroutine
A recursive subroutine is a subroutine that calls itself. The following function generates a Fibonacci sequence recursively.
; Fibonacci Subroutine ; Input: A ; Output: The Ath fibonacci number in register A :fibo SET PUSH, Y ; Push our working variables to the stack. SET PUSH, Z IFB A, 0xfffe ; The base case - if A = 1 or 0, return A. SET PC, reccase ; Otherwise, return fibo(A-1) + fibo(A-2) SET PC, endfibo :reccase ; The recursive case. SUB A, 1 SET Z, A JSR fibo ; Calculate fibo(A-1) SET Y, A ; Save it in Y SET A, Z SUB A, 1 JSR fibo ; Calculate fibo(A-2) ADD A, Y ; Set A = fibo(A-2) + Y (fibo(A-1)) :endfibo SET Z, POP ; Restore the registers we saved. SET Y, POP SET PC, POP ; And return to where we left off!
Try this with A = 12. Use a launcher such as
SET A, 12 JSR fibo :end SET PC, end
[edit] See Also
| ||||||||

