GDB调试时修改RAX寄存器未影响程序执行的原因咨询
修改RAX后字符串输出未变化的核心原因
出现这个现象是三个认知和操作层面的错误共同导致的:
- 搞错了x86_64 Linux平台的函数传参规则
x86_64架构下System V ABI的函数调用约定中,整数、指针类型的第一个函数参数固定存储在RDI寄存器;RAX的作用仅为存储函数返回值,以及在可变参数函数中标记使用的浮点寄存器数量,根本不是用来传递字符串指针的寄存器。
从反汇编代码的mov rdi,rax指令就能看出逻辑:RAX在这里只是临时计算栈地址的中转寄存器,执行完这条mov指令后,字符串首地址就被复制到RDI中,后续call puts(编译器自动将带\n后缀的printf优化为puts调用)只会从RDI读取参数,和RAX不再有任何关联。 - 搞错了字符串的实际存储位置
反汇编中出现的movabs rax, 0x6f57206f6c6c6548、movabs rdx, 0x6d6f726620646c72两条指令,并不是把字符串存在寄存器中准备传参,只是把硬编码的字符串常量按8字节分块,临时通过RAX/RDX中转,拷贝到栈上的message_c_str局部数组内存中。拷贝完成后,RAX/RDX里存储的字符串片段值就失去了作用,字符串本体始终存放在栈上rbp-0x20起始的内存区域,并非长期驻留在寄存器中。 - 修改寄存器的时机错误,修改值直接被后续指令覆盖
你在GDB中从line5执行next走到line6时,程序会停在C代码第6行对应的第一条汇编指令(地址0x118b的lea rax,[rbp-0x20])之前。这时候你修改RAX的值,接下来执行的第一条指令就是lea rax,[rbp-0x20],会直接把RAX重新赋值为栈上字符串数组的首地址,你修改的值会被直接覆盖。后续参数复制、函数调用流程中,RAX里早就不是你设置的值,自然不会对输出产生任何影响。
可生效的动态修改方式
如果要在调试时修改打印的字符串,选择任意一种操作即可:
- 在
call puts指令(地址0x1192)处下断点,程序断下后直接修改RDI指向的内存内容,例如执行GDB命令set {char[21]}$rdi = "Modified by GDB!",继续运行就会输出修改后的内容。 - 在
mov rdi,rax指令(地址0x118f)执行前修改RAX的值,让它指向你构造的、可访问的其他字符串地址,后续参数传递就会使用你设置的新地址。 - 直接修改栈上
message_c_str数组所在的内存内容,不需要操作寄存器。
内容的提问来源于stack exchange,提问作者Alexis Nicole
相关产品推荐
相关产品推荐

