首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 與組合語言混合編程:相互調用原理、編譯鏈接流程與實戰範例

     編輯:關於C語言

核心原理:編譯 → 目標文件 → 鏈接

C 與組合語言 (ASM) 互調的本質:各自編譯為同一格式目標文件 (ELF/COFF),鏈接器解析符號引用,生成最終可執行文件。

工具鏈與命令 (Linux x86-32 示例)

# C 文件編譯
gcc -m32 -c -o bar.o bar.c        # 生成 bar.o (含符號表、重定位表)

# ASM 文件編譯
nasm -f elf -o foo.o foo.asm      # 生成 foo.o

# 鏈接
ld -m elf_i386 -s -o foobar foo.o bar.o  # 解析符號,生成可執行文件

符號可見性規範

完整實戰範例

foo.asm (NASM 語法)

section .data
    num1 dq 3          ; 64 位整數 3
    num2 dq 4          ; 64 位整數 4

section .text
    global main
    global myprint
    extern choose      ; 聲明 C 函數

main:
    push qword [num2]  ; 參數右至左壓棧
    push qword [num1]
    call choose        ; 調用 C 函數
    add esp, 16        ; 清理棧 (2 個 64 位參數 = 16 字節)

    mov ebx, 0         ; 返回碼 0
    mov eax, 1         ; sys_exit
    int 0x80

myprint:               ; 供 C 調用的打印函數
    mov edx, [esp+8]   ; 參數 2: 長度
    mov ecx, [esp+4]   ; 參數 1: 字串指標
    mov ebx, 1         ; stdout
    mov eax, 4         ; sys_write
    int 0x80
    ret

bar.c

#include <string.h>

void myprint(char *msg, int len);  // 聲明 ASM 函數

int choose(int a, int b) {
    if (a >= b) {
        myprint("the 1st one", 13);
    } else {
        myprint("the 2nd one", 13);
    }
    return 0;
}

關鍵技術細節

  1. 調用慣例一致性:C 默認 cdecl (參數右至左壓棧,調用者清棧),ASM 必須遵循
  2. 參數大小:32 位模式下 int 4 字節,64 位模式下前 6 個整數參數用寄存器 (RDI, RSI, RDX, RCX, R8, R9),超出部分壓棧
  3. 名稱修飾:C++ 會修飾符號名,跨語言調用必須用 extern "C"
  4. 棧對齊:x86-64 System V ABI 要求調用前 RSP % 16 == 8 (調用指令後對齊 16)
  5. 保存非易失性寄存器:ASM 函數若使用 RBX, RBP, R12-R15 必須保存恢復

驗證運行

$ ./foobar
the 1st one
$ echo $?
0

進階應用場景

  • 性能熱點優化:關鍵循環用 SIMD 內聯組合語言
  • 系統調用封裝:裸機環境、OS 內核開發
  • 啟動代碼/中斷處理:Bootloader、實時系統
  • 逆向工程/漏洞利用:Shellcode、ROP 鏈構造
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方向C 代碼ASM 代碼 (NASM)
C 調用 ASM 函數extern int asm_func(int);global asm_func + asm_func:
ASM 調用 C 函數int c_func(int) { ... }extern c_func + call c_func