Gdb 选择地址以更改内存中的值

Gdb 选择地址以更改内存中的值,gdb,Gdb,SO上的问答说明了如何使用GDB更改内存中的值,但在给出的示例中,它选择了一个地址来设置以前未使用的值 例如,要将返回值更改为22,作者需要 set {unsigned char}0x00000000004004b9 = 22 但是,为什么此地址0x00000000004004b9会是要更改的地址?如果查看disas/r的输出,地址0x00000000004004b9未被使用,那么为什么要使用此地址设置为22?我试图了解如果disas/r的输出没有显示返回值,如何知道需要更改哪个地址(在本例中

SO上的问答说明了如何使用GDB更改内存中的值,但在给出的示例中,它选择了一个地址来设置以前未使用的值

例如,要将返回值更改为22,作者需要

set {unsigned char}0x00000000004004b9 = 22
但是,为什么此地址
0x00000000004004b9
会是要更改的地址?如果查看
disas/r
的输出,地址
0x00000000004004b9
未被使用,那么为什么要使用此地址设置为22?我试图了解如果
disas/r
的输出没有显示返回值,如何知道需要更改哪个地址(在本例中)来更改返回值

代码

$cat t.c
int main()
{
返回42;
}
$gcc t.c&./a.out;回声$?
42
$gdb——写入–q./a.out
(gdb)disas/r干管
主功能的汇编程序代码转储:
0x0000000000404B4:55推送%rbp
0x0000000000404B5:4889E5MOV%rsp%rbp
0x0000000000404B8:b8 2a 00 00 mov$0x2a,%eax
0x00000000004004bd:5d pop%rbp
0x0000000000404BE:c3 retq
汇编程序转储结束。
(gdb)集合{unsigned char}0x0000000000404B9=22
(gdb)disas/r干管
主功能的汇编程序代码转储:
0x0000000000404B4:55推送%rbp
0x0000000000404B5:4889E5MOV%rsp%rbp
0x0000000000404B8:b8 16 00 00 mov$0x16,%eax
我试图理解如果disas/r的输出没有显示返回值,如何知道需要更改哪个地址(在本例中)来更改返回值

要理解这一点,你需要理解。这里的指令是“将立即数32位常量移到寄存器”。常量是指令的一部分(这就是“立即”的意思)。相反,编译以下内容可能会有所帮助:

int foo() { return 0x41424344; }
int bar() { return 0x45464748; }
int main() { return foo() + bar(); }
当您编译它时,您应该会看到类似的内容:

(gdb) disas/r foo
Dump of assembler code for function foo:
   0x00000000004004ed <+0>:     55      push   %rbp
   0x00000000004004ee <+1>:     48 89 e5        mov    %rsp,%rbp
   0x00000000004004f1 <+4>:     b8 44 43 42 41  mov    $0x41424344,%eax
   0x00000000004004f6 <+9>:     5d      pop    %rbp
   0x00000000004004f7 <+10>:    c3      retq   
End of assembler dump.
(gdb) disas/r bar
Dump of assembler code for function bar:
   0x00000000004004f8 <+0>:     55      push   %rbp
   0x00000000004004f9 <+1>:     48 89 e5        mov    %rsp,%rbp
   0x00000000004004fc <+4>:     b8 48 47 46 45  mov    $0x45464748,%eax
   0x0000000000400501 <+9>:     5d      pop    %rbp
   0x0000000000400502 <+10>:    c3      retq   
End of assembler dump.
(gdb)disas/r foo
函数foo的汇编程序代码转储:
0x0000000000404ED:55推送%rbp
0x000000000004004EE:48 89 e5 mov%rsp,%rbp
0x0000000000404F1:b8 44 43 42 mov$0x41424344,%eax
0x00000000004004f6:5d pop%rbp
0x00000000004004f7:c3 retq
汇编程序转储结束。
(gdb)disas/r条
功能条的汇编代码转储:
0x00000000004004f8:55推送%rbp
0x00000000004004f9:48 89 e5 mov%rsp,%rbp
0x00000000004004fc:b8 48 47 45 mov$0x45464748,%eax
0x0000000000400501:5d pop%rbp
0x0000000000400502:c3 retq
汇编程序转储结束。
现在,您可以清楚地看到立即数常量的每个字节在指令流中的位置(而且x86对它们使用小端编码)

x86指令编码的标准参考是Intel。您可以在第3-528页找到
0xB8
说明

(gdb) disas/r foo
Dump of assembler code for function foo:
   0x00000000004004ed <+0>:     55      push   %rbp
   0x00000000004004ee <+1>:     48 89 e5        mov    %rsp,%rbp
   0x00000000004004f1 <+4>:     b8 44 43 42 41  mov    $0x41424344,%eax
   0x00000000004004f6 <+9>:     5d      pop    %rbp
   0x00000000004004f7 <+10>:    c3      retq   
End of assembler dump.
(gdb) disas/r bar
Dump of assembler code for function bar:
   0x00000000004004f8 <+0>:     55      push   %rbp
   0x00000000004004f9 <+1>:     48 89 e5        mov    %rsp,%rbp
   0x00000000004004fc <+4>:     b8 48 47 46 45  mov    $0x45464748,%eax
   0x0000000000400501 <+9>:     5d      pop    %rbp
   0x0000000000400502 <+10>:    c3      retq   
End of assembler dump.