Недавно я начал изучать язык ассемблера для архитектуры Intel x86-64 с использованием YASM. При решении одной из задач, предложенной в книге (Ray Seyfarth), я пришел к следующей проблеме:gdb ведет себя по-разному для символов в .bss, против символов в .data
Когда я помещаю некоторые символы в буфер в разделе .bss, я все еще вижу пустую строку при отладке ее в gdb , Размещение символов в буфере в разделе .data отображается как ожидалось в gdb.
segment .bss
result resb 75
buf resw 100
usage resq 1
segment .data
str_test db 0, 0, 0, 0
segment .text
global main
main:
mov rbx, 'A'
mov [buf], rbx ; LINE - 1 STILL GET EMPTY STRING AFTER THAT INSTRUCTION
mov [str_test], rbx ; LINE - 2 PLACES CHARACTER NICELY.
ret
В БГД я получаю:
после LINE 1:
x/s &buf
, результат -0x7ffff7dd2740 <buf>: ""
после LINE 2:
x/s &str_test
, результат -0x601030: "A"
It выглядит как &buf
не e оценивая правильный адрес, поэтому он все еще видит все нули. 0x7ffff7dd2740 не находится в BSS процесса, который отлаживается, в соответствии с его /proc/PID/maps
, поэтому это не имеет смысла. Почему &buf
оценивает с неправильным адресом, но &str_test
оценивает на правильном адресе? Также не являются «глобальными» символами, но мы строили их с помощью отладочной информации.
Протестировано с GNU gdb (Ubuntu 7.10-1ubuntu2) 7.10 на x86-64 Ubuntu 15.10.
Я строю с
yasm -felf64 -Worphan-labels -gdwarf2 buf-test.asm
gcc -g buf-test.o -o buf-test
nm
на исполняемом показывает правильные адреса символов:
$ nm -n buf-test # numeric sort, heavily edited to omit symbols from glibc
...
0000000000601028 D __data_start
0000000000601038 d str_test
...
000000000060103c B __bss_start
0000000000601040 b result
000000000060108b b buf
0000000000601153 b usage
(примечание редактора: я переписал много вопроса, потому что странность в реализации GDB поведение, а не asm!).
Я в основном переписал вопрос, так как ваш asm * был * работает. Проблема заключалась в том, что '& buf' в gdb был каким-то странным адресом в стеке. '0x7ffff ...' адреса - это адреса стека в x86-64 Linux. bss и адреса данных всегда находятся на низком уровне 2 ГБ (поэтому они вписываются в подписанные 32-битные целые числа, потому что многие инструкции x86-64 используют расширенные символы 'imm32', например' add rax, symbol' использует 'add r/m64 , imm64' кодировка). Во всяком случае, я тестировал себя на своем рабочем столе x86-64 и воспроизводил странность gdb, не найдя способ получить правильный адрес 'buf' в выражении gdb. –
Другой ключ, по которому вы получаете неправильный адрес, состоит в том, что он равен 16B (последняя шестнадцатеричная цифра равна 0), но мы знаем, что 'buf' не должно быть. Он следует за «resb 75», а начало bss обычно выравнивается по 16B (как мы видим, «результат» находится в выходе nm. И да, эти адреса символов - это место, где исполняемый файл будет фактически отображаться каждый раз, когда вы Запустите его, потому что он не перемещается. Код для исполняемых файлов Linux не обязательно должен быть независимым от позиции, в отличие от динамических библиотек, которые необходимы (скомпилируйте с '-fPIC' или избегайте абсолютных адресов в рукописном asm). –
Спасибо, Питер , как я понимаю, это поведение gdb, возможно ли справиться с ним и поместить символы как-то в раздел .bss. Некорректная позиция buf в стеке вместо .bss меня раздражает, и я не понимаю, почему это так. Должен ли я выравнивать buf каким-то образом? –