Assembly:目的是在调用函数之前加载有效地址?

问题描述 投票:0回答:1

源C代码:

 int main()
    {
      int i;
      for(i=0, i < 10; i++)
      {
        printf("Hello World!\n");
      }
    }

函数main的Intel语法x86汇编程序代码的转储:

  1.  0x000055555555463a <+0>:     push   rbp
  2.  0x000055555555463b <+1>:     mov    rbp,rsp 
  3.  0x000055555555463e <+4>:     sub    rsp,0x10
  4.  0x0000555555554642 <+8>:     mov    DWORD PTR [rbp-0x4],0x0
  5.  0x0000555555554649 <+15>:    jmp    0x55555555465b <main+33>
  6.  0x000055555555464b <+17>:    lea    rdi,[rip+0xa2]    # 0x5555555546f4
  7.  0x0000555555554652 <+24>:    call   0x555555554510 <puts@plt>
  8.  0x0000555555554657 <+29>:    add    DWORD PTR [rbp-0x4],0x1
  9.  0x000055555555465b <+33>:    cmp    DWORD PTR [rbp-0x4],0x9
  10. 0x000055555555465f <+37>:    jle    0x55555555464b <main+17>
  11. 0x0000555555554661 <+39>:    mov    eax,0x0
  12. 0x0000555555554666 <+44>:    leave  
  13. 0x0000555555554667 <+45>:    ret    

我目前正在研究“哈克,《剥削的艺术》第二版,乔恩·埃里克森(Jon Erickson),而我才刚刚开始着手解决组装问题。

我对将所提供的C代码转换为Assembly有几个问题,但是我主要想知道我的第一个问题。

第一个问题:第6行的目的是什么? (lea rdi,[rip + 0xa2])。

我当前的工作原理是,此方法用于保存下一条指令将跳转到的位置以跟踪发生的情况。我相信这行代码与源C代码中的printf函数相关。

因此,从本质上讲,它将rip + 0xa2(0x5555555546f4)的有效地址加载到寄存器rdi中,以简单地跟踪将跳转到printf函数的位置吗?

第二个问题:第11行的目的是什么? (mov eax,0x0?)我看不到EAX寄存器的先前使用,并且不确定为什么需要将其设置为0。

c assembly x86-64 disassembly
1个回答
2
投票

它将指向字符串文字的指针放入寄存器,作为put的第一个arg。您要查找的搜索词是“呼叫约定”和/或ABI。 (以及相对RIP寻址)。 Why is the address of static variables relative to the Instruction Pointer?

代码和数据之间的小偏移量(仅+0xa2)是因为.rodata节与.text被链接到同一ELF段中,并且您的程序很小。 (较新的gcc + ld版本会将其放在单独的页面中,因此它无法执行。)

在Linux PIE可执行文件中,编译器不能在位置无关的代码中使用更短的更有效的mov edi, address。可以通过gcc -fno-pie -no-pie

完成

mov eax,0在C99和C ++保证的return 0末尾实现隐式main。 EAX是所有调用约定中的返回值寄存器。

[如果不使用gcc -O2或更高版本,将不会获得像xor-zeroing(xor eax,eax)之类的窥视孔优化。

© www.soinside.com 2019 - 2024. All rights reserved.