OpenEuler 中C语言中的函数调用测试

OpenEuler 中C语言中的函数调用测试

20191331 lyx

实践任务

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

一、在OpenEuler下实践2.4内容

1.函数调用

实验环境:Ubuntu 16.04 with x86

测试代码

int sub(int x,int y)
{
    int u,v;
    u = 4;v = 5;
    return x+y+u+v;
}

int main()
{
    int a,b,c;
    a = 1;b = 2;c = 3;
    c = sub(a,b);
    printf("c = %d\n",c);
}

编译运行

gcc -g main.c sub.c -o sub32 -m32

测试代码汇编

main.s

	.file	"main.c"
	.section	.rodata
.LC0:
	.string	"c = %d\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	$1, -12(%rbp)
	movl	$2, -8(%rbp)
	movl	$3, -4(%rbp)
	movl	-8(%rbp), %edx
	movl	-12(%rbp), %eax
	movl	%edx, %esi
	movl	%eax, %edi
	movl	$0, %eax
	call	sub
	movl	%eax, -4(%rbp)
	movl	-4(%rbp), %eax
	movl	%eax, %esi
	movl	$.LC0, %edi
	movl	$0, %eax
	call	printf
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
	.section	.note.GNU-stack,"",@progbits

sub.s

	.file	"sub.c"
	.text
	.globl	sub
	.type	sub, @function
sub:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	%edi, -20(%rbp)
	movl	%esi, -24(%rbp)
	movl	$4, -8(%rbp)
	movl	$5, -4(%rbp)
	movl	-20(%rbp), %edx
	movl	-24(%rbp), %eax
	addl	%eax, %edx
	movl	-8(%rbp), %eax
	addl	%eax, %edx
	movl	-4(%rbp), %eax
	addl	%edx, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	sub, .-sub
	.ident	"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
	.section	.note.GNU-stack,"",@progbits

使用GDB调试器查看堆栈内容

gdb sub32

b main (设断点)
r  (运行程序)
disas  (反汇编)
i r  (打印寄存器信息)

a,b,c 压栈

u,v 压栈

2.long jump

测试代码

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

