C/C++/x86asm 混合编程

Posted by lzzmm on March 31, 2021
About 5 minutes to read

DCS218 - Operating Systems Lab 2021 Spring

前言

本文章介绍了 C 代码调用汇编函数的语法和汇编代码调用 C 函数的语法,以及 C/C++ 混合编程。

混合编程

global

在汇编中告诉编译器后续跟的是一个全局可见的名字,可能是函数名也可能是变量名。

extern

当进行编译时,此关键字告诉编译器它所声明的函数和变量已在其他文件中定义,可以在本模块或者文件以及其他模块或文件中使用。

extern "C"

这句话告诉编译器此语句块按 C 的特性编译和链接。由于 C++ 支持函数重载,因而函数在符号表中的名字与 C 中函数的不一样。为了能让 C 代码调用此函数,需要此语句。在 C++ 中引用 C 语言中的函数和变量时需要换用 C 编译和链接的方法,一般使用下述方式。

0
1
2
3
4
5
6
7
/* 如果采用了 C++,下述代码 extern "C" 有效 */
#ifdef __cplusplus
    extern "C" {
#endif
    ... /* 采用C编译器编译的C语言代码段 */
#ifdef __cplusplus          
    }   /* 结束使用C编译器 */
#endif

示例

  1. 在文件 c_func.c 中定义C函数 function_from_C。 在文件 cpp_func.cpp 中定义C++函数 function_from_CPP 。 在文件 asm_func.asm 中定义汇编函数 function_from_asm,在 function_from_asm 中调用 function_from_Cfunction_from_CPP 。 在文件 main.cpp 中调用汇编函数 function_from_asm

  2. 首先在文件 c_func.c 中定义C函数 function_from_C

    0
    1
    2
    3
    4
    
    #include <stdio.h>
       
    void function_from_C() {
        printf("This is a function from C.\n");
    }
    
  3. 然后在文件 cpp_func.cpp 中定义C++函数 function_from_CPP

    0
    1
    2
    3
    4
    
    #include <iostream>
       
    extern "C" void function_from_CPP() {
        std::cout << "This is a function from C++." << std::endl;
    }
    
  4. 接着在文件 asm_func.asm 中定义汇编函数 function_from_asm ,在 function_from_asm 中调用 function_from_Cfunction_from_CPP

    0
    1
    2
    3
    4
    5
    6
    7
    8
    
    [bits 32]
    global function_from_asm
    extern function_from_C
    extern function_from_CPP
       
    function_from_asm:
        call function_from_C
        call function_from_CPP
        ret
    
  5. 然后在文件 main.cpp 中调用汇编函数 function_from_asm

    0
    1
    2
    3
    4
    5
    6
    7
    8
    
    #include <iostream>
       
    extern "C" void function_from_asm();
       
    int main() {
        std::cout << "Call function from assembly." << std::endl;
        function_from_asm();
        std::cout << "Done." << std::endl;
    }
    
  6. 使用malefile将这4个文件统一编译成可重定位文件即.o文件,然后将这些.o文件链接成一个可执行文件。

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
     main.out: main.o c_func.o cpp_func.o asm_func.o
     g++ -o main.out main.o c_func.o cpp_func.o asm_func.o -m32
    
     c_func.o: c_func.c
     gcc -o c_func.o -m32 -c c_func.c
    
     cpp_func.o: cpp_func.cpp
     g++ -o cpp_func.o -m32 -c cpp_func.cpp 
    
     main.o: main.cpp
     g++ -o main.o -m32 -c main.cpp
    
     asm_func.o: asm_func.asm
     nasm -o asm_func.o -f elf32 asm_func.asm
     clean:
     rm *.o
    
  7. 运行结果如下:

    image-20210406154325213

参考

https://gitee.com/nelsoncheung/sysu-2021-spring-operating-system/tree/main

Creative Commons License本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.