Вы смотрите на 4 байта, начиная с result
, который включает input
в качестве 2-го или 3-го байта.(Вот почему значение увеличивается кратно 256 или 65536, оставляя младший байт = 1, если вы print (char)result
).Это было бы более очевидно, если вы используете p /x
для печати в шестнадцатеричном формате.
Поведение GDB по умолчанию для print result
, когда не было отладочной информации, предполагало int
.Теперь, из-за таких ошибок пользователя, как gdb
8.1 в Arch Linux, print result
сообщает 'result' has unknown type; cast it to its declared type
GAS + ld
неожиданно (во всяком случае, мне) объединить сегменты BSS и данных в одинстраница, поэтому ваши переменные являются смежными, даже если вы помещаете их в разные разделы, которые, как вы ожидаете, будут обрабатываться по-разному.(BSS поддерживается анонимными обнуленными страницами, данные - частным отображением файла для чтения и записи).
После сборки с gcc -nostdlib -no-pie test.S
я получаю:
(gdb) p &result
$1 = (<data variable, no debug info> *) 0x600126
(gdb) p &input
$2 = (<data variable, no debug info> *) 0x600128 <input>
В отличие отиспользуя .section .bss
и резервируя место вручную, .lcomm
свободен для заполнения, если захочет.Предположительно для выравнивания, может быть, здесь, так что BSS начинается на 8-байтовой границе.Когда я строил с clang
, я получил input
в байте после result
(по разным адресам).
Я исследовал, добавив большой массив с .lcomm arr, 888332
.Как только я понял, что в исполняемом файле не хранятся буквальные нули для BSS, я использовал readelf -a a.out
для дальнейшей проверки:
(по теме: В чем разница между разделом и сегментом в формате файла ELF )
...
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000126 0x0000000000000126 R E 0x200000
LOAD 0x0000000000000126 0x0000000000600126 0x0000000000600126
0x0000000000000001 0x00000000000d8e1a RW 0x200000
NOTE 0x00000000000000e8 0x00000000004000e8 0x00000000004000e8
0x0000000000000024 0x0000000000000024 R 0x4
Section to Segment mapping:
Segment Sections...
00 .note.gnu.build-id .text
01 .data .bss
02 .note.gnu.build-id
...
Так что да, секции .data
и .bss
оказались в одном и том же сегменте ELF.
Я думаю, что здесь происходит то, что метаданные ELF говорятдля отображения MemSize 0xd8e1a
байтов (обнуленных страниц), начиная с virt addr 0x600126
.и ЗАГРУЗИТЬ 1 байт из смещения 0x126
в файле на виртуальный адрес 0x600126
.
Таким образом, вместо просто mmap, загрузчик программ ELF должен копировать данные из файла встраница с нулевым счетом, поддерживающая разделы BSS и .data
.
Вероятно, это больший раздел .data
, который потребуется компоновщику для принятия решения об использовании отдельных сегментов.