首页
社区
课程
招聘
[原创]ARM函数调用传参规则
发表于: 2020-10-14 13:21 5691

[原创]ARM函数调用传参规则

2020-10-14 13:21
5691

对应main函数的汇编代码

此时栈及寄存器如下:
图片描述

对应func函数的汇编代码

图片描述

结论: 传递基本数据类型,前4个放入寄存器r0-r3中,多于的放入栈上

main函数对应的汇编

结论:传递数组 实际上传递的是数组首地址指针,取数组内容通过首地址偏移

main函数对应汇编

结论:结构体的传递和直接传递参数一样 --> func1(int a, int b, int c, int d, int e)

main对应汇编代码

结论:传递枚举,直接传递的值 类似于 func2(int a)

main函数对应汇编

结论:传递对象指针 传递过来的是地址

main函数汇编,和传递对象地址是一样的

main函数的汇编代码

func5对应的部分汇编代码

结论:传递对象 传递过来的是成员变量值,在被调用方再分配空间。 c++对象内存模型中只有成员变量占对象内存空间

int func(int a, int b, int c, int d, int e) {
    int v1 = 1;
    int r = a + b + c + d + e + v1;
    return r;
}
int main() {
    int i = 1, j = 2;
    int r = func(i, j, 3, 4, 5);
    printf("%d \n", r);
}
int func(int a, int b, int c, int d, int e) {
    int v1 = 1;
    int r = a + b + c + d + e + v1;
    return r;
}
int main() {
    int i = 1, j = 2;
    int r = func(i, j, 3, 4, 5);
    printf("%d \n", r);
}
; int __cdecl main(int argc, const char **argv, const char **envp)
 
