GCC Inline Assembly

2017-03-26 misc asm c

因為想要在 C 裡寫一些組合語言,所以就研究了一下怎麼寫,發現事情並不是像我想的這麼簡單故筆記之。

GCC 准許我們使用行內組語依照如下格式

asm("asm template"               //           組合語言
	:output operands             //(optional) 輸出運算元
    :input operands              //(optional) 輸入運算元
    :list of clobbered registers //(optional) 被更動的暫存器

組合語言使用雙引號 (") 包住,若為多行組語則須在結尾加上 \n\t 最後一行除外

因為 GCC 將組語一行一行指令當成字串

以下為簡單範例

#include <stdio.h> // simple.c
int main(void) {
    int foo=10, bar=5, result;
    asm("add ebx, eax":"=b"(result):"a"(foo), "b"(bar));
    printf("foo + bar = %d\n", result);
    return 0;
}

範例中 a 就代表 eax, b 表示 ebx 其他以此類推

然後編譯一下 gcc -o simple simple.c

然後你就會得到錯誤如下

simple.c Assembler messages :

simple.c:5: Error: too many memory references for `add’

這奇怪的錯誤訊息著實讓人看不懂,其實只是我們使用的是 intel syntax 去寫,可是 GCC 預設的是 AT&T

所以我們只要給個參數就好 gcc -masm=intel -o simple simple.c 這樣就可以執行無誤了

當然我們也可以使用 system call

#include <stdio.h>
int main(void){
    asm(
        "mov eax, 0x1\n\t"
        "mov ebx, 0x2a\n\t"
        "int 0x80");
    return 0;
}

一樣編譯並執行之,使用 echo $? 可以看到最後一行指令的 exit code 為 42 代表呼叫成功。

所以你其實也可以完完全全在 C 裡寫組語過日子

//hell.c
#include <stdio.h>

char *line = "Hello world!\n";
/*
eax = syscall numer
ebx = unsigned int fd
ecx = const void *buf
edx = size_t count
*/
void sayHi(){
    asm(
        "mov eax, 0x4\n\t"
        "mov ebx, 0x1\n\t"
        "mov ecx, %0\n\t"
        "mov edx, 0xd\n\t"
        "int 0x80"
        ::"r"(line):"eax", "ebx", "ecx", "edx");
}

//eax = syscall number, ebx = int error_code
void exit(){ 
    asm(
        "mov eax, 0x1\n\t"
        "mov ebx, 0x2a\n\t"
        "int 0x80");
}

notmain(){
    echo();
    exit();
}

我們全部都使用 inline assembly 來撰寫一個 Hello world

其中 “r” 代表 register, 而 %0 代表第一個參數,也就是 input operands 的第一個,也就是 line

這邊我們編譯的時候略有不同

gcc -c -m32 -fno-builtin -masm=intel hell.c

ld -static -m elf_i386 -e notmain -o hell hell.o

  • -fno-builtin 參數表示我們不使用內建的函式
  • -c 代表只編譯不連結
  • -m32 代表該程式要編譯成 32 位元
  • -m elf_i386 同上原因
  • -static 使用靜態連結
  • -e notmain 可以將程式的入口,由預設的 _start 改為 notmain

大致上簡單的 inline assembly 就是如此了,不過這些都只是冰山一角
還有更多的東西可以挖掘在這裡這裡