回复:反汇编的C++代码中一些指令的含义(使用gdb v.13.2反汇编, 使用 g++ v.13.1.0 编译,带有 -std=c++23、-g 和 -o 标志)。
大多数说明及其目的可以通过搜索有关该主题的书籍和网站来找到,但有一行仅部分解释,另一行没有我能找到的任何解释。这些问题的灵感来自以下内容,取自 gdb 程序集转储:
Dump of assembler code for function _ZdlPvy:
0x00007ff75cdb17f0 <+0>: jmp *0x8a92(%rip) # 0x7ff75cdba288 <__imp__ZdlPvy>
0x00007ff75cdb17f6 <+6>: nop
0x00007ff75cdb17f7 <+7>: nop
Dump of assembler code for function __imp__ZdlPvy:
0x00007ff75cdba288 <+0>: push %rax
0x00007ff75cdba289 <+1>: ret
0x00007ff75cdba28a <+2>: rex.X
0x00007ff75cdba28b <+3>: rex.WX (bad)
0x00007ff75cdba28d <+5>: jg 0x7ff75cdba28f <__imp__ZdlPvy+7>
0x00007ff75cdba28f <+7>: add %dl,%al
然而,当我5天后反汇编相同的代码时,<__imp__ZdlPvy>出来的是这样的:
Dump of assembler code for function __imp__ZdlPvy:
0x00007ff75cdba288 <+0>: push %rax
0x00007ff75cdba289 <+1>: ret
0x00007ff75cdba28a <+2>: stos %al,%es:(%rdi)
0x00007ff75cdba28b <+3>: or $0xf8,%al
0x00007ff75cdba28d <+5>: jg 0x7ff75cdba28f <__imp__ZdlPvy+7>
0x00007ff75cdba28f <+7>: add %dl,%al
我的问题是:
rex.X 在这里做什么? rex.WX(坏)在这里做什么以及它意味着什么? or 指令如何替换 rex.WX (假设是)? 为什么同一例程的第二次反汇编将 rex.X 替换为 stos 指令? 即使代码不是这样,为什么一次反汇编与下一次反汇编会有差异? 改变了,并且整个过程中只在 gdb 中运行了几次?
有关更多上下文:通过以下反汇编在例程中找到 _ZdlPvy。 (从代码中可以看到,有一个分段错误,是由 insert() 方法引起的。这是故意留下来作为一个谜题让我解决的。)
Dump of assembler code for function _ZN4MathIiED1Ev:
0x00007ff75cdb3430 <+0>: push %rbp
0x00007ff75cdb3431 <+1>: mov %rsp,%rbp
0x00007ff75cdb3434 <+4>: sub $0x30,%rsp
0x00007ff75cdb3438 <+8>: mov %rcx,0x10(%rbp)
0x00007ff75cdb343c <+12>: movl $0x0,-0x4(%rbp)
0x00007ff75cdb3443 <+19>: jmp 0x7ff75cdb3464 <_ZN4MathIiED1Ev+52>
0x00007ff75cdb3445 <+21>: mov 0x10(%rbp),%rax
0x00007ff75cdb3449 <+25>: mov 0x8(%rax),%rax
0x00007ff75cdb344d <+29>: mov -0x4(%rbp),%edx
0x00007ff75cdb3450 <+32>: movslq %edx,%rdx
0x00007ff75cdb3453 <+35>: shl $0x2,%rdx
0x00007ff75cdb3457 <+39>: add %rdx,%rax
0x00007ff75cdb345a <+42>: movl $0x0,(%rax)
0x00007ff75cdb3460 <+48>: addl $0x1,-0x4(%rbp)
0x00007ff75cdb3464 <+52>: mov 0x10(%rbp),%rax
0x00007ff75cdb3468 <+56>: mov (%rax),%eax
0x00007ff75cdb346a <+58>: cmp %eax,-0x4(%rbp)
0x00007ff75cdb346d <+61>: jl 0x7ff75cdb3445 <_ZN4MathIiED1Ev+21>
0x00007ff75cdb346f <+63>: mov 0x10(%rbp),%rax
0x00007ff75cdb3473 <+67>: movq $0x0,0x8(%rax)
0x00007ff75cdb347b <+75>: mov 0x10(%rbp),%rax
0x00007ff75cdb347f <+79>: mov 0x8(%rax),%rax
0x00007ff75cdb3483 <+83>: test %rax,%rax
0x00007ff75cdb3486 <+86>: je 0x7ff75cdb3495 <_ZN4MathIiED1Ev+101>
0x00007ff75cdb3488 <+88>: mov $0x4,%edx
0x00007ff75cdb348d <+93>: mov %rax,%rcx
0x00007ff75cdb3490 <+96>: call 0x7ff75cdb17f0 <_ZdlPvy>
0x00007ff75cdb3495 <+101>: nop
0x00007ff75cdb3496 <+102>: add $0x30,%rsp
0x00007ff75cdb349a <+106>: pop %rbp
0x00007ff75cdb349b <+107>: ret
这会在下面的 main() 反汇编中弹出:
main (argc=1, args=0x7297a0) at Try_Out.cpp:275
275 pointier.insert(0, 5);
Dump of assembler code for function main(int, char**):
0x00007ff75cdb16d0 <+0>: push %rbp
0x00007ff75cdb16d1 <+1>: push %rbx
0x00007ff75cdb16d2 <+2>: sub $0x48,%rsp
0x00007ff75cdb16d6 <+6>: lea 0x40(%rsp),%rbp
0x00007ff75cdb16db <+11>: mov %ecx,0x20(%rbp)
0x00007ff75cdb16de <+14>: mov %rdx,0x28(%rbp)
0x00007ff75cdb16e2 <+18>: call 0x7ff75cdb18c7 <__main>
0x00007ff75cdb16e7 <+23>: movl $0x2,-0x4(%rbp)
0x00007ff75cdb16ee <+30>: lea -0x20(%rbp),%rax
0x00007ff75cdb16f2 <+34>: mov $0x1,%edx
0x00007ff75cdb16f7 <+39>: mov %rax,%rcx
0x00007ff75cdb16fa <+42>: call 0x7ff75cdb33f0 <_ZN4MathIiEC1Ei>
=> 0x00007ff75cdb16ff <+47>: lea -0x20(%rbp),%rax
0x00007ff75cdb1703 <+51>: mov $0x5,%r8d
0x00007ff75cdb1709 <+57>: mov $0x0,%edx
0x00007ff75cdb170e <+62>: mov %rax,%rcx
0x00007ff75cdb1711 <+65>: call 0x7ff75cdb33c0 <_ZN4MathIiE6insertEii>
0x00007ff75cdb1716 <+70>: lea -0x20(%rbp),%rax
0x00007ff75cdb171a <+74>: mov $0xa,%r8d
0x00007ff75cdb1720 <+80>: mov $0x1,%edx
0x00007ff75cdb1725 <+85>: mov %rax,%rcx
0x00007ff75cdb1728 <+88>: call 0x7ff75cdb33c0 <_ZN4MathIiE6insertEii>
0x00007ff75cdb172d <+93>: lea -0x20(%rbp),%rax
0x00007ff75cdb1731 <+97>: mov $0x0,%edx
0x00007ff75cdb1736 <+102>: mov %rax,%rcx
0x00007ff75cdb1739 <+105>: call 0x7ff75cdb3390 <_ZN4MathIiE4at_vEi>
0x00007ff75cdb173e <+110>: mov %eax,%edx
0x00007ff75cdb1740 <+112>: mov 0x3c99(%rip),%rax # 0x7ff75cdb53e0 <__fu0__ZSt4cout>
--Type <RET> for more, q to quit, c to continue without paging--c
0x00007ff75cdb1747 <+119>: mov %rax,%rcx
0x00007ff75cdb174a <+122>: call 0x7ff75cdb1800 <_ZNSolsEi>
0x00007ff75cdb174f <+127>: mov %rax,%rcx
0x00007ff75cdb1752 <+130>: lea 0x38f7(%rip),%rax # 0x7ff75cdb5050
0x00007ff75cdb1759 <+137>: mov %rax,%rdx
0x00007ff75cdb175c <+140>: call 0x7ff75cdb17f8 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc>
0x00007ff75cdb1761 <+145>: mov %rax,%rbx
0x00007ff75cdb1764 <+148>: lea -0x20(%rbp),%rax
0x00007ff75cdb1768 <+152>: mov $0x1,%edx
0x00007ff75cdb176d <+157>: mov %rax,%rcx
0x00007ff75cdb1770 <+160>: call 0x7ff75cdb3390 <_ZN4MathIiE4at_vEi>
0x00007ff75cdb1775 <+165>: mov %eax,%edx
0x00007ff75cdb1777 <+167>: mov %rbx,%rcx
0x00007ff75cdb177a <+170>: call 0x7ff75cdb1800 <_ZNSolsEi>
0x00007ff75cdb177f <+175>: lea 0x38d5(%rip),%rax # 0x7ff75cdb505b
0x00007ff75cdb1786 <+182>: mov %rax,%rdx
0x00007ff75cdb1789 <+185>: mov 0x3c50(%rip),%rax # 0x7ff75cdb53e0 <__fu0__ZSt4cout>
0x00007ff75cdb1790 <+192>: mov %rax,%rcx
0x00007ff75cdb1793 <+195>: call 0x7ff75cdb17f8 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc>
0x00007ff75cdb1798 <+200>: mov $0x7a120,%ecx
0x00007ff75cdb179d <+205>: call 0x7ff75cdb2eb0 <usleep>
0x00007ff75cdb17a2 <+210>: mov $0x0,%ebx
0x00007ff75cdb17a7 <+215>: lea -0x20(%rbp),%rax
0x00007ff75cdb17ab <+219>: mov %rax,%rcx
0x00007ff75cdb17ae <+222>: call 0x7ff75cdb3430 <_ZN4MathIiED1Ev>
0x00007ff75cdb17b3 <+227>: mov %ebx,%eax
0x00007ff75cdb17b5 <+229>: jmp 0x7ff75cdb17d1 <main(int, char**)+257>
0x00007ff75cdb17b7 <+231>: mov %rax,%rbx
0x00007ff75cdb17ba <+234>: lea -0x20(%rbp),%rax
0x00007ff75cdb17be <+238>: mov %rax,%rcx
0x00007ff75cdb17c1 <+241>: call 0x7ff75cdb3430 <_ZN4MathIiED1Ev>
0x00007ff75cdb17c6 <+246>: mov %rbx,%rax
0x00007ff75cdb17c9 <+249>: mov %rax,%rcx
0x00007ff75cdb17cc <+252>: call 0x7ff75cdb2e60 <_Unwind_Resume>
0x00007ff75cdb17d1 <+257>: add $0x48,%rsp
0x00007ff75cdb17d5 <+261>: pop %rbx
0x00007ff75cdb17d6 <+262>: pop %rbp
0x00007ff75cdb17d7 <+263>: ret
所有这些都是从以下代码中反汇编的:
#include <iostream>
#include <unistd.h>
#include <memory>
template <typename T> class Math
{
public:
int size = 2; T* ptr;
Math (int size)
{ T* ptr = new T(*ptr) ;}
T at_v (int place)
{ return ptr[place] ;}
void insert (int place, int value)
{ ptr[place] = value ;}
};
int main()
{
int size = 2 ;
Math <int> pointier(1) ;
pointier.insert(0, 5) ;
pointier.insert(1, 10) ;
std::cout << pointier.at_v(0) << " and also " << pointier.at_v(1) ;
std::cout << "\n\n"; usleep(500000) ;
}
这只是对一些汇编指令含义的询问,对可用的网站和文献的搜索一无所获。我想知道,因为它可以更好地让我弄清楚如何从反汇编中调试代码:我打算自己进行此调试,但需要帮助理解几行。
汇编(asm)中的RET与Return函数类似,只不过c++生成的每个迷你块都有一个RET,即表示指令序列已经结束,必须返回到调用它的指令。语句的其余部分是返回的参数: