2015-10-25 82 views
1

我編譯使用cc -g -O0 -m32下一個代碼的地址:GCC產生`call`下一條指令

void f() { 
    int l; 
    short s; 
    char c; 

    l = 0xdeadbeef; 
    s = l; 
    c = l; 

    printf("l = 0x%x (%d bits)\n", l, sizeof(l) * 8); 
    printf("s = 0x%x (%d bits)\n", s, sizeof(s) * 8); 
    printf("c = 0x%x (%d bits)\n", c, sizeof(c) * 8); 
} 

什麼是以下行的目的是什麼?

0x00001e89 <+9>: call 0x1e8e <f+14> 
    0x00001e8e <+14>: pop %eax 
    0x00001e8f <+15>: lea 0xe8(%eax),%ecx 

當我拆機用gdb

(gdb) disassemble f 
Dump of assembler code for function f: 
    0x00001e80 <+0>: push %ebp 
    0x00001e81 <+1>: mov %esp,%ebp 
    0x00001e83 <+3>: push %ebx 
    0x00001e84 <+4>: push %edi 
    0x00001e85 <+5>: push %esi 
    0x00001e86 <+6>: sub $0x3c,%esp 
    0x00001e89 <+9>: call 0x1e8e <f+14> 
    0x00001e8e <+14>: pop %eax 
    0x00001e8f <+15>: lea 0xe8(%eax),%ecx 
    0x00001e95 <+21>: mov $0x20,%edx 
    0x00001e9a <+26>: movl $0xdeadbeef,-0x10(%ebp) 
    0x00001ea1 <+33>: mov -0x10(%ebp),%esi 
    0x00001ea4 <+36>: mov %si,%di 
    0x00001ea7 <+39>: mov %di,-0x12(%ebp) 
    0x00001eab <+43>: mov -0x10(%ebp),%esi 
    0x00001eae <+46>: mov %esi,%ebx 
    0x00001eb0 <+48>: mov %bl,-0x13(%ebp) 
    0x00001eb3 <+51>: mov -0x10(%ebp),%esi 
    0x00001eb6 <+54>: mov %ecx,(%esp) 
    0x00001eb9 <+57>: mov %esi,0x4(%esp) 
    0x00001ebd <+61>: movl $0x20,0x8(%esp) 
    0x00001ec5 <+69>: mov %eax,-0x18(%ebp) 
    0x00001ec8 <+72>: mov %edx,-0x1c(%ebp) 
    0x00001ecb <+75>: call 0x1f5a 
    0x00001ed0 <+80>: mov -0x18(%ebp),%ecx 
    0x00001ed3 <+83>: lea 0xfc(%ecx),%edx 
    0x00001ed9 <+89>: mov $0x10,%esi 
    0x00001ede <+94>: movswl -0x12(%ebp),%ecx 
    0x00001ee2 <+98>: mov %edx,(%esp) 
    0x00001ee5 <+101>: mov %ecx,0x4(%esp) 
    0x00001ee9 <+105>: movl $0x10,0x8(%esp) 
    0x00001ef1 <+113>: mov %eax,-0x20(%ebp) 
    0x00001ef4 <+116>: mov %esi,-0x24(%ebp) 
    0x00001ef7 <+119>: call 0x1f5a 
    0x00001efc <+124>: mov -0x18(%ebp),%ecx 
    0x00001eff <+127>: lea 0x110(%ecx),%edx 
    0x00001f05 <+133>: mov $0x8,%esi 
    0x00001f0a <+138>: movsbl -0x13(%ebp),%ecx 
    0x00001f0e <+142>: mov %edx,(%esp) 
    0x00001f11 <+145>: mov %ecx,0x4(%esp) 
    0x00001f15 <+149>: movl $0x8,0x8(%esp) 
    0x00001f1d <+157>: mov %eax,-0x28(%ebp) 
    0x00001f20 <+160>: mov %esi,-0x2c(%ebp) 
    0x00001f23 <+163>: call 0x1f5a 
    0x00001f28 <+168>: mov %eax,-0x30(%ebp) 
    0x00001f2b <+171>: add $0x3c,%esp 
    0x00001f2e <+174>: pop %esi 
    0x00001f2f <+175>: pop %edi 
    0x00001f30 <+176>: pop %ebx 
    0x00001f31 <+177>: pop %ebp 
    0x00001f32 <+178>: ret  
End of assembler dump. 

回答

1

這是一招生成位置無關的代碼。你可以看到下一條指令是一個pop %eax,它將從堆棧中獲取返回地址。當然,返回地址是pop本身的地址,因此它獲得指令的絕對地址,因此它可以用作訪問與代碼相關的東西的基礎。

它立即用於獲取第一個printf調用(字面格式字符串)的第一個參數。您可以看到ecx是基於eax在線+15加載的,然後ecx根據調用約定在第一個參數槽中的第+54行處寫入堆棧。

該參考點也存儲在行+69。與第一個printf一樣,它隨後被重新用於後續格式字符串,請參閱行+83+127

+0

'%eax'加載指令絕對地址='0x00001e8e'(或'')。地址0x00001e8e + 0xe8中應該出現什麼?即爲什麼該地址的內容被加載到'%ecx'中? (通過地址'<+15>' – Bush

+0

的指令對不起,我錯過了代碼如何使用它。請參閱更新的答案。注意,使用'gcc -S'應該產生更易讀的代碼,甚至可以看到被引用的格式字符串。 – Jester