好的,所以在 C 代码中,我让它循环遍历命令行参数并打印出每个参数。我编译它并在 GDB 中打开它以查看主要功能的样子,因为我试图在汇编中做同样的事情。我最终弄清楚了我的问题所在——我的打印函数使用的寄存器与主函数使用的寄存器相同。我最终只是在函数调用之前将每个插入堆栈,然后将它们弹出。我唯一不明白的是为什么这段代码似乎没有这样做,为什么它没有遇到和我一样的问题。
0x000000000040052d <+0>: push %rbp
0x000000000040052e <+1>: mov %rsp,%rbp
0x0000000000400531 <+4>: sub $0x20,%rsp
0x0000000000400535 <+8>: mov %edi,-0x14(%rbp)
0x0000000000400538 <+11>: mov %rsi,-0x20(%rbp)
0x000000000040053c <+15>: jmp 0x400561 <main+52>
0x000000000040053e <+17>: mov -0x4(%rbp),%eax
0x0000000000400541 <+20>: cltq
0x0000000000400543 <+22>: lea 0x0(,%rax,8),%rdx
0x000000000040054b <+30>: mov -0x20(%rbp),%rax
0x000000000040054f <+34>: add %rdx,%rax
0x0000000000400552 <+37>: mov (%rax),%rax
0x0000000000400555 <+40>: mov %rax,%rdi
0x0000000000400558 <+43>: callq 0x400410 <puts@plt>
0x000000000040055d <+48>: addl $0x1,-0x4(%rbp)
0x0000000000400561 <+52>: mov -0x4(%rbp),%eax
0x0000000000400564 <+55>: cmp -0x14(%rbp),%eax
0x0000000000400567 <+58>: jl 0x40053e <main+17>
0x0000000000400569 <+60>: leaveq
0x000000000040056a <+61>: retq
欢迎任何意见,谢谢。
(gdb) disass 0x400410
Dump of assembler code for function puts@plt:
0x0000000000400410 <+0>: jmpq *0x200c02(%rip) # 0x601018 <puts@got.plt>
0x0000000000400416 <+6>: pushq $0x0
0x000000000040041b <+11>: jmpq 0x400400
End of assembler dump.
(gdb) disass 0x601018
Dump of assembler code for function puts@got.plt:
0x0000000000601018 <+0>: (bad)
0x0000000000601019 <+1>: add $0x40,%al
0x000000000060101b <+3>: add %al,(%rax)
0x000000000060101d <+5>: add %al,(%rax)
0x000000000060101f <+7>: add %ah,(%rsi)
End of assembler dump.
事实上,我什至无法找到它在 puts 中打印的位置。我一定是错过了什么,只是不知道是什么。
最佳答案
您为 puts 显示的反汇编不正确。动态加载库的库符号是动态解析的。编译器生成对 stub (过程链接表 或PLT)的调用,加载器在运行时解析该地址,第二次调用该函数时地址已解析,并且它运行得更快。在第 2 次迭代时反汇编它,您将看到实际的 puts 代码正在运行,并且您会看到寄存器被压入。
更多信息 here .
关于c - 保留寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28197841/