===================================================== LMC Sample Program #7 - subroutine call/return and linkage ===================================================== - Ian! D. Allen - idallen@idallen.ca - www.idallen.com ============================================================================= 7A: LMC Subroutine CALL/return Example -------------------------------------- Let's write a program that reads numbers from the input and outputs the double and quadruple of each number. The program will stop when it reads the input number 000. We will code this as two separate source files: a MAIN program and a Double subroutine that takes one input argument and returns the double of the number in the LMC Calculator. We choose to pass our argument to the subroutine by using a memory location to store it. (Real-world subroutine linkage usually puts arguments on the stack or in registers.) The return value from the subroutine is placed in the LMC calculator. The input argument is not modified. Here is the pseudocode for the two modules: // MAIN program loop { input num if ( num == 000 ) break doub = Double(num) output doub quad = Double(doub) output quad } stop // Double subroutine subroutine Double(arg) { return arg+arg } ; main program LOOP IN ; input num STO NUM LDA NUM ; if ( num == 000 ) break SUB ZERO SKNZ ; skip *into* loop body if NUM is not zero JMP BREAK LDA NUM ; doub = Double(num) STO ARG CALL DOUBLE STO DOUB LDA DOUB ; output doub OUT LDA DOUB ; quad = Double(doub) STO ARG CALL DOUBLE STO QUAD LDA QUAD ; output quad OUT JMP LOOP BREAK HLT NUM DAT ; variable DOUB DAT ; variable QUAD DAT ; variable ZERO DAT 000 ; constant ; Double subroutine ; ARG - input argument ; returns double the input using LMC Calculator ARG DAT ; input argument must be stored here first RETURN DAT ; space for CALL return value DOUBLE LDA ARG ; return arg+arg ADD ARG JMP RETURN In machine code: 00 500 : LOOP IN ; input num 01 220 : STO NUM 02 120 : LDA NUM ; if ( num == 000 ) break 03 423 : SUB ZERO 04 803 : SKNZ ; skip *into* loop body if NUM is not zero 05 919 : JMP BREAK 06 120 : LDA NUM ; doub = Double(num) 07 224 : STO ARG 08 026 : CALL DOUBLE 09 221 : STO DOUB 10 121 : LDA DOUB ; output doub 11 600 : OUT 12 121 : LDA DOUB ; quad = Double(doub) 13 224 : STO ARG 14 026 : CALL DOUBLE 15 222 : STO QUAD 16 122 : LDA QUAD ; output quad 17 600 : OUT 18 900 : JMP LOOP 19 700 : BREAK HLT 20 000 : NUM DAT ; variable 21 000 : DOUB DAT ; variable 22 000 : QUAD DAT ; variable 23 000 : ZERO DAT 000 ; constant 24 000 : ARG DAT ; input argument must be stored here first 25 000 : RETURN DAT ; space for CALL return value 26 124 : DOUBLE LDA ARG ; return arg+arg 27 324 : ADD ARG 28 925 : JMP RETURN ============================================================================= 7B: LMC Subroutine call-return argument Example ----------------------------------------------- This is the same basic algorithm as the previous example, but instead of returning the value in the LMC calculator, the subroutine argument is a call-return argument that is itself modified to contain the return value: // MAIN program loop { input num if ( num == 000 ) break Double(num) // call-return argument is modified by subroutine output num Double(num) // call-return argument is modified by subroutine output num } stop // Double subroutine with call-return argument subroutine Double(CALLRETURN arg) { arg = arg+arg // call-return argument is itself modified } ; main program LOOP IN ; input num STO NUM LDA NUM ; if ( num == 000 ) break SUB ZERO SKNZ ; skip *into* loop body if NUM is not zero JMP BREAK LDA NUM ; Double(num) *** num is a call-return argument *** STO ARG CALL DOUBLE LDA ARG ; *** pick up modified call-return argument *** STO NUM LDA NUM ; output num OUT LDA NUM ; Double(num) STO ARG CALL DOUBLE LDA ARG ; pick up modified call-return argument STO NUM LDA NUM ; output num OUT JMP LOOP BREAK HLT NUM DAT ; variable ZERO DAT 000 ; constant ; Double subroutine ; ARG - input and output argument (call-return parameter) ; returns double the input by modifying the input argument ARG DAT ; input/output argument must be stored here first RETURN DAT ; space for CALL return value DOUBLE LDA ARG ; arg = arg+arg ADD ARG STO ARG ; subroutine modifies input argument with answer JMP RETURN In machine code: 00 500 : LOOP IN ; input num 01 222 : STO NUM 02 122 : LDA NUM ; if ( num == 000 ) break 03 423 : SUB ZERO 04 803 : SKNZ ; skip *into* loop body if NUM is not zero 05 921 : JMP BREAK 06 122 : LDA NUM ; Double(num) *** num is a call-return argument *** 07 224 : STO ARG 08 026 : CALL DOUBLE 09 124 : LDA ARG ; *** pick up modified call-return argument *** 10 222 : STO NUM 11 122 : LDA NUM ; output num 12 600 : OUT 13 122 : LDA NUM ; Double(num) 14 224 : STO ARG 15 026 : CALL DOUBLE 16 124 : LDA ARG ; pick up modified call-return argument 17 222 : STO NUM 18 122 : LDA NUM ; output num 19 600 : OUT 20 900 : JMP LOOP 21 700 : BREAK HLT 22 000 : NUM DAT ; variable 23 000 : ZERO DAT 000 ; constant 24 000 : ARG DAT ; input/output argument must be stored here first 25 000 : RETURN DAT ; space for CALL return value 26 124 : DOUBLE LDA ARG ; arg = arg+arg 27 324 : ADD ARG 28 224 : STO ARG ; subroutine modifies input argument with answer 29 925 : JMP RETURN -- | Ian! D. Allen - idallen@idallen.ca - Ottawa, Ontario, Canada | Home Page: http://idallen.com/ Contact Improv: http://contactimprov.ca/ | College professor (Free/Libre GNU+Linux) at: http://teaching.idallen.com/ | Defend digital freedom: http://eff.org/ and have fun: http://fools.ca/