2014-08-30 86 views
4

我有這樣的代碼如下函數中:Gcc內嵌程序集「'asm'操作數具有不可能的約束」是什麼意思?

void makeSystemCall(uint32_t num, uint32_t param1, uint32_t param2, uint32_t param3){ 
    asm volatile (
     "mov %0, %%eax\n\t"//Move num to eax 
     "mov %1, %%ebx\n\t"//Move param1 to ebx 
     "mov %2, %%ecx\n\t"//Move param2 to ecx 
     "mov %3, %%edx\n\t"//Move param3 to edx 
     "int $0x80"//Call interrupt. Data in eax, ebx, ecx and edx 
     : //No output params 
     : "r" (num), "r" (param1), "r" (param2), "r" (param3)//Input params 
     : "%eax", "%ebx", "%ecx", "%edx" //This handles register state pushing and popping? 
    ); 
} 

現在我不知道爲什麼這是行不通的。 Gcc說:「錯誤:'asm'操作數具有不可能的約束」我一直在遵循gcc內聯彙編教程,我認爲這將是從c代碼到內聯彙編塊參數的正確方法。

另外我使用爲32位x86構建的gcc交叉編譯器。

+0

不要這樣做。使用可用的[syscalls(2)](http://man7.org/linux/man-pages/man2/syscalls.2.html)或者如果您需要間接[syscall(2)](http:// man7 .ORG/LINUX /人-頁/男2/syscall.2.html)。他們會使用[VDSO](https://en.wikipedia.org/wiki/VDSO),所以會更快。 – 2014-08-30 06:50:00

+0

@BasileStarynkevitch我有點開發我自己的操作系統在這裏,如果你不介意... – 2014-08-30 06:50:43

+0

然後嘗試移植一些現有的libc到它。 [musl-libc](http://musl-libc.org/)有非常可讀的源代碼,它將教你如何去做。並使用'SYSENTER'機器調用。 – 2014-08-30 06:51:37

回答

8

使用「r」約束強制編譯器在使用該暫存寄存器作爲您的mov指令之一之前將該參數加載到暫存寄存器中。沒有可用的4個暫存寄存器。

改爲使用「g」約束。無論如何,這是更高效的,因爲編譯器可以直接在你的指令中訪問參數,使用一個幀指針偏移內存訪問到目標寄存器,而不是將其寫入一個臨時寄存器,然後將臨時寄存器移動到最終目的地。

+0

謝謝。將'r'改爲'g',它的作用就像一個魅力:D。 – 2014-08-30 06:59:17