Function call test in C language in OpenEuler (optional)

Operation requirements

  1. On x86_ Contents in practice 2.4 under 64 architecture
  2. Check the contents of the register through GDB and fill in the specific values in the figure in the textbook
  3. The C code of 2.4 is practiced again in OpenEuler, and the logic block diagram of ARM64 is drawn
  4. The experimental content can only get the corresponding score after oral defense

Practice flow 1 - in x86_ Under 64 architecture

Code and assembly conversion

According to the textbook, there are differences in parameter transfer between 64 bit and 32 bit. 32-bit transfers parameters directly through the stack, while 64-bit transfers the first six parameters into rdi, rsi, rdx, rcx, r8 and r9 in turn, and then the remaining parameters are passed through the stack like 32-bit. In the 2.5 operation, a segment error occurs when calling printf function directly on 64 bit with 32-bit code. The textbook directly explains here, This difference is the cause.
Example code t.c:

#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;

In x86_ Convert openEuler of 64 to assembly code and view:


	.file	"t.c"
	.globl	sub
	.type	sub, @function
	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, -4(%rbp)
	movl	$10, -8(%rbp)
	movl	$11, -12(%rbp)
	movl	-20(%rbp), %edx
	movl	16(%rbp), %eax
	addl	%eax, %edx
	movl	-4(%rbp), %eax
	addl	%eax, %edx
	movl	-8(%rbp), %eax
	addl	%edx, %eax
	popq	%rbp
	.cfi_def_cfa 7, 8
	.size	sub, .-sub
	.globl	main
	.type	main, @function
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$48, %rsp
	movl	$1, -4(%rbp)
	movl	$2, -8(%rbp)
	movl	$3, -12(%rbp)
	movl	$4, -16(%rbp)
	movl	$5, -20(%rbp)
	movl	$6, -24(%rbp)
	movl	$7, -28(%rbp)
	movl	$8, -32(%rbp)
	movl	-24(%rbp), %r9d
	movl	-20(%rbp), %r8d
	movl	-16(%rbp), %ecx
	movl	-12(%rbp), %edx
	movl	-8(%rbp), %esi
	movl	-4(%rbp), %eax
	movl	-32(%rbp), %edi
	pushq	%rdi
	movl	-28(%rbp), %edi
	pushq	%rdi
	movl	%eax, %edi
	call	sub
	addq	$16, %rsp
	movl	%eax, -36(%rbp)
	movl	$0, %eax
	.cfi_def_cfa 7, 8
	.size	main, .-main
	.ident	"GCC: (GNU) 7.3.0"
	.section	.note.GNU-stack,"",@progbits

gdb analysis

Use gcc -g t.s -o t to compile t.s. you can directly debug the assembly code through cgdb t and view it.

Use b main, r to start stepping.

Before the function is executed, it will push its rbp onto the stack.
Use s to step.

The first is the variable definition of the main function. First, esp is reduced by 48 to provide space for a~h.
View the value of the register: use i r to view the value in the corresponding memory, and use x 0x012345678abcdef

Corresponding to the value of ebp in the figure above, view the value of a~h in the stack:

Analyze the stack state after saving the value of main function:

After entering the sub function, the numbers in the six registers are stored on the stack before operation:

However, I see that the code does not restore the two extra parameters (g and h).
In operation, you need to add a, g, u and v.
Where u and v are defined in the sub function, a is passed in through the register, and h is passed through the stack. Through analysis, the value of h is 16(%rbp).
The box in the following figure is the addition part.

The following figure shows the stack analysis diagram:

After the final calculation, restore rbp and return to. The return value exists in rax.

Practice process 2 - under Arm64 architecture

Huawei Kunpeng server is based on Arm64 architecture.

Code and assembly conversion

t.s under arm64 architecture:

 .cpu generic+fp+simd
        .file   "t.c"
        .align  2
        .global sub
        .type   sub, %function
        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
        .size   sub, .-sub
        .align  2
        .global main
        .type   main, %function
        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
        .size   main, .-main
        .ident  "GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-39)"
        .section        .note.GNU-stack,"",%progbits

Parameter transfer process analysis

In arm: str is storage and ldr is fetch.

In the above figure, save a-h to the corresponding positions of x29,60~x29,32.
Stack and flowchart after analysis:

It can be seen that the function parameter transfer in arm64 in this example is realized through w0-w7.

Posted on Sun, 05 Dec 2021 13:51:21 -0500 by SalokinX