2.4 OpenEuler中C语言中的函数调用测试(选做)

# 2.4 OpenEuler中C语言中的函数调用测试(选做)


0.任务详情

1. 在X86_64架构下实践2.4中的内容
2. 通过GDB查看寄存器的内容,把教材中的图填入具体的值
3. 把2.4的C代码在OpenEuler中重新实践一遍,绘制出ARM64的逻辑框图
4. 实验内容要经过答辩才能得到相应分数

1.

通过教材可知,64位和32位在参数传递上存在差异。32位在传递参数的时候是直接通过堆栈进行传递,而64位在传递传输的时候是先将前6个参数依次传入rdi、rsi、rdx、rcx、r8、r9,然后剩余的参数像32位一样通过堆栈传递,在2.5的作业上用32位代码直接在64位上调用printf函数出现段错误的问题,教材这里直接说明了,就是这个差异导致的。

1.32位GCC中的运行时堆栈使用情况

  • main.c:
main(){
int a,b,c;
a=1;b=2;c=3;
c=sub(a,b);
printf("c=%d\n",c);
}
  • sub.c
int sub(int x,int y){
        int u,v;
        u=4;v=5;
        return x+y+u+v;
}
gcc -g main.c sub.c -o main -m32

进入gdb调试器:

image-20211204213243434

b main
run
disassamble
ir

img
u,v被压入栈中
img
u,v栈的地址为
img

longjump

include<stdio.h>
#include<setjmp.h>
jmp_buf env;

int main()
{
        int r,a=100;
        printf("call setjmp to save environmen\n");
        if((r=setjmp(env))==0){
                A();
                printf("normal return\n");
        }
        else
                printf("back to main() via long jump,r=%d,a=%d",r,a);
}

int A()
{
        printf("enter A()\n");
        B();
        printf("exit A()\n");

}

int B()
{
        printf("enter B()\n");
        printf("long jump?(y|n) ");
        if(getchar()=='y')
                longjmp(env,1234);
        printf("exit B()\n");
}

img

2.64位GCC中的运行时堆栈使用情况

#include <stdio.h>
int sub(int a, int b, int c, int d, int e, int f, int g, int h)
{
int u, v, w;
u = 9;
v = 10;
w= 11;
return a+g+u+v;
}

int main()
{
int a, b, c, d, e,f, g, h,i;
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
f = 6;
g = 7;
h = 8;
i = sub(a,b,c,d,e,f,g,h);
}

img

树莓派arm64位环境

arm64架构下的的t.s:

.cpu generic+fp+simd
.file "t.c"
.text
.align 2
.global sub
.type sub, %function
sub:
.LFB0:
.cfi_startproc
sub sp, sp, #48
.cfi_def_cfa_offset 48
str w0, [sp,28]
str w1, [sp,24]
str w2, [sp,20]
str w3, [sp,16]
str w4, [sp,12]
str w5, [sp,8]
str w6, [sp,4]
str w7, [sp]
mov w0, 9
str w0, [sp,44]
mov w0, 10
str w0, [sp,40]
mov w0, 11
str w0, [sp,36]
ldr w1, [sp,28]
ldr w0, [sp,4]
add w1, w1, w0
ldr w0, [sp,44]
add w1, w1, w0
ldr w0, [sp,40]
add w0, w1, w0
add sp, sp, 48
.cfi_def_cfa_offset 0
ret
.cfi_endproc
.LFE0:
.size sub, .-sub
.align 2
.global main
.type main, %function
main:
.LFB1:
.cfi_startproc
stp x29, x30, [sp, -64]!
.cfi_def_cfa_offset 64
.cfi_offset 29, -64
.cfi_offset 30, -56
add x29, sp, 0
.cfi_def_cfa_register 29
mov w0, 1
str w0, [x29,60]
mov w0, 2
str w0, [x29,56]
mov w0, 3
str w0, [x29,52]
mov w0, 4
str w0, [x29,48]
mov w0, 5
str w0, [x29,44]
mov w0, 6
str w0, [x29,40]
mov w0, 7
str w0, [x29,36]
mov w0, 8
str w0, [x29,32]
ldr w0, [x29,60]
ldr w1, [x29,56]
ldr w2, [x29,52]
ldr w3, [x29,48]
ldr w4, [x29,44]
ldr w5, [x29,40]
ldr w6, [x29,36]
ldr w7, [x29,32]
bl sub
str w0, [x29,28]
ldp x29, x30, [sp], 64
.cfi_restore 30
.cfi_restore 29
.cfi_def_cfa 31, 0
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-39)"
.section .note.GNU-stack,"",%progbits

posted @ 2021-12-04 21:34  20191310李烨龙  阅读(71)  评论(0编辑  收藏  举报