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
中的內容再放到foo
C變量中;"a"(foo)
表示這段內聯彙編代碼開始運行時,foo
C變量輸入到%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
- http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html