x86和arm上的调用约定

x86和arm上的调用约定

一个函数可以分为三部分

  • prologue
  • Body
  • Epilogue

1 x86上的调用约定

1587216724069
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
.486
.MODEL FLAT
.CODE
PUBLIC _myFunc
_myFunc PROC
; Subroutine Prologue
push ebp ; Save the old base pointer value.
mov ebp, esp ; Set the new base pointer value.
sub esp, 4 ; Make room for one 4-byte local variable.
push edi ; Save the values of registers that the function
push esi ; will modify. This function uses EDI and ESI.
; (no need to save EBX, EBP, or ESP)

; Subroutine Body
mov eax, [ebp+8] ; Move value of parameter 1 into EAX
mov esi, [ebp+12] ; Move value of parameter 2 into ESI
mov edi, [ebp+16] ; Move value of parameter 3 into EDI

mov [ebp-4], edi ; Move EDI into the local variable
add [ebp-4], esi ; Add ESI into the local variable
add eax, [ebp-4] ; Add the contents of the local variable
; into EAX (final result)

; Subroutine Epilogue
pop esi ; Recover register values
pop edi
mov esp, ebp ; Deallocate local variables
pop ebp ; Restore the caller's base pointer value
ret
_myFunc ENDP
END

1.1 序言

  1. 保存原来栈的栈帧
  2. 设定当前栈的栈帧为esp所指向的位置
  3. 开辟新的栈:esp - 4
  4. 保存其他可能会更改的寄存器内容到栈上

1.2 主体

从栈上读取callee写入栈上的参数(利用ebp寻址)

进行运算,结果写入eax

1.3 尾声

  1. 将序言中存入栈的内容取回到寄存器
  2. 将esp恢复到ebp的位置,释放栈
  3. callee的ebp出栈
  4. 调用ret,返回地址出栈,然后跳转到返回地址所指向的位置

2 ARM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.global main

main:
push {r11, lr} /* Start of the prologue. Saving Frame Pointer and LR onto the stack */
add r11, sp, #0 /* Setting up the bottom of the stack frame */
sub sp, sp, #16 /* End of the prologue. Allocating some buffer on the stack */
mov r0, #1 /* setting up local variables (a=1). This also serves as setting up the first parameter for the max function */
mov r1, #2 /* setting up local variables (b=2). This also serves as setting up the second parameter for the max function */
bl max /* Calling/branching to function max */
sub sp, r11, #0 /* Start of the epilogue. Readjusting the Stack Pointer */
pop {r11, pc} /* End of the epilogue. Restoring Frame pointer from the stack, jumping to previously saved LR via direct load into PC */

max:
push {r11} /* Start of the prologue. Saving Frame Pointer onto the stack */
add r11, sp, #0 /* Setting up the bottom of the stack frame */
sub sp, sp, #12 /* End of the prologue. Allocating some buffer on the stack */
cmp r0, r1 /* Implementation of if(a<b) */
movlt r0, r1 /* if r0 was lower than r1, store r1 into r0 */
add sp, r11, #0 /* Start of the epilogue. Readjusting the Stack Pointer */
pop {r11} /* restoring frame pointer */
bx lr /* End of the epilogue. Jumping back to main via LR register */

2.1 序言

  1. 将栈帧入栈
  2. 栈帧改为sp
  3. sp减少开辟栈空间
  4. 可能会用到的寄存器入栈

2.2 主体

从寄存器 r0-r3取参数前4个

计算

2.3 尾声

  1. 栈帧出栈
  2. bx lr 通过lr(存储返回地址) 跳转回栈帧