int main()
{
    int r,a=100;
    printf("call setjmp to save environment\n");
    if ((r = setjmp(env)) == 0)
    {
        A();
        printf("normal return\n");
    }
    else
        printf("back to main() via long jump, r = %d a = %d\n",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");
}

编译运行

gcc -g longjump.c -o jump32 -m32

测试代码汇编

	.file	"longjump.c"
	.comm	env,200,32
	.section	.rodata
	.align 8
.LC0:
	.string	"call setjmp to save environment"
.LC1:
	.string	"normal return"
	.align 8
.LC2:
	.string	"back to main() via long jump, r = %d a = %d\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$16, %rsp
	movl	$100, -8(%rbp)
	movl	$.LC0, %edi
	call	puts
	movl	$env, %edi
	call	_setjmp
	movl	%eax, -4(%rbp)
	cmpl	$0, -4(%rbp)
	jne	.L6
	movl	$0, %eax
	call	A
	movl	$.LC1, %edi
	call	puts
	jmp	.L4
.L6:
	movl	-8(%rbp), %edx
	movl	-4(%rbp), %eax
	movl	%eax, %esi
	movl	$.LC2, %edi
	movl	$0, %eax
	call	printf
.L4:
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.section	.rodata
.LC3:
	.string	"enter A()"
.LC4:
	.string	"exit A()"
	.text
	.globl	A
	.type	A, @function
A:
.LFB1:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$.LC3, %edi
	call	puts
	movl	$0, %eax
	call	B
	movl	$.LC4, %edi
	call	puts
	nop
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	A, .-A
	.section	.rodata
.LC5:
	.string	"enter B()"
.LC6:
	.string	"long jump? (y|n) "
.LC7:
	.string	"exit B()"
	.text
	.globl	B
	.type	B, @function
B:
.LFB2:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	$.LC5, %edi
	call	puts
	movl	$.LC6, %edi
	movl	$0, %eax
	call	printf
	call	getchar
	cmpl	$121, %eax
	jne	.L9
	movl	$1234, %esi
	movl	$env, %edi
	call	longjmp
.L9:
	movl	$.LC7, %edi
	call	puts
	nop
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE2:
	.size	B, .-B
	.ident	"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
	.section	.note.GNU-stack,"",@progbits

使用 GDB 调试器查看堆栈内容

   0x080484db <+0>:	lea    0x4(%esp),%ecx
   0x080484df <+4>:	and    $0xfffffff0,%esp
   0x080484e2 <+7>:	pushl  -0x4(%ecx)
   0x080484e5 <+10>:	push   %ebp
   0x080484e6 <+11>:	mov    %esp,%ebp
   0x080484e8 <+13>:	push   %ecx
   0x080484e9 <+14>:	sub    $0x14,%esp
=> 0x080484ec <+17>:	movl   $0x64,-0x10(%ebp)
   0x080484f3 <+24>:	sub    $0xc,%esp
   0x080484f6 <+27>:	push   $0x8048660
   0x080484fb <+32>:	call   0x80483b0 <puts@plt>
   0x08048500 <+37>:	add    $0x10,%esp
   0x08048503 <+40>:	sub    $0xc,%esp
   0x08048506 <+43>:	push   $0x804a060
   0x0804850b <+48>:	call   0x8048390 <_setjmp@plt>
   0x08048510 <+53>:	add    $0x10,%esp
   0x08048513 <+56>:	mov    %eax,-0xc(%ebp)
   0x08048516 <+59>:	cmpl   $0x0,-0xc(%ebp)
   0x0804851a <+63>:	jne    0x8048533 <main+88>
   0x0804851c <+65>:	call   0x8048556 <A>
   0x08048521 <+70>:	sub    $0xc,%esp
   0x08048524 <+73>:	push   $0x8048680
   0x08048529 <+78>:	call   0x80483b0 <puts@plt>
   0x0804852e <+83>:	add    $0x10,%esp
   0x08048531 <+86>:	jmp    0x8048549 <main+110>
   0x08048533 <+88>:	sub    $0x4,%esp
   0x08048536 <+91>:	pushl  -0x10(%ebp)
   0x08048539 <+94>:	pushl  -0xc(%ebp)
   0x0804853c <+97>:	push   $0x8048690
   0x08048541 <+102>:	call   0x8048370 <printf@plt>
   0x08048546 <+107>:	add    $0x10,%esp
   0x08048549 <+110>:	mov    $0x0,%eax
   0x0804854e <+115>:	mov    -0x4(%ebp),%ecx
   0x08048551 <+118>:	leave  
   0x08048552 <+119>:	lea    -0x4(%ecx),%esp
   0x08048555 <+122>:	ret 

3. 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);
}

编译运行

gdb查看堆栈情况

测试代码汇编

	.file	"gcc64.c"
	.text
	.globl	sub
	.type	sub, @function
sub:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movl	%edi, -20(%rbp)
	movl	%esi, -24(%rbp)
	movl	%edx, -28(%rbp)
	movl	%ecx, -32(%rbp)
	movl	%r8d, -36(%rbp)
	movl	%r9d, -40(%rbp)
	movl	$9, -12(%rbp)
	movl	$10, -8(%rbp)
	movl	$11, -4(%rbp)
	movl	-20(%rbp), %edx
	movl	16(%rbp), %eax
	addl	%eax, %edx
	movl	-12(%rbp), %eax
	addl	%eax, %edx
	movl	-8(%rbp), %eax
	addl	%edx, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	sub, .-sub
	.globl	main
	.type	main, @function
