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

GCC 環境下 C 與組合語言混合編程完整指南:AT&T 語法、函數調用約定與 Makefile 實戰

     編輯:關於C語言

專案結構

endian_demo.c   // C 主程式,實現 main()
function.S      // AT&T 語法組合語言,實現 swapEnds、writeHexASCII
Makefile        // 編譯腳本

關鍵知識點:GCC x86 函數調用約定

  • 參數傳遞:通過堆疊,呼叫端壓入參數,被呼叫端從 %esp 取值。
  • 返回值:通過 %eax 傳回。
  • 堆疊幀:%ebp 為幀指標,區域變數用負偏移,參數用正偏移(4(%esp) 為第一參數,8(%esp) 為第二參數...)。

組合語言實作細節

函數導出聲明

.text
.code32
.globl writeHexASCII
.globl swapEnds

writeHexASCII(char *buffer, unsigned int number)

將整數轉為 8 位十六進位 ASCII 字串存入緩衝區。

writeHexASCII:
    movl $28, %ecx        # 位移量初始值 (7*4)
    movl $0, %edi         # 迴圈計數器
    mov 0x4(%esp), %edx   # buffer 位址
    jmp if_loop_end
loop_start:
    mov 0x8(%esp), %eax   # number
    shr %cl, %eax         # 右移取 4 bits
    and $0xf, %eax        # 取低 4 位
    cmpl $9, %eax
    jg hex_abcdef
hex_0_9:
    addl $0x30, %eax      # '0'-'9'
    jmp hex_convert_complete
hex_abcdef:
    addl $0x57, %eax      # 'A'-'F'
hex_convert_complete:
    mov %al, (%edx)       # 存入 buffer
    add $1, %edx
    subl $4, %ecx         # 下一組 4 bits
    addl $1, %edi
if_loop_end:
    cmpl $7, %edi
    jle loop_start
    movb $0x0, (%edx)     # 結尾 \0
    ret

swapEnds(unsigned int x) — 位元組序大小端轉換

swapEnds:
    mov 4(%esp), %eax
    and $0xff000000, %eax
    shr $24, %eax
    mov %eax, %edi        # 保存最高位元組到 edi

    movzbl 4(%esp), %eax  # 取最低位元組 (零擴展)
    shl $24, %eax
    or %eax, %edi         # 合併到 edi

    mov 4(%esp), %eax
    and $0xff0000, %eax
    shr $8, %eax
    or %eax, %edi

    mov 4(%esp), %eax
    and $0xff00, %eax
    shl $8, %eax
    or %eax, %edi

    mov %edi, %eax        # 結果放入 eax 返回
    ret

C 主程式介面聲明

extern void writeHexASCII(char *buffer, unsigned int number);
extern unsigned int swapEnds(unsigned int x);

Makefile

all: endian_demo

endian_demo: function.o endian_demo.o
    gcc -o $@ function.o endian_demo.o

function.o: function.S
    gcc -o $@ -c $<

endian_demo.o: endian_demo.c
    gcc -o $@ -c $< -ansi

clean:
    rm -f *.o endian_demo

編譯執行

$ make
$ ./endian_demo 1 255 1334
1: 00000001 <-> 01000000 = 16777216
255: 000000FF <-> FF000000 = 4278190080
1334: 00000536 <-> 36050000 = 905969664

假設環境

  • Intel x86 32-bit Linux
  • 已安裝 GNU make、gcc、as

來源:「techlife」博客,原文連結:https://techlife.blog.51cto.com/212583/55348。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved