The CALL opcode transfers CPU execution to a function address while saving the current address on a stack for RETURN. In CPU RIA/3, CALL uses the form 0x2nnn, where nnn identifies the function in memory. section 5.7.4
A CALL operation follows this sequence:
- Store the current execution address at the stack pointer. section 5.7.4
- Increment the stack pointer. section 5.7.4
- Set the CPU's memory position to nnn, beginning the function. section 5.7.4
- Let RETURN decrement the stack pointer and resume at the saved address. section 5.7.4
Calling a small function
A function stored at 0x100 can contain 0x8014, 0x8014, and 0x00EE: two addition operations followed by RETURN. Loading these bytes into RAM lets CALL enter the function and RETURN resume the caller. section 5.7.4
Listing 5.28 Adding the call() and ret() methods
41 fn call(&mut self, addr: u16) {
42 let sp = self.stack_pointer;
43 let stack = &mut self.stack;
44
45 if sp > stack.len() {
46 panic!("Stack overflow!")
47 }
48
49 stack[sp] = self.position_in_memory as u16; #1
50 self.stack_pointer += 1; #2
51 self.position_in_memory = addr as usize; #3
52 }
53
54 fn ret(&mut self) {
55 if self.stack_pointer == 0 {
56 panic!("Stack underflow");
57 }
58
59 self.stack_pointer -= 1;
60 let call_addr = self.stack[self.stack_pointer]; #4
61 self.position_in_memory = call_addr as usize; #4
62 }
Inspect the Rust call() and ret() methods, including stack-overflow and stack-underflow checks. section 5.7.4
