Двоичный файл или программа состоит как из машинного кода, так и из данных. В этом случае ваша строка, которую вы поместили в исходный код, компилятор тоже использует данные, которые представляют собой просто байты, и из-за того, как она использовалась, считалась данными только для чтения, поэтому в зависимости от компилятора, который может попасть в .rodata или .text или какое-либо другое имя, которое может использовать компилятор. Gcc, вероятно, назвал бы это .rodata. Сама программа в .text. Появляется компоновщик, и когда он связывает вещи, он находит место для .text, .data, .bss, .rodata и любых других элементов, которые могут у вас быть, а затем соединяет точки. В случае вашего вызова printf компоновщик знает, куда он поместил строку, массив байтов, и ему было сказано, каково его имя (без сомнения, какое-то внутреннее временное имя), и вызову printf было сказано об этом имени, чтобы компоновщик исправляет инструкцию, чтобы захватить адрес в строку формата перед вызовом printf.
Disassembly of section .text:
0000000000400430 <main>:
400430: 53 push %rbx
400431: bb 0a 00 00 00 mov $0xa,%ebx
400436: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40043d: 00 00 00
400440: bf e4 05 40 00 mov $0x4005e4,%edi
400445: e8 b6 ff ff ff callq 400400 <puts@plt>
40044a: 83 eb 01 sub $0x1,%ebx
40044d: 75 f1 jne 400440 <main+0x10>
40044f: 31 c0 xor %eax,%eax
400451: 5b pop %rbx
400452: c3 retq
400453: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40045a: 00 00 00
40045d: 0f 1f 00 nopl (%rax)
Disassembly of section .rodata:
00000000004005e0 <_IO_stdin_used>:
4005e0: 01 00 add %eax,(%rax)
4005e2: 02 00 add (%rax),%al
4005e4: 48 rex.W
4005e5: 65 6c gs insb (%dx),%es:(%rdi)
4005e7: 6c insb (%dx),%es:(%rdi)
4005e8: 6f outsl %ds:(%rsi),(%dx)
4005e9: 2c 20 sub $0x20,%al
4005eb: 77 6f ja 40065c <__GNU_EH_FRAME_HDR+0x68>
4005ed: 72 6c jb 40065b <__GNU_EH_FRAME_HDR+0x67>
4005ef: 64 21 00 and %eax,%fs:(%rax)
компилятор закодировал эту инструкцию, но оставил адрес как нули, вероятно, или какое-то заполнение
400440: bf e4 05 40 00 mov $0x4005e4,%edi
чтобы компоновщик мог заполнить его позже. Дизассемблер gnu пытается дизассемблировать блоки .rodata (и .data и т. д.), что не имеет смысла, поэтому игнорируйте инструкции, которые он пытается интерпретировать, ваша строка, начинающаяся с адреса 0x4005e4.
Перед привязкой разборки объекта показаны два раздела .text и .rodata
Disassembly of section .text.startup:
0000000000000000 <main>:
0: 53 push %rbx
1: bb 0a 00 00 00 mov $0xa,%ebx
6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
d: 00 00 00
10: bf 00 00 00 00 mov $0x0,%edi
15: e8 00 00 00 00 callq 1a <main+0x1a>
1a: 83 eb 01 sub $0x1,%ebx
1d: 75 f1 jne 10 <main+0x10>
1f: 31 c0 xor %eax,%eax
21: 5b pop %rbx
22: c3 retq
0000000000000000 <.rodata.str1.1>:
0: 48 rex.W
1: 65 6c gs insb (%dx),%es:(%rdi)
3: 6c insb (%dx),%es:(%rdi)
4: 6f outsl %ds:(%rsi),(%dx)
5: 2c 20 sub $0x20,%al
7: 77 6f ja 78 <main+0x78>
9: 72 6c jb 77 <main+0x77>
b: 64 21 00 and %eax,%fs:(%rax)
несвязанный, он должен просто дополнить этот адрес/смещение, чтобы компоновщик мог заполнить его позже.
10: bf 00 00 00 00 mov $0x0,%edi
также обратите внимание, что объект содержит только строку в .rodata. связывание с библиотеками и другими элементами, чтобы сделать его полной программой, явно добавило больше .rodata, но компоновщик управляет всем этим.
Возможно, проще увидеть на этом примере
void more_fun ( unsigned int, unsigned int, unsigned int );
unsigned int a;
unsigned int b=5;
const unsigned int c=7;
void fun ( void )
{
more_fun(a,b,c);
}
разобран как объект
Disassembly of section .text:
0000000000000000 <fun>:
0: 8b 35 00 00 00 00 mov 0x0(%rip),%esi # 6 <fun+0x6>
6: 8b 3d 00 00 00 00 mov 0x0(%rip),%edi # c <fun+0xc>
c: ba 07 00 00 00 mov $0x7,%edx
11: e9 00 00 00 00 jmpq 16 <fun+0x16>
Disassembly of section .data:
0000000000000000 <b>:
0: 05 .byte 0x5
1: 00 00 add %al,(%rax)
...
Disassembly of section .rodata:
0000000000000000 <c>:
0: 07 (bad)
1: 00 00 add %al,(%rax)
...
и по какой-то причине вы должны связать его, чтобы увидеть раздел .bss. Суть примера в том, что машинный код для функции находится в .text, неинициализированный глобальный файл — в .bss, инициализированный глобальный — .data, а константный глобальный — .rodata. Компилятор был достаточно умен, чтобы знать, что константа, даже если она глобальная, не изменится, поэтому он может просто жестко закодировать это значение в математике и не читать из оперативной памяти, но две другие переменные он должен прочитать из оперативной памяти, поэтому генерирует инструкцию с адресными нулями, которые должны быть заполнены компоновщиком во время компоновки.
В вашем случае ваши данные только для чтения / const представляли собой набор байтов, и это не была математическая операция, поэтому байты, определенные в исходном файле, были помещены в память, чтобы на них можно было указать в качестве первого параметра для printf.
Двоичный код — это нечто большее, чем просто машинный код. И компилятор, и компоновщик могут размещать вещи в памяти для получения машинным кодом, сам машинный код не должен записывать каждое значение, которое будет использоваться остальной частью машинного кода.
person
old_timer
schedule
06.03.2017
[esp]
не совпадает сesp
, первый обращается к памяти и не изменяет самогоesp
. - person Jester   schedule 06.03.20170x8048441
и заканчивается на0x80484e0
. Имейте в виду, что строка — это список целых чисел. - person Xorifelse   schedule 06.03.2017puts
. - person Jester   schedule 06.03.2017"Hello, world!\n"
в раздел данных только для чтения, будучи строковым литералом. Этот возможно дублирующийся вопрос может вас заинтересовать. - person Weather Vane   schedule 06.03.2017objdump -d -M intel -s a.out
, чтобы увидеть также раздел .data, в котором хранится строка (редактировать: НЕ в вашем случае, переходит в .text с кодом). Затем эта часть исполняемого файла загружается в память в виде двоичного блока перед запуском первой инструкции исполняемого файла, поэтому код найдет эту часть памяти, настроенную со значениями из источника. (на самом деле строка находится в сегменте кода, так что objdump будет немного забавнее, чем когда вы делаете это с помощью простого человеческого примера ASM hello world... попробуйте в любом случае :) ) - person Ped7g   schedule 07.03.2017