main:
.LFB1:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$48, %rsp
	movl	$1, -36(%rbp)
	movl	$2, -32(%rbp)
	movl	$3, -28(%rbp)
	movl	$4, -24(%rbp)
	movl	$5, -20(%rbp)
	movl	$6, -16(%rbp)
	movl	$7, -12(%rbp)
	movl	$8, -8(%rbp)
	movl	-16(%rbp), %r9d
	movl	-20(%rbp), %r8d
	movl	-24(%rbp), %ecx
	movl	-28(%rbp), %edx
	movl	-32(%rbp), %esi
	movl	-36(%rbp), %eax
	movl	-8(%rbp), %edi
	pushq	%rdi
	movl	-12(%rbp), %edi
	pushq	%rdi
	movl	%eax, %edi
	call	sub
	addq	$16, %rsp
	movl	%eax, -4(%rbp)
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	main, .-main
	.ident	"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609"
	.section	.note.GNU-stack,"",@progbits

二、在openeuler with arm64 中重现实践

环境 OpenEuler with arm64

  • sub

测试运行

汇编

main.s

	.arch armv8-a
	.file	"main.c"
	.text
	.section	.rodata
	.align	3
.LC0:
	.string	"c = %d\n"
	.text
	.align	2
	.global	main
	.type	main, %function
main:
.LFB0:
	.cfi_startproc
	stp	x29, x30, [sp, -32]!
	.cfi_def_cfa_offset 32
	.cfi_offset 29, -32
	.cfi_offset 30, -24
	add	x29, sp, 0
	.cfi_def_cfa_register 29
	mov	w0, 1
	str	w0, [x29, 28]
	mov	w0, 2
	str	w0, [x29, 24]
	mov	w0, 3
	str	w0, [x29, 20]
	ldr	w1, [x29, 24]
	ldr	w0, [x29, 28]
	bl	sub
	str	w0, [x29, 20]
	adrp	x0, .LC0
	add	x0, x0, :lo12:.LC0
	ldr	w1, [x29, 20]
	bl	printf
	mov	w0, 0
	ldp	x29, x30, [sp], 32
	.cfi_restore 30
	.cfi_restore 29
	.cfi_def_cfa 31, 0
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (GNU) 7.3.0"
	.section	.note.GNU-stack,"",@progbits

sub.s

	.arch armv8-a
	.file	"sub.c"
	.text
	.align	2
	.global	sub
	.type	sub, %function
sub:
.LFB0:
	.cfi_startproc
	sub	sp, sp, #32
	.cfi_def_cfa_offset 32
	str	w0, [sp, 12]
	str	w1, [sp, 8]
	mov	w0, 4
	str	w0, [sp, 28]
	mov	w0, 5
	str	w0, [sp, 24]
	ldr	w1, [sp, 12]
	ldr	w0, [sp, 8]
	add	w1, w1, w0
	ldr	w0, [sp, 28]
	add	w1, w1, w0
	ldr	w0, [sp, 24]
	add	w0, w1, w0
	add	sp, sp, 32
	.cfi_def_cfa_offset 0
	ret
	.cfi_endproc
.LFE0:
	.size	sub, .-sub
	.ident	"GCC: (GNU) 7.3.0"
	.section	.note.GNU-stack,"",@progbits

  • longjump

测试运行

汇编

	.arch armv8-a
	.file	"longjump.c"
	.text
	.comm	env,312,8
	.section	.rodata
	.align	3
.LC0:
	.string	"call setjmp to save environment"
	.align	3
.LC1:
	.string	"normal return"
	.align	3
.LC2:
	.string	"back to main() via long jump, r = %d a = %d\n"
	.text
	.align	2
	.global	main
	.type	main, %function
