操作系統學習之GCC內聯匯編


GCC內聯匯編(INLINE ASSEMBLY)

  什么是內聯匯編(Inline assembly)?

  1、這是GCC對C語言的擴張,就是在C代碼里面去寫匯編代碼

  2、可以直接在C的語句中插入匯編指令

 

  有何用處?

  1、C語言不足以完成所有CPU的指令, 特別是有一些特權指令,比如加載gdt表(Global Descriptor Table 全局描述符表),從而使用匯編代碼來完成

  2、用匯編在C語言中手動優化,特別是在操作系統當中,使用匯編對操作系統的掌控更為精准,更加准確。

 

  如何工作?

  1、用給定的模板和約束來生成匯編指令

  2、才C函數內形成匯編代碼

 

下面一個小例子,簡單看一下匯編代碼和內聯匯編的不同:

 

GCC內聯匯編-Example 1

 

  匯編代碼 Assembly(*.S):

    movl $0xffff, %eax     //把0xffff給eax

  內聯匯編 Inline assembly(*.c):

    asm("movl $0xffff, %%eax\n")    //1、加了一個內聯匯編關鍵字asm,把匯編代碼括起來然后用引號表示一個字符串 2、寄存器前變為%%

 

 

GCC內聯匯編-語法

  asm("assmbler template"               //assmbler template就是example 1 的那個字符串的內容(匯編語句)

    :output operands (optional)  //可選的輸出操作數(輸出寄存器)            

    :input operands   (optional)  //可選的輸入操作數(輸入寄存器)

    :clobbers              (optional)  //會被修改的寄存器

  );

 

GCC內聯匯編-Example2

Inline assembly(*.c)

  uint32_t cr0;                   //一個叫cr0的變量

  asm volatile("movl %%cr0, %0\n" :"=r"(cr0));   //把cr0里面的內容讀到%0這個寄存器當中, =r這個寄存器的內容會賦給cr0這個變量(輸出操作)

  cr0 |= 0x80000000;                 //把某一個位設成1  

  asm volatile("movl %0, %%cr0\n" ::"r"(cr0));    //再把cr0變量里的內容寫回到cr0寄存器當中。把cr0給一個寄存器,然后這個寄存器再把他里面的內容賦給cr0寄存器(輸入操作)

 

一些關鍵字的含義

volatile:No reordering; No elimination. 不需要進一步的優化,不需要進一步的調整順序

%0  :The first constraint following. 第一個用到的寄存器

r    :A constraint; GCC is free to use any register. 任意一個寄存器

 

上面的內聯匯編所對應的匯編代碼如下

Generated assembly code(*.s):

  movl %cr0, %ebx                             //cr0 --> ebx

  movl %ebx, 12(%esp)                     //ebx賦給一個局部變量12(%esp)

  orl    $-2147483648, 12(%esp)       //或操作

  movl 12(%esp), %eax                     //再給eax

  movl %eax, %cr0        //再把eax寄存器里面的內容賦給cr0

 

GCC內聯匯編-Example3

Inline assembly(*.c)

  long _res, arg1 = 2, arg2 = 22, arg3 = 222, arg4 = 233;

  _asm_volatile("int $0x80"            

    :"=a"(_res)

    :"0"(11), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4));    //把arg1給ebx, arg2給ecx,arg3給edx, arg4給esi

 

在內聯匯編當中

a = %eax, b = %ebx, c = %ecx, d = %edx, S = %esi, D = %edi, 0 = same as the first 第一個出現的寄存器

 

Generated assembly code(*.s):

  mov $11, %eax

  movl-28(%ebp), %ebx

  movl-24(%ebp), %ecx

  movl-20(%ebp), %edx

  movl-16(%ebp), %esi

  int $0x80

  movl %edi, -12(%ebp)

 

如果想要了解GCC內聯匯編更多的知識,請訪問

Inline assembly for x86 in Linux

http://www.ibm.com/developerworks/library/l-ia/index.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM