Assembly Language Programming 4/28/2015 AVRASSEMBLY PROGRAMMING Procedure Calls Dr. Tim Margush 1 Assembly Language Programming 4/28/2015 PROCEDURE CALLS uint8_t addone (uint8_t X) { uint8_t sum; sum = X + 1; return (sum); } main () { uint8_t var1, var2; var1 = 50; var2 = addone (var1); } Dr. Tim Margush 2 2 Assembly Language Programming 4/28/2015 SEVERAL NEW ISSUES Where do we return to after the procedure call is done? Where are the local variables of the procedure kept? How are the parameters passed? How is the result returned? 3 Dr. Tim Margush 3 Assembly Language Programming 4/28/2015 RETURN ADDRESS We need to keep the return address somewhere? #return addresses that need to be remembered? How many instances of local variables per procedure? Can a procedure be called (instantiated) multiple times? Stack. 4 Dr. Tim Margush 4 Assembly Language Programming 4/28/2015 STACK The stack grows downward from a high address to a low address. Special instructions and I/O register support stack access: RET, CALL, PUSH, POP, … SP (Stack Pointer) The stack requires initialization Set SP to an appropriate address (empty stack) The stack is managed by application and is also used by the processor interrupt system 5 Dr. Tim Margush 5 Assembly Language Programming 4/28/2015 STACK INITIALIZATION Typically, the stack starts at the highest SRAM address and grows downward through memory SP points to the next available byte of stack storage (top of stack after a push) ldi R16, high(RAMEND) out SPH, R16 ldi R16, low(RAMEND) out SPL, R16 Dr. Tim Margush $100 SRAM SP $1FFF Stack 6 6 Assembly Language Programming 4/28/2015 SP IN SRAM (ADDRESS) The I/O addresses are 0x3D and 0x3E on ATmega128 (to use IN/OUT) The memory addresses are 0x5D and 0x5E (to use LDS/STS) 7 Dr. Tim Margush 7 Assembly Language Programming 4/28/2015 PUSH AND POP push Rr Register data copied to byte at address in SP. SP is decremented. 2 cycles pop Rd SP is incremented. Byte at address in SP is copied to Rd. 2 cycles 8 Dr. Tim Margush 8 Assembly Language Programming 4/28/2015 PUSH OPERATION push R2 Addr R2: 0xAB Byte Addr Byte 0x1300 0x00 0x1300 0x00 0x12ff 0x11 0x12ff 0x11 0x12fe 0x22 0x12fe 0x22 0x12fd 0xAB SPH: 0x12 SPL: 0xfd SPL: 0xfc 9 Dr. Tim Margush 9 Assembly Language Programming 4/28/2015 POP OPERATION pop R3 Addr R3: 0x00 Byte Addr Byte 0x1300 0x00 0x1300 0x00 0x12ff 0x11 0x12ff 0x11 0x12fe 0x22 0x12fe 0x22 SPH: 0x12 SPL: 0xfd SPL: 0xfe R3: 0x22 Dr. Tim Margush 10 10 Assembly Language Programming 4/28/2015 PROCEDURE CALL R16 R17 main () { uint8_t var1, var2; var1 = 50; var2 = addone (var1); } main: ----------------ldi R16, 50 ;var1 = 50 ;pass parameters on ;stack left to right push R16 rcall addone -----------rcall: jumps to label ----------- Relative addressing Pushes the address of the next instruction on the stack. Return address (RA) Dr. Tim Margush 11 11 Assembly Language Programming 4/28/2015 FUNCTION CALL AND RETURN SP register: Stack Pointer register Before RCALL After RCALL High end SP ret addr. Other Data Low end Data Memory next addr. Other Data main RCALL … … addone ret Data Memory Program Memory Dr. Tim Margush 12 Assembly Language Programming 4/28/2015 STACK FOR MAIN Stack frame for main: Local vars Any saved vars Proc call paras var1 var2 SP:0x1200 Dr. Tim Margush 13 13 Assembly Language Programming 4/28/2015 push R16 var1 var2 50 SP:0x11ff Dr. Tim Margush 14 14 Assembly Language Programming 4/28/2015 rcall addone var1 var2 0x4000: ldi r16, 50 0x4002: push r16 0x4004: rcall addone 0x4006: something PC: 0x4004 50 RAL: 0x06 RAH: 0x40 SP:0x11fd 15 PC: address of addone: 0x4400 Dr. Tim Margush 15 Assembly Language Programming 4/28/2015 PROCEDURE ADDONE uint8_t addone (int X) { uint8_t sum; sum = X + 1; return (sum); } addone: in YH, SPH in YL, SPL ; Now on Y serves as an ; entry point into stack 16 Dr. Tim Margush 16 Assembly Language Programming ldd R1, Y+3 ; what if R1 is used by the ; caller – main? Y: R28:29: 0x11fd Dr. Tim Margush var1 var2 50 RAL: 0x06 RAH: 0x40 SP:0x11fd Stack frame for addone addone: in YH, SPH in YL, SPL ; Now on Y serves as an ; entry point into stack ;Now move var X into reg. 4/28/2015 17 17 Assembly Language Programming var1 var2 50 RAL: 0x06 RAH: 0x40 Saved R1 Y: R28:29: 0x11fd Dr. Tim Margush SP:0x11fc Stack frame for addone addone: in YH, SPH in YL, SPL ; save R1 before using it push R1 ldd R1, Y+3 ; sum = X+1 ; where is sum? ; on the stack. 4/28/2015 18 18 Assembly Language Programming Y: R28:29: 0x11fd Dr. Tim Margush var1 var2 50 (51) RAL: 0x06 RAH: 0x40 sum (local vars): 51 Saved R1 SP:0x11fb Stack frame for addone addone: in YH, SPH in YL, SPL ; skip over local vars push zero ; save R1 before using it push R1 ldd R1, Y+3 ; sum = X+1 inc R1 st Y, R1 ; return result – where? ; overwrite input para std Y+3, R1 4/28/2015 19 19 Assembly Language Programming ; now we return with RET var1 var2 50 (51) RAL: 0x06 RAH: 0x40 sum (local vars) Saved R1 Y: R28:29: 0x11fd Dr. Tim Margush SP:0x11fb (11fc)(11fd) Stack frame for addone ; return result – where? ; overwrite input para std Y+3, R1 ; now undo everything ; restore R1 pop R1 ; skip over local vars out SPH, YH out SPL, YL 4/28/2015 20 20 Assembly Language Programming ; now we return with RET ret var1 var2 51 RAL: 0x06 RAH: 0x40 PC: 0x4006 SP: 11fd Dr. Tim Margush Stack frame for addone ; return result – where? ; overwrite input para std Y+3, R1 ; now undo everything ; restore R1 pop R1 ; skip over local vars out SPH, YH out SPL, YL 4/28/2015 21 21 Assembly Language Programming addone: in YH, SPH in YL, SPL ; skip over local vars push zero ; save R1 before using it push R1 ldd R1, Y+3 ; sum =inc inc R1 st Y, R1 ; sum =inc ; overwrite input para std Y+3, R1 ; now undo everything ; restore R1 pop R1 4/28/2015 ; skip over local vars out SPH, YH out SPL, YL ; now we return with RET ret 22 Dr. Tim Margush 22 Assembly Language Programming 4/28/2015 COMPLETE “MAIN” var1 main: ----------------ldi R16, 50 ;var1 = 50 ;pass parameters on ;stack left to right push R16 rcall addone ;read the result ; var2 <- result pop R17 Dr. Tim Margush var2 51 SP: 11ff (1200) 23 23 Assembly Language Programming 4/28/2015 AVR-GCC CALL CONVENTION Function parameters R25:R24, R23:R22, ..., R9:R8 All aligned to start in even-numbered register i.e. char will take two registers (use the even one) A long type uses two pairs Extra parameters go to stack Function return values 8-bit in r24 (with r25 cleared to zero), or 16-bit in R25:R24, or 32-bit in R25-R22, or 64-bit in R25-R18 Dr. Tim Margush 24 Assembly Language Programming 4/28/2015 AVR-GCC CALL CONVENTION How to share register usage? Call-saved/Callee-save/Non-volatile: R2-R17, R28-R29 Caller may use them for free (save registers) Call-used/Caller-save/Volatile: R18-R27, R30-R31 Callee may use them for free (temp registers) Fixed registers R0: Temporary register used by gcc (no need to save) R1: Should be zero Dr. Tim Margush 25 Assembly Language Programming 4/28/2015 AVR-GCC CALL CONVENTION R0 R1 (Zero) R2 R3 R4 R5 R6 R7 R8 (P8) R9 (P8) R10 (P7) R11 (P7) R12 (P6) R13 (P6) R14 (P5) R15 (P5) R16 (P4) R24 (P0, V0) R17 (P4, V8) R25 (P0, V1) R18 (P3, V6) R26 X R19 (P3, V7) R27 R20 (P2, V4) R28 Y R21 (P2, V5) R29 R22 (P1, V2) R30 Z R23 (P1, V3) R31 Call-saved/Callee-save/Non-volatile Call-used/Caller-save/Volatile Fixed Dr. Tim Margush P: Parameter V: Result 26 Assembly Language Programming 4/28/2015 AVR-GCC CALL CONVENTION Where are the parameters and return values? char add_char(char a, char b); int checksum(int A[], int size); char add_3char(char a, char b, char c); Dr. Tim Margush 27 Assembly Language Programming 4/28/2015 FUNCTION EXAMPLE ; char add_char(char a, char b) ; reg: r24 for a, r22 for b add_char: ADD r24, r22 ; r24=a+b LDI r25, 0 ; clear r25 RET main: … LDI r24, 0x01 ; load a LDI r22, 0x02 ; load b RCALL add_char ; c=a+b ST X, r24 ; save c Dr. Tim Margush 28 Assembly Language Programming 4/28/2015 FUNCTION EXAMPLE // assume size is greater than zero //parity check - ExOR char checksum(char A[], int size); Dr. Tim Margush 29 Assembly Language Programming 4/28/2015 FUNCTION EXAMPLE ; parameter r25:r24 for A,r23:r22 for size, ; Use Y for &A[k], r24 for csum ; r23:r22 for i, r20 for A[i] ; return value in r25:r24 checksum: ; func prologue PUSH r29 ; save r29 PUSH r28 ; save r28 ; loop prologue MOVW r28, r24 ; reg Y=&A[0] CLR r24 ; csum = 0; Dr. Tim Margush 30 Assembly Language Programming 4/28/2015 FUNCTION EXAMPLE loop: LD EOR SUBI BNE ; func CLR r25:r24 POP POP RET Dr. Tim Margush r20, Y+ ; load A[k] r24, r20 ; csum^=A[k] r22, 1 ; size-loop ; cont until i==0 epilogue r25 ; ret value in r28 r29 ; restore r28 ; restore r29 31 Assembly Language Programming 4/28/2015 FUNCTION EXAMPLE char add_3char(char a, char b, char c) { return add_char(add_char(a, b), c); } Dr. Tim Margush 32 Assembly Language Programming 4/28/2015 FUNCTION EXAMPLE ; parameters: r24=a, r22=b, r20=c add_3char: PUSH r20 ; r20 is volatile ; call add_char(a, b) RCALL add_char ; call add_char(ret_value, c) POP r22 ; make c a param. RCALL add_char RET Dr. Tim Margush 33 Assembly Language Programming 4/28/2015 SUMMARY We have learned AVR-GCC Call Convention Make function call (caller) and return (callee) Pass parameters (caller and callee) Get return value (caller) Share registers (caller and callee) Use stack This is how one function can call another function by prototype, with no need for the source code Dr. Tim Margush 34
© Copyright 2025