main:
.LFB0:
	.cfi_startproc
	stp	x29, x30, [sp, -32]!
	.cfi_def_cfa_offset 32
	.cfi_offset 29, -32
	.cfi_offset 30, -24
	add	x29, sp, 0
	.cfi_def_cfa_register 29
	mov	w0, 100
	str	w0, [x29, 28]
	adrp	x0, .LC0
	add	x0, x0, :lo12:.LC0
	bl	puts
	adrp	x0, env
	add	x0, x0, :lo12:env
	bl	_setjmp
	str	w0, [x29, 24]
	ldr	w0, [x29, 24]
	cmp	w0, 0
	bne	.L3
	bl	A
	adrp	x0, .LC1
	add	x0, x0, :lo12:.LC1
	bl	puts
	b	.L4
.L3:
	adrp	x0, .LC2
	add	x0, x0, :lo12:.LC2
	ldr	w2, [x29, 28]
	ldr	w1, [x29, 24]
	bl	printf
.L4:
	mov	w0, 0
	ldp	x29, x30, [sp], 32
	.cfi_restore 30
	.cfi_restore 29
	.cfi_def_cfa 31, 0
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.section	.rodata
	.align	3
.LC3:
	.string	"enter A()"
	.align	3
.LC4:
	.string	"exit A()"
	.text
	.align	2
	.global	A
	.type	A, %function
A:
.LFB1:
	.cfi_startproc
	stp	x29, x30, [sp, -16]!
	.cfi_def_cfa_offset 16
	.cfi_offset 29, -16
	.cfi_offset 30, -8
	add	x29, sp, 0
	.cfi_def_cfa_register 29
	adrp	x0, .LC3
	add	x0, x0, :lo12:.LC3
	bl	puts
	bl	B
	adrp	x0, .LC4
	add	x0, x0, :lo12:.LC4
	bl	puts
	nop
	ldp	x29, x30, [sp], 16
	.cfi_restore 30
	.cfi_restore 29
	.cfi_def_cfa 31, 0
	ret
	.cfi_endproc
.LFE1:
	.size	A, .-A
	.section	.rodata
	.align	3
.LC5:
	.string	"enter B()"
	.align	3
.LC6:
	.string	"long jump? (y|n) "
	.align	3
.LC7:
	.string	"exit B()"
	.text
	.align	2
	.global	B
	.type	B, %function
B:
.LFB2:
	.cfi_startproc
	stp	x29, x30, [sp, -16]!
	.cfi_def_cfa_offset 16
	.cfi_offset 29, -16
	.cfi_offset 30, -8
	add	x29, sp, 0
	.cfi_def_cfa_register 29
	adrp	x0, .LC5
	add	x0, x0, :lo12:.LC5
	bl	puts
	adrp	x0, .LC6
	add	x0, x0, :lo12:.LC6
	bl	printf
	bl	getchar
	cmp	w0, 121
	bne	.L8
	adrp	x0, env
	add	x0, x0, :lo12:env
	mov	w1, 1234
	bl	longjmp
.L8:
	adrp	x0, .LC7
	add	x0, x0, :lo12:.LC7
	bl	puts
	nop
	ldp	x29, x30, [sp], 16
	.cfi_restore 30
	.cfi_restore 29
	.cfi_def_cfa 31, 0
	ret
	.cfi_endproc
.LFE2:
	.size	B, .-B
	.ident	"GCC: (GNU) 7.3.0"
	.section	.note.GNU-stack,"",@progbits

  • gcc64

测试运行

汇编

	.arch armv8-a
	.file	"gcc64.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	w7, [x29, 32]
	ldr	w6, [x29, 36]
	ldr	w5, [x29, 40]
	ldr	w4, [x29, 44]
	ldr	w3, [x29, 48]
	ldr	w2, [x29, 52]
	ldr	w1, [x29, 56]
	ldr	w0, [x29, 60]
	bl	sub
	str	w0, [x29, 28]
	mov	w0, 0
	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) 7.3.0"
	.section	.note.GNU-stack,"",@progbits

代码已托管:https://gitee.com/DKY2019/xxaqxt/tree/master/2.4

posted @ 2021-12-05 21:11  20191331liyu  阅读(27)  评论(0编辑  收藏  举报