PUSH            {R11,LR}                    ;保存现场
ADD             R11, SP, #4                 ;新栈的基址 FP(BP)
SUB             SP, SP, #0x18               ;开辟栈空间
MOV             R3, #1                      ;r3 = 1
STR             R3, [R11,#var_8]            ;[r11+var_8] = 1
MOV             R3, #2                      ;r3 = 2
STR             R3, [R11,#var_C]            ;[r11+var_C] = 2
MOV             R3, #5                      ;r3 = 5
STR             R3, [SP,#0x1C+var_1C] ; int ;[sp+0x1c+var_1c] = 5
LDR             R0, [R11,#var_8]            ;r0 = [r11+var_8] = 1   
LDR             R1, [R11,#var_C]            ;r1 = [r11+var_C] = 2
MOV             R2, #3                      ;r2 = 3
MOV             R3, #4                      ;r3 = 4
BL              _Z4funciiiii ; func(int,int,int,int,int)
; int __cdecl main(int argc, const char **argv, const char **envp)
 
PUSH            {R11,LR}                    ;保存现场
ADD             R11, SP, #4                 ;新栈的基址 FP(BP)
SUB             SP, SP, #0x18               ;开辟栈空间
MOV             R3, #1                      ;r3 = 1
STR             R3, [R11,#var_8]            ;[r11+var_8] = 1
MOV             R3, #2                      ;r3 = 2
STR             R3, [R11,#var_C]            ;[r11+var_C] = 2
MOV             R3, #5                      ;r3 = 5
STR             R3, [SP,#0x1C+var_1C] ; int ;[sp+0x1c+var_1c] = 5
LDR             R0, [R11,#var_8]            ;r0 = [r11+var_8] = 1   
LDR             R1, [R11,#var_C]            ;r1 = [r11+var_C] = 2
MOV             R2, #3                      ;r2 = 3
MOV             R3, #4                      ;r3 = 4
BL              _Z4funciiiii ; func(int,int,int,int,int)
 
; _DWORD __fastcall func(int, int, int, int, int)
PUSH            {R11}
ADD             R11, SP, #0
SUB             SP, SP, #0x1C
STR             R0, [R11,#var_10]   ; r0 = 1
STR             R1, [R11,#var_14]   ; r1 = 2
STR             R2, [R11,#var_18]   ; r2 = 3
STR             R3, [R11,#var_1C]   ; r3 = 4
MOV             R3, #1
STR             R3, [R11,#var_8]
LDR             R2, [R11,#var_10]
LDR             R3, [R11,#var_14]
ADD             R2, R2, R3 ; 1 + 2
LDR             R3, [R11,#var_18]
ADD             R2, R2, R3 ; 1+2+3
LDR             R3, [R11,#var_1C]
ADD             R2, R2, R3 ; 1+2+3+4
LDR             R3, [R11,#arg_0]    ; 注意这里 r11+4,就是在main中传入的第5个参数
ADD             R2, R2, R3
; _DWORD __fastcall func(int, int, int, int, int)
PUSH            {R11}
ADD             R11, SP, #0
SUB             SP, SP, #0x1C
STR             R0, [R11,#var_10]   ; r0 = 1
STR             R1, [R11,#var_14]   ; r1 = 2
STR             R2, [R11,#var_18]   ; r2 = 3
STR             R3, [R11,#var_1C]   ; r3 = 4
MOV             R3, #1
STR             R3, [R11,#var_8]
LDR             R2, [R11,#var_10]
LDR             R3, [R11,#var_14]
ADD             R2, R2, R3 ; 1 + 2
LDR             R3, [R11,#var_18]
ADD             R2, R2, R3 ; 1+2+3
LDR             R3, [R11,#var_1C]
ADD             R2, R2, R3 ; 1+2+3+4
LDR             R3, [R11,#arg_0]    ; 注意这里 r11+4,就是在main中传入的第5个参数
ADD             R2, R2, R3
 
void func6(int a[], int len) {
    for (int i = 0; i < len; i++) {
        printf("index: %d , num: %d\n", i, a[i]);
    }
}
int main() {
    int a[] = {0, 1, 2};
    int n = sizeof(a) / sizeof(int);
    func6(a, n);
}
void func6(int a[], int len) {
    for (int i = 0; i < len; i++) {
        printf("index: %d , num: %d\n", i, a[i]);
    }
}
int main() {
    int a[] = {0, 1, 2};
    int n = sizeof(a) / sizeof(int);
    func6(a, n);
}
PUSH            {R11,LR}
ADD             R11, SP, #4
SUB             SP, SP, #0x10
LDR             R2, =(dword_20BC - 0x8C8)
ADD             R2, PC, R2 ; dword_20BC     ; r2存储数组首地址
SUB             R3, R11, #-var_14
LDM             R2, {R0-R2}                 ; 把数组[0,1,2]内容存到r0,r1,r2
STM             R3, {R0-R2}                 ; 再存到r3所指向的栈上
MOV             R3, #3
STR             R3, [R11,#var_8]
SUB             R3, R11, #-var_14           ; 获取数组在栈上首地址。数组首地址放到r0中,作为参数传递
MOV             R0, R3  ; int *
LDR             R1, [R11,#var_8] ; int
BL              _Z5func6Pii                 ; func6(int *,int)
MOV             R3, #0
MOV             R0, R3
SUB             SP, R11, #4
POP             {R11,PC}
PUSH            {R11,LR}
ADD             R11, SP, #4
SUB             SP, SP, #0x10
LDR             R2, =(dword_20BC - 0x8C8)
ADD             R2, PC, R2 ; dword_20BC     ; r2存储数组首地址
SUB             R3, R11, #-var_14
LDM             R2, {R0-R2}                 ; 把数组[0,1,2]内容存到r0,r1,r2
STM             R3, {R0-R2}                 ; 再存到r3所指向的栈上
MOV             R3, #3
STR             R3, [R11,#var_8]
SUB             R3, R11, #-var_14           ; 获取数组在栈上首地址。数组首地址放到r0中,作为参数传递
MOV             R0, R3  ; int *
LDR             R1, [R11,#var_8] ; int
BL              _Z5func6Pii                 ; func6(int *,int)
MOV             R3, #0
MOV             R0, R3
SUB             SP, R11, #4
POP             {R11,PC}
struct st_a {
    int a;
    int b;
    int c;
    int d;
    int e;
};
void func1(st_a stA) {
    int a = stA.a;
    int b = stA.b;
    int c = stA.c;
    int d = stA.d;
    int e = stA.e;
    printf("%d, %d \n", a, b, c, d, e);
}
int main() {
    st_a stA;
    stA.a = 123;
    stA.b = 234;
    stA.c = 345;
    stA.d = 456;
    stA.e = 567;
    func1(stA);
}
struct st_a {
    int a;
    int b;
    int c;
    int d;
    int e;
};
void func1(st_a stA) {
    int a = stA.a;
    int b = stA.b;
    int c = stA.c;
    int d = stA.d;
    int e = stA.e;
    printf("%d, %d \n", a, b, c, d, e);
}
int main() {
    st_a stA;
    stA.a = 123;
    stA.b = 234;
    stA.c = 345;
    stA.d = 456;
    stA.e = 567;
    func1(stA);
}
PUSH            {R11,LR}
ADD             R11, SP, #4
SUB             SP, SP, #0x20
MOV             R3, #123
STR             R3, [R11,#var_18]       ; 123 放到栈上[r11-0x18]
MOV             R3, #234
STR             R3, [R11,#var_14]       ; 234 放到栈上[r11-0x14]
LDR             R3, =345
STR             R3, [R11,#var_10]       ; 345 放到栈上[r11-0x10]
MOV             R3, #456
STR             R3, [R11,#var_C]        ; 456 放到栈上[r11-0xc]
LDR             R3, =567
STR             R3, [R11,#var_8]        ; 567 放到栈上[r11-0x8]
LDR             R3, [R11,#var_8]
STR             R3, [SP,#0x24+var_24]   ; 567 放到栈上[sp]
SUB             R3, R11, #-var_18
LDM             R3, {R0-R3}             ; 将 123 234 345 456放到寄存器r0,r1,r2,r3
BL              _Z5func14st_a ; func1(st_a)
MOV             R3, #0
MOV             R0, R3
SUB             SP, R11, #4
POP             {R11,PC}
PUSH            {R11,LR}
ADD             R11, SP, #4
SUB             SP, SP, #0x20
MOV             R3, #123
STR             R3, [R11,#var_18]       ; 123 放到栈上[r11-0x18]
MOV             R3, #234
STR             R3, [R11,#var_14]       ; 234 放到栈上[r11-0x14]
LDR             R3, =345
STR             R3, [R11,#var_10]       ; 345 放到栈上[r11-0x10]
MOV             R3, #456
STR             R3, [R11,#var_C]        ; 456 放到栈上[r11-0xc]
LDR             R3, =567
STR             R3, [R11,#var_8]        ; 567 放到栈上[r11-0x8]
LDR             R3, [R11,#var_8]
STR             R3, [SP,#0x24+var_24]   ; 567 放到栈上[sp]
SUB             R3, R11, #-var_18
LDM             R3, {R0-R3}             ; 将 123 234 345 456放到寄存器r0,r1,r2,r3
BL              _Z5func14st_a ; func1(st_a)
MOV             R3, #0
MOV             R0, R3
SUB             SP, R11, #4
POP             {R11,PC}
enum en_a {
    p1 = 103,
    p2 = 201
};
void func2(en_a enA) {
    printf("%d \n", enA);
}
int main() {
    func2(p1);
}
enum en_a {

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2020-10-14 19:09 被lanoche编辑 ,原因: 修改图片错误
收藏
免费 2
支持
分享
最新回复 (2)
雪    币: 1446
活跃值: (1526)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感觉main函数栈 图,的r11 和 lr的顺序不大对
2020-10-14 17:04
0
雪    币: 1365
活跃值: (3554)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
奋斗der小鸟 感觉main函数栈 图,的r11 和 lr的顺序不大对
是的,写反了
2020-10-14 19:07
0
游客
登录 | 注册 方可回帖
返回
//