GCC內聯彙編(1)Get started

鍾超發表於2012-07-09

GCC內聯彙編(1)Get started

  • 作者:柳大·Poechant(鍾超)
  • 郵箱:zhongchao.ustc#gmail.com(# -> @)
  • 部落格:Blog.CSDN.net/Poechant
  • 日期:July 7th, 2012

1. Intel vs. AT&T

其實並不是要說 Intel 和 AT&T PK 的故事,哈哈。因為首先要熟悉 Intel syntax 的彙編指令寫法和 AT&T syntax 彙編指令的寫法,所以看下錶:


+------------------------------+------------------------------------+
|       Intel Code             |      AT&T Code                     |
+------------------------------+------------------------------------+
| mov     eax,1                |  movl    $1,%eax                   |   
| mov     ebx,0ffh             |  movl    $0xff,%ebx                |   
| int     80h                  |  int     $0x80                     |   
| mov     ebx, eax             |  movl    %eax, %ebx                |
| mov     eax,[ecx]            |  movl    (%ecx),%eax               |
| mov     eax,[ebx+3]          |  movl    3(%ebx),%eax              | 
| mov     eax,[ebx+20h]        |  movl    0x20(%ebx),%eax           |
| add     eax,[ebx+ecx*2h]     |  addl    (%ebx,%ecx,0x2),%eax      |
| lea     eax,[ebx+ecx]        |  leal    (%ebx,%ecx),%eax          |
| sub     eax,[ebx+ecx*4h-20h] |  subl    -0x20(%ebx,%ecx,0x4),%eax |
+------------------------------+------------------------------------+

2. 示例

看一個用內聯彙編寫的例子,計算兩數的和:


#include <stdio.h>                                                                                                                                                                                   
int main(void) {

    int foo = 10, bar = 15;

    __asm__ __volatile__ (
        "addl   %%ebx, %%eax"
        :"=a"(foo)
        :"a"(foo), "b"(bar)
        :"%eax"
    );

    printf("foo + bar = %d\n", foo);

    return 0;
}

該程式作如下解釋:

  • __asm__用於表示這是一個內聯彙編程式碼段;
  • 如果使用了__volatile修飾符,則這段內聯彙編程式碼不會被編譯器優化掉,但是如果只是做簡單的計算,不會產生任何可能的 side effects,則最好不要加這個修飾符,這樣可以使編譯器幫助我們優化程式碼;
  • "=a"(foo)"表示這段內聯彙編程式碼執行結束後,輸出結果放在暫存器%eax中,然後%eax中的內容再放到fooC變數中;
  • "a"(foo)表示這段內聯彙編程式碼開始執行時,fooC變數輸入到%eax暫存器中,多個輸入值可以用上面示例中的方式表達。
  • 以冒號開始的那兩行,其實都是“約束”,這個是constraint的直譯,其實你可以理解為邊界條件,即輸入輸出條件。
  • 最後一個冒號開始的行,是告訴編譯器,哪些暫存器的值會在內聯彙編程式碼的執行過程中被篡改,因此不要使用這些暫存器去儲存值。這裡就是%eax的值會被篡改的意思。

3. 暫存器縮寫

+---+--------------------+
| r |    Register(s)     |
+---+--------------------+
| a |   %eax, %ax, %al   |
| b |   %ebx, %bx, %bl   |
| c |   %ecx, %cx, %cl   |
| d |   %edx, %dx, %dl   |
| S |   %esi, %si        |
| D |   %edi, %di        |
+---+--------------------+

Reference

  1. http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

-

轉載請註明來自柳大的CSDN部落格:Blog.CSDN.net/Poechant

-

相關文章