Я отлаживаю ассемблерный код следующей простой программы:
int main()
{
int x = 5;
return 0;
}
Я установил точку останова на операторе return. gdb показывает следующий ассемблерный код (синтаксис Intel):
(gdb) disass
Dump of assembler code for function main():
0x00005555555545fa <+0>: push rbp
0x00005555555545fb <+1>: mov rbp,rsp
0x00005555555545fe <+4>: mov DWORD PTR [rbp-0x4],0x5
=> 0x0000555555554605 <+11>: mov eax,0x0
0x000055555555460a <+16>: pop rbp
0x000055555555460b <+17>: ret
End of assembler dump.
Вот информация о регистре rsp:
(gdb) info reg rsp
rsp 0x7fffffffdcb0 0x7fffffffdcb0
Значение переменной x должно быть помещено в стек, как распечатать стек? Я пробую следующую команду, но безуспешно:
(gdb) x/10x $rsp
0x7fffffffdcb0: 0x55554610 0x00005555 0xf7a03c87 0x00007fff
0x7fffffffdcc0: 0x00000001 0x00000000 0xffffdd98 0x00007fff
0x7fffffffdcd0: 0x00008000 0x00000001
Более того, я не понимаю, почему разница между указанными выше адресами равна 16.
Что касается вашего другого вопроса, x/10x
печатает память кусками по 4 байта. Он напечатал 4 фрагмента в одной строке, что составляет 16 байт. Таким образом, следующая строка начинается на 16 байт позже.
Технически x/10x
использует последний размер, но в данном случае да, это 4 байта.
Как напечатать один кусок в строке?
Я не вижу способа указать элементы в строке. Кроме того, по крайней мере, моя версия gdb игнорирует set width
. Так что, похоже, остается только сценарий, если вам это действительно нужно.
Значение переменной x должно быть помещено в стек, как распечатать стек?
То, что вы видите, называется красной зоной — любой функции разрешено использовать некоторое пространство стека ниже указателя стека. Это оптимизация на уровне ABI — указатель стека нужно перемещать только при вызове другой функции или выходе за красную зону (128 байт в SysV ABI).
Обратите внимание, что значение хранится на 4 байта ниже указателя кадра rbp
(который здесь равен указателю стека rsp
).
mov DWORD PTR [rbp-0x4],0x5
Поэтому попробуйте распечатать стек, начиная с $rsp - 4
или меньше.
x/10wx $rsp-4
Или скомпилируйте с помощью -mno-red-zone
(но обратите внимание, что в SysV указатель стека ABI выровнен по 16 байтам, поэтому ваше значение, вероятно, будет равно $rsp + 12
).
Более того, я не понимаю, почему разница между указанными выше адресами равна 16
Дамп памяти содержит 16 байт на строку (см. 4 значения по 4 байта). Итак, следующая строка начинается на 16 байт позже (или 0x10). с x/10x
вы запросили напечатать 10 шестнадцатеричных значений (по умолчанию двойные слова), поэтому вы получаете 40 байтов памяти.
Вы можете напечатать одно значение двойного слова с помощью x/wx $rsp-4
.
Для получения более подробной информации обратитесь к GDB docs - Память.
Обратите внимание, что ассемблерный код хранит от 5 до
rbp - 4
. Вы должны проверять$rbp - 4
или$rsp - 4
(поскольку mov сделал их обоих равными). Если вы сомневаетесь, спросите GDB с помощьюprint &x
.