• 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

  • 相关阅读:
    [转]ORACLE 异常错误处理
    Oracle 返回结果集的 存储过程
    [转]Oracle字符串拼接的方法
    [转]Install App to SD
    [转]重新分配内置存储空间 android手机
    Oracle SQL Developer 操作
    [转].net 调用oracle存储过程返回多个记录集
    [转]使用ADO.NET访问Oracle存储过程
    [转]Oracle ORA-01403: no data found Exception SYS_REFCURSOR
    [转]Oracle开发专题之:%TYPE 和 %ROWTYPE
  • 原文地址:https://www.cnblogs.com/DKYcaiji/p/15647128.html
Copyright © 2020-2023  润新知