zoukankan      html  css  js  c++  java
  • 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();
    }
    

    编译运行截图

  • 相关阅读:
    hdu 4396(spfs/二维最短路)
    hdu 4360(最短路变形)
    hdu 3501(欧拉函数的应用)
    bnu 4359(数位dp)
    用Hermite插值方法估计积分值
    虞旦盛老师 的《数学分析续》课件
    数值积分中的梯形法则
    数值积分中的梯形法则
    辛普森三八律
    利用自然数的标准分解证明可数集合的所有有限子集形成的集合是可数集
  • 原文地址:https://www.cnblogs.com/WANGYUHAN/p/15645792.html
Copyright © 2011-2022 走看看