2.5 OpenEuler 中C与汇编的混合编程

2.5 OpenEuler 中C与汇编的混合编程

任务详情

  1. 在X86_64架构下实践2.5中的内容,提交代码和实践截图
  2. 把2.5的内容在OpenEuler中重新实践一遍,提交相关代码和截图

任务一x86_64实现

操作环境:Ubuntu Kylin(x86_64)

2.5.1用汇编代码编程

将C代码编译成汇编代码

a.c file

#include <stdio.h>

extern int B();
int A(int x, int y){
        int d, e, f;
        d = 4;
        e = 5;
        f = 6;
        f = B(d,e);
}

a.s file

A:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        movl    $4, -20(%ebp)
        movl    $5, -16(%ebp)
        movl    $6, -12(%ebp)
        subl    $8, %esp
        pushl   -16(%ebp)
        pushl   -20(%ebp)
        call    B
        addl    $16, %esp
        movl    %eax, -12(%ebp)
        nop
        leave
        ret

2.5.2用汇编语言实现函数

示例2.2

获取CPU寄存器

s.s file

.global get_esp, get_ebp

get_esp:
        movl %esp, %eax
        ret
get_ebp:
        movl %ebp, %eax
        ret

print.c

#include <stdio.h>
int main(){
        int ebp, esp;
        ebp = get_ebp();
        esp = get_esp();
        printf("ebp=%8x esp=%8x\n", ebp, esp);
}

编译运行截图

示例2.3

用汇编语言编写mysum函数

mysum.s

.code32
        .text
        .global mysum, printf

mysum:
        pushl %ebp
        movl %esp, %ebp

        movl 8(%ebp), %eax
        addl 12(%ebp), %eax

        movl %ebp, %esp
        pop %ebp
        ret

sum.c

#include <stdio.h>
int main(){
        int a, b, c;
        a = 123;
        b = 456;
        c = mysum(a, b);
        printf("c=%d\n",c);
}

编译运行截图

2.5.3从汇编中调用C函数

示例2.4:访问全局变量并调用printf()

sub.s

.text
        .global sub, a, d, printf

sub:
        pushl %ebp
        movl %esp, %ebp

        pushl b
        pushl a
        pushl $fmt
        call printf
        addl $12, %esp
        leave
        ret

        .data
fmt:    .asciz "a=%d b=%d\n"

submain.c

#include <stdio.h>
int a, b;
int main(){
        a = 100;
        b = 200;
        sub();
}

编译运行截图

任务二OpenEuler实现

  • 因为openeuler系统不支持32位,所以需要将32位汇编代码改为64位汇编;

  • 根据书2.4.3可知在64位模式下寄存器扩展,调用函数时参数依次进入edi,esi,edx,ecx,r8d,r9d不需要再在调用前进行压栈操作;

  • 64位模式保留红色栈区128字节,即默认进行指令subl $128, %rsp,所以一般情况下不进行压栈操作,直接对栈帧%rbp进行操作即可;

  • 进入叶过程中需要对寄存器中传入参数保留在栈中;

  • 因为在64位模式下,对寄存器为64位操作,部分指令需要改变

操作环境:OpenEuler(wsl)

2.5.1用汇编代码编程

将C代码编译成汇编代码

a.c file

#include <stdio.h>

extern int B();
int A(int x, int y){
        int d, e, f;
        d = 4;
        e = 5;
        f = 6;
        f = B(d,e);
}

a.s file

A:
        pushq   %rbp
        movq    %rsp, %rbp
        subq    $32, %rsp
        movl    %edi, -20(%rbp)
        movl    %esi, -24(%rbp)
        movl    $4, -4(%rbp)
        movl    $5, -8(%rbp)
        movl    $6, -12(%rbp)
        movl    -8(%rbp), %edx
        movl    -4(%rbp), %eax
        movl    %edx, %esi
        movl    %eax, %edi
        movl    $0, %eax
        call    B
        movl    %eax, -12(%rbp)
        leave
        ret

2.5.2用汇编语言实现函数

示例2.2

获取CPU寄存器

s.s file

 .globl get_esp, get_ebp

get_esp:
        movq %rsp, %rax
        ret

get_ebp:
        movq %rsp, %rax
        ret

print.c

#include <stdio.h>
int main(){
        int ebp, esp;
        ebp = get_ebp();
        esp = get_esp();
        printf("rbp=%8x rsp=%8x\n", ebp, esp);
}

编译运行截图

示例2.3

用汇编语言编写mysum函数

mysum.s

        .text
        .global mysum, printf

mysum:
        pushq %rbp
        movq %rsp, %rbp

        movl %edi, -4(%rbp)
        movl %esi, -8(%rbp)

        movl -8(%rbp), %eax
        addl -4(%rbp), %eax

        popq %rbp
        ret

sum.c

#include <stdio.h>
int main(){
        int a, b, c;
        a = 123;
        b = 456;
        c = mysum(a, b);
        printf("c=%d\n",c);
}

编译运行截图

2.5.3从汇编中调用C函数

示例2.4:访问全局变量并调用printf()

sub.s

.text
        .global sub, a, d, printf

sub:
        pushq %rbp
        movq %rsp, %rbp

        movl b, %edx
        movl a, %esi
        movl $fmt, %edi
        call printf
        leave
        ret

        .data
fmt:    .asciz "a=%d b=%d\n"

submain.c

#include <stdio.h>
int a, b;
int main(){
        a = 100;
        b = 200;
        sub();
}

编译运行截图

posted @ 2021-12-05 15:38  WangYuHan20191323  阅读(45)  评论(0编辑  收藏  举报