//Shows math operations, some stack usage, and subprocedure call define_procedure sum_of_3 contract { I promise to pop 4 elements (three numbers to sum, return address) and push 1 element (their sum) on the stack I promise to preserve the value of all registers except: registers[0], registers[1], registers[2] } body { //Get the arguments (except the return address) registers[2] = stack.pop() (as number_to_sum_3) registers[1] = stack.pop() (as number_to_sum_2) registers[0] = stack.pop() (as number_to_sum_1) //Add the first two numbers: //Push the first two numbers to the stack stack.push(registers[0]) (as number_to_add_1) stack.push(registers[1]) (as number_to_add_2) //Process the two numbers on top of the stack add //Get the added value from the top of the stack registers[0] = stack.pop() (as sum_of_first_two) //Add the third number to the intermediate sum: //Push the first two numbers to the stack stack.push(registers[0]) (as sum_of_first_two) stack.push(registers[2]) (as number_to_add_3) //Process the two numbers on top of the stack add //Get the added value from the top of the stack registers[0] = stack.pop() (as total_sum) //Get the return address send by the caller procedure registers[1] = stack.pop() (as return_address) //Push the sum to the stack, as promised by our contract stack.push(registers[0]) (as sum) //Jump to the return address the caller requested us to return to jump to registers[1] } define_procedure average_of_3 contract { I promise to pop 4 elements (three numbers to average, return address) and push 1 element (their average) on the stack I promise to preserve the value of all registers except: registers[0], registers[1], registers[2] } body { //Get the arguments (except the return address) registers[2] = stack.pop() (as number_to_average_3) registers[1] = stack.pop() (as number_to_average_2) registers[0] = stack.pop() (as number_to_average_1) //Sum the numbers using a subroutine: //Prepare the return address the subroutine should come back to after it's done: stack.push(#.after_summing_jump_here.lineNumber) (as address_to_return_to_after_procedure_call) //Prepare the arguments (the numbers to sum) for the subroutine stack.push(registers[0]) (as number_to_sum_1) stack.push(registers[1]) (as number_to_sum_2) stack.push(registers[2]) (as number_to_sum_3) //Jump to the subroutine jump to #sum_of_3.lineNumber #LABEL: .after_summing_jump_here //Process the output of the subroutine, which it left for us on the stack registers[0] = stack.pop() (as sum) //Divide the sum by 3 //Push the divident and divisor stack.push(registers[0]) (as sum) stack.push(3) (as diviser) //Process the two numbers at the top of the stack divide //Get the divided value registers[0] = stack.pop() (as average) //Get the return address send by the caller procedure registers[1] = stack.pop() (as return_address) //Push the sum to the stack, as promised by our contract stack.push(registers[0]) (as average) //Jump to the return address the caller requested us to return to jump to registers[1] } define_procedure main body { #LABEL: .loopStart input input input registers[2] = stack.pop() (as number_to_average_3) registers[1] = stack.pop() (as number_to_average_2) registers[0] = stack.pop() (as number_to_average_1) //Average the numbers using a subroutine: //Prepare the return address the subroutine should come back to after it's done: stack.push(#.after_averaging_jump_here.lineNumber) (as address_to_return_to_after_procedure_call) //Prepare the arguments (the numbers to average) for the subroutine stack.push(registers[0]) (as number_to_average_1) stack.push(registers[1]) (as number_to_average_2) stack.push(registers[2]) (as number_to_average_3) //Jump to the subroutine jump to #average_of_3.lineNumber #LABEL: .after_averaging_jump_here //Process the output of the subroutine, which it left for us on the stack registers[0] = stack.pop() (as average) //Print the output print registers[0] (as average_of_3) jump to #.loopStart.lineNumber //Or alternatively, jump to #main.lineNumber }
Run