| 方向 | 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 |
完整實戰範例
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;
}
關鍵技術細節
- 調用慣例一致性:C 默認 cdecl (參數右至左壓棧,調用者清棧),ASM 必須遵循
- 參數大小:32 位模式下
int 4 字節,64 位模式下前 6 個整數參數用寄存器 (RDI, RSI, RDX, RCX, R8, R9),超出部分壓棧
- 名稱修飾:C++ 會修飾符號名,跨語言調用必須用
extern "C"
- 棧對齊:x86-64 System V ABI 要求調用前
RSP % 16 == 8 (調用指令後對齊 16)
- 保存非易失性寄存器:ASM 函數若使用
RBX, RBP, R12-R15 必須保存恢復
驗證運行
$ ./foobar
the 1st one
$ echo $?
0
進階應用場景
- 性能熱點優化:關鍵循環用 SIMD 內聯組合語言
- 系統調用封裝:裸機環境、OS 內核開發
- 啟動代碼/中斷處理:Bootloader、實時系統
- 逆向工程/漏洞利用:Shellcode、ROP 鏈構造
- 上一篇文章: Windows Native 開發核心筆記:C 語言函數完整指南(聲明、定義、遞迴、可變參數、儲存類別)
- 下一篇文章: 序列點在 C 語言表達式求值中的關鍵作用
Copyright ©
程式碼之家 All Rights Reserved