Tutorial 3: ARM assembly function call -------------------------------------- .. include:: shared/notformark.rst Question 1: Understanding the stack ################################### Report the final contents of the stack and the registers when the following ARM assembly instructions are executed. Assume that the initial stack is empty and :code:`R0=-1 R1=22 R2=3 R4=0`.After that, rewrite the instructions using :code:`Pop/Push` only. .. code-block:: arm STR R4, [SP, #-4]! STR R4, [SP, #-4]! STR R0, [SP, #-4]! LDR R1, [SP], #4 STR R1, [SP, #-4]! STR R2, [SP, #-4]! LDR R0, [SP], #4 Question 2: Function call with no argument passed or value returned ################################################################### Identify the caller, the callee and the instruction that the link register will have its address when the following program finishes execution. .. code-block:: arm .global _start _start: MOV R0, #0 MOV R1 #2 ADD R1, R0, R1 BL function_1 LSR R3, #2 AND R0, R1, R3 .end function_1: BX LR Question 3: Function call with argument passed by value and a value returned ############################################################################ Convert the following C program into ARM assembly. .. note:: To follow ARM calling convention: use :code:`R0–R3` for passing arguments, and use :code:`R0` for the return value. You can use the stack to pass the arguments if you want. Also Please make sure to follow the Callee-save convention (callee is responsible for leaving the registers as it found them) .. code-block:: c int MAC (i1, i2, i3, i4); void main(){ int weight0 = 2; int ifm0 = 18; int weight1 = 3; int ifm1 = 8; int ofm = MAC(weight0, ifm0, weight1, ifm1); } int MAC (i1, i2, i3, i4){ return i1*i2 + i3*i4; } Question 4: Passing arguments by reference vs passing by value ################################################################################# Given the following C program, what's the result of each `printf` statement? .. code-block:: c #include int ASR_Val (int i) { i = i >> 1; return i ; } void ASR_Ref (int *i) { *i = (*i) >> 1; } void main () { int w = 14; int w_returned ; w_returned = ASR_Val(w) ; printf("%d\n",w); printf("%d\n", w_returned); ASR_Ref(&w) ; printf("%d\n",w); } Question 5: Structs (Always passed by value) ############################################ Show, in ARM assembly, how to pass the struct in the following C program as an argument using the stack. Also, report the result of each `printf` statement. .. code-block:: c #include struct Vec { //Vector struct that has two integers x and y. int x; int y; }; struct Vec add2(struct Vec v); void main(){ struct Vec vector_to_pass; struct Vec vector_returned; vector_to_pass.x = 12; vector_to_pass.y = 43; vector_returned = add2(vector_to_pass); printf("%d\n",vector_to_pass.x); printf("%d\n",vector_to_pass.y); printf("%d\n",vector_returned.x); printf("%d\n",vector_returned.y); } struct Vec add2(struct Vec v){ //Function `add2`, that takes a struct of type `vec` and adds 2 to its integers and returns a struct of type Vec v.x = v.x + 2; v.y = v.y + 2; return v; } Question 6: Frame Pointer ############################################ Modify the previous program (Q5) to use the Frame Pointer :code:`FP (R11)` with relative addressing to access arguments. .. note:: Frame Pointer contains the base address of the function frame on the stack (Stack Pointer value right after entering a function). It is used to simplify addressing when passing arguments through the stack. The following instructions will help you save and intialize FP properly. .. code-block:: arm start: .... BL add2 add2: PUSH {FP} ADD FP, SP, #4 .... POP {FP}