• 39 C 语言与汇编语言混合编程


    参考

    https://blog.51cto.com/13475106/category6.html及狄泰软件相关课程

    从下图的编译过程就可以很明显的看出可执行文件的生成过程

    编译小知识
    1.源文件编译后得到目标文件-二进制文件
    2.不同语言可编译相同格式的目标文件
    3.链接器负责将目标文件组装得到可执行文件

    在这里出现的一个问题-C语言中的函数调用是如何进行的?
    在这里需要对函数调用时栈的变化进行解释

    ebp指向关键位置上半部分-高地址位置,包含了函数调用之前的信息,下部分低地址处函数调用后所使用的信息。
    汇编语言栈的变化-执行入栈出栈的操作
    C语言函数调用(如上图所示)-ebp指向当前栈顶,esp指向的也是栈顶,当函数返回时,将函数所使用堆空间释放,将栈顶指针寄存器位置改变,做法是将esp移动到基准位置ebp位置,之后ebp恢复之前的值(将其弹出)

    ,此时esp指向的是返回地址,结束之后esp指向参数的位置,在这里需要介绍调用约定的概念

    调用约定

    1.参数从右到左入栈
    2.函数调用者负责参数的入栈出栈
    3.函数本身根据约定使用栈中参数

    GCC编译器使用的栈帧布局

     ebp是函数调用以及函数返回的核心寄存器
    1.ebp寄存器位当前栈帧的基准
    2.通过ebp能够获取返回值地址、参数、局部变量等

     在接下来的会用实验来进行验证

    使用汇编语言编写Linux可执行程序

    a.定义_start标签作为程序执行的起点
    b.通过int 0x80使用内核服务(执行系统调用)

    global _start ;标签 程序入口处
    
    [section .data]
        vstr    db  "D.T.Software",0x0A
    
    [section .text]
    _start:     ;app entry
        mov edx,13
        mov ecx,vstr   ;"D.T.Software
    "
        mov ebx,1
        mov eax,4    ;sys_write
        int 0x80   
    
        mov ebx,0  
        mov eax,1  ;sys_exit
        int 0x80
    

    交互关键字
    1.global-从汇编语言中导出符号(变量或函数)
    2.extern-使用外部文件中定义的符号(变量或函数)

    示例分析

     实验运行结果-在linux下编程

     混合编程注意事项
    1.相同的目标文件格式--elf格式
    2.相同的函数调用约定--cdecl调用约定
    3.相同的活动记录(栈帧)结构-ebp基准

    实验

    代码-新建entry.asm、main.c、test.c
    代码分别为

    ;entry.asm
    global _start
    global vstr
    global vlen
    global print
    
    extern c_func
    
    [section .data]
       vstr    db    "D.T.Software", 0x0A
       vlen    dd    $ - vstr
    
    [section .text]
    _start:
        mov ebp, 0
    
        call c_func
    
        call exit
    
    print:
        push ebp
        mov ebp, esp
    
        mov edx, [ebp + 12]
        mov ecx, [ebp + 8]
        mov ebx, 1
        mov eax, 4
        int 0x80
    
        pop ebp
        ret
    
    exit:
        mov ebx, 0
        mov eax, 1
        int 0x80
    
    main.c      
    extern void print(char*, int len);
    extern char vstr[];
    extern int vlen;
    
    int c_func()
    {
        char* delphi = "Delphi
    ";
    
        print(vstr, vlen);
    
        return 0;
    }
    
    test.c
    
    extern void print(char*, int len);
    extern char vstr[];
    extern int vlen;
    
    int c_func()
    {
        char* delphi = "Delphi
    ";
    
        print(vstr, vlen);
    
        return 0;
    }
    

     运行结果-c语言与汇编
    在这里需要使用gcc将其编译成目标文件,最后进行链接

    小结

    C语言与汇编语言在满足以下条件时可以混合编程
    1.遵循相同的函数调用约定
    2.遵循相同的目标文件格式

     

      

  • 相关阅读:
    Python3小练习2——(汉诺塔的移动),递归
    Python3小练习1——(ax*x+ bx + c = 0的解)
    SSRS数据导出Excel多出空白列
    ETL 压缩文件(makecab) 并邮件发送
    关于System.Web.Script.Serialization命名空间的引用
    如何通过VIsual Studio安装程序修改VS2017?
    如何其他服务器能够连接自己本机的数据库?
    SSAS表格模型部署问题
    表格模型——安装实例
    Leetcode 76题:最小覆盖子串 滑动窗口经典题
  • 原文地址:https://www.cnblogs.com/lh03061238/p/14604838.html
Copyright © 2020-2023  润新知