cc編譯c語(yǔ)言中內(nèi)嵌匯編
--AT&T and Intel 匯編語(yǔ)法對(duì)照
寄存器命名: AT&T: %eax Intel: eax
AT&T 語(yǔ)法源地址在左側(cè),目的地址在右側(cè)與Intel 方式語(yǔ)法相反 將eax值傳入ebx AT&T: movl %eax, %ebx Intel: mov ebx, eax
AT&T 語(yǔ)法在立即數(shù)前有前綴$. AT&T: movl $0x0h, %eax Intel: mov eax,0x0h
AT&T 語(yǔ)法在操作符后跟表示操作數(shù)類(lèi)型的后綴b,w,l分別表示字節(jié),字,雙字,相當(dāng)于偽操作符ptr,如果不加的話(huà)GAS會(huì)guess AT&T: movw %ax, %bx Intel: mov bx, ax
內(nèi)存尋址方式 AT&T: immed32(basepointer,indexpointer,indexscale) Intel: [basepointer + indexpointer*indexscale + immed32]
地址計(jì)算公式為: immed32 + basepointer + indexpointer * indexscale
直接尋址
AT&T: _a Intel: [_a]
間接尋址 AT&T: (%eax) Intel: [eax]
相對(duì)尋址 AT&T: _variable(%eax) Intel: [eax + _variable]
AT&T: _array(,%eax,4) Intel: [eax*4 + array]
C 代碼: *(p+1) p定義為char * AT&T: 1(%eax) where eax has the value of p Intel: [eax + 1]
結(jié)構(gòu)體數(shù)組尋址,結(jié)構(gòu)體長(zhǎng)度為8,下標(biāo)存于eax,結(jié)構(gòu)體內(nèi)偏移地址存于ebx,_array為結(jié)構(gòu)體數(shù)組首地址
AT&T: _array(%ebx,%eax,8) Intel: [ebx + eax*8 + _array] 函數(shù)內(nèi)部實(shí)現(xiàn)交換 1、輸入與輸出變量相同 匯編代碼部分標(biāo)準(zhǔn)的交換實(shí)現(xiàn),輸入部分用0寄存器表示"=r"(a)中所指定的寄存器即輸入與輸出變量相同 int main() { 804842c: mov 0xfffffff4(%ebp),%ecx int a = 10, b = 0; 804842f: mov 0xfffffff0(%ebp),%edx printf("before swap: a = %2d, b = %2d\n", a , b); 8048432: mov %ecx,%ebx __asm__("nop; 8048434: mov %edx,%esi movl %0, %%eax; 8048436: nop movl %1, %0; 8048437: mov %ebx,%eax movl %%eax, %1; 8048439: mov %esi,%ebx nop;" 804843b: mov %eax,%esi : 804843d: nop "=r"(a), "=r"(b) 804843e: mov %ebx,%edx : 8048440: mov %esi,%ecx "0"(a), "1"(b) 8048442: mov %edx,%eax : 8048444: mov %eax,0xfffffff4(%ebp) "%eax" 8048447: mov %ecx,%eax ); 8048449: mov %eax,0xfffffff0(%ebp) printf("after swap: a = %2d, b = %2d\n", a, b); return 0; } 2、輸入與輸出用不同的寄存器,&表示輸入輸出需要分配不同的寄存器 int main() { int a = 10, b = 0; printf("before swap: a = %2d, b = %2d\n", a, b); 804842b: mov 0xfffffff8(%ebp),%edx
__asm__("nop; 804842e:
mov 0xfffffff4(%ebp),%eax movl %2,
%1; 8048431:
nop movl %3,
%0; 8048432:
mov %edx,%ebx
nop;"
8048434: mov %eax,%ecx
:
8048436: nop
"=&r"(a), "=&r"(b)
8048437: mov %ecx,%eax
:
8048439: mov %ebx,%edx
"r"(a), "r"(b)
804843b: mov %eax,%eax
);
804843d: mov %eax,0xfffffff8(%ebp) printf("after swap: a = %2d, b = %2d\n", a , b); 8048440: mov %edx,%eax
return
0;
8048442: mov %eax,0xfffffff4(%ebp) } 3、交換函數(shù),需要間接尋址 #include <stdio.h>
void swap(int* x, int* y) 08048400 <swap>: { 8048400: push %ebp __asm__("nop; 8048401: mov %esp,%ebp movl (%0), %%eax; 8048403: push %ebx movl (%1), %%ebx; 8048404: mov 0x8(%ebp),%ecx movl %%ebx, (%0); 8048407: mov 0xc(%ebp),%edx movl %%eax, (%1); 804840a: nop nop;" 804840b: mov (%ecx),%eax : 804840d: mov (%edx),%ebx : 804840f: mov %ebx,(%ecx) "r"(x),"r"(y) 8048411: mov %eax,(%edx) : 8048413: nop "eax", "ebx", "memory" 8048414: mov (%esp,1),%ebx ;ebx還原
); 8048417:
leave ;movl %ebp, %esp; pop ebp } 8048418: ret 8048419: lea 0x0(%esi),%esi int main() { int a = 10, b = 0; printf("before swap: a = %2d, b = %2d\n", a, b); swap(&a, &b); printf("after swap: a = %2d, b = %2d\n", a, b); return 0; }
4、從匯編代碼中分離函數(shù)
1> 獲得匯編代碼 這里用加法函數(shù),源代碼為: int sum(int a, int b) { int c = a + b; return c; } 對(duì)應(yīng)的匯編代碼為 Disassembly of section .text: 00000000 <sum>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 04 sub $0x4,%esp 6: 8b 45 0c mov 0xc(%ebp),%eax 9: 03 45 08 add 0x8(%ebp),%eax c: 89 45 fc mov %eax,0xfffffffc(%ebp) f: 8b 45 fc mov 0xfffffffc(%ebp),%eax 12: 89 c0 mov %eax,%eax 14: c9 leave 15: c3 ret 16: 89 f6 mov %esi,%esi
2> 編寫(xiě)內(nèi)嵌匯編語(yǔ)言函數(shù) 分析:為函數(shù)構(gòu)建運(yùn)行時(shí)堆棧情況即可使其順利運(yùn)行,由于編譯器在函數(shù)執(zhí)行開(kāi)始和結(jié)束時(shí)會(huì)增加 routine begin: push %ebp; mov %esp, %ebp routine end: leave; ret 將上面的0, 1, 14, 15去掉,返回參數(shù)放在eax中將輸出部分設(shè)置為"=a"(r) 用eax寄存器 r 為需要的return type 步驟: i 定義return_type r 變量 ii 去掉push %ebp; mov %esp, %ebp; leave; ret iii 輸出部分為:"=a"(r):
$ vi sumassemble.c int sum(int a, int b) { int r; __asm__("sub $0x4, %%esp; movl 0xc(%%ebp), %%eax; addl 0x8(%%ebp), %%eax; movl %%eax, 0xfffffffc(%%ebp); movl 0xfffffffc(%%ebp), %%eax; movl %%eax, %%eax;" : "=a"(r) ); return r; }
Disassembly of section .text:
00000000 <sum>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 04 sub $0x4,%esp 6: 83 ec 04 sub $0x4,%esp 9: 8b 45 0c mov 0xc(%ebp),%eax c: 03 45 08 add 0x8(%ebp),%eax f: 89 45 fc mov %eax,0xfffffffc(%ebp) 12: 8b 45 fc mov 0xfffffffc(%ebp),%eax 15: 89 c0 mov %eax,%eax 17: 89 c0 mov %eax,%eax 19: 89 45 fc mov %eax,0xfffffffc(%ebp) 1c: 8b 45 fc mov 0xfffffffc(%ebp),%eax 1f: 89 c0 mov %eax,%eax 21: c9 leave 22: c3 ret 23: 90 nop 3> 編譯可執(zhí)行程序 $ vi summain.c extern int sum(int ,int); int main() { int x = sum(1,2); printf("x = %d\n", x); return 0; } $ cc -o sum_main sum_main.c sum_assemble.c $ ./sum_main
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=267929
|