О расположении памяти программ в Linux

У меня есть несколько вопросов о структуре памяти программы в Linux. Я знаю из различных источников (я читаю «Программирование с нуля»), что каждый раздел загружается в свою область памяти. Сначала текстовый раздел загружается по виртуальному адресу 0x8048000, сразу после этого загружается раздел данных, затем - раздел bss, затем куча и стек.

Чтобы поэкспериментировать с макетом я сделал эту программу в сборке. Сначала он печатает адреса некоторых меток и вычисляет точку останова системы. Затем он входит в бесконечный цикл. Цикл увеличивает указатель и затем пытается получить доступ к памяти по этому адресу, в какой-то момент ошибка сегментации завершит работу программы (я сделал это намеренно).

Это программа:

.section .data

start_data:
str_mem_access:
.ascii "Accessing address: 0x%x\n\0"
str_data_start:
.ascii "Data section start at: 0x%x\n\0"
str_data_end:
.ascii "Data section ends at: 0x%x\n\0"
str_bss_start:
.ascii "bss section starts at: 0x%x\n\0"
str_bss_end:
.ascii "bss section ends at: 0x%x\n\0"
str_text_start:
.ascii "text section starts at: 0x%x\n\0"
str_text_end:
.ascii "text section ends at: 0x%x\n\0"
str_break:
.ascii "break at: 0x%x\n\0"
end_data:

.section .bss

start_bss:
.lcomm buffer, 500
.lcomm buffer2, 250
end_bss:

.section .text
start_text:

.globl _start
_start:

# print address of start_text label
pushl $start_text
pushl $str_text_start
call printf
addl $8, %esp
# print address of end_text label
pushl $end_text
pushl $str_text_end
call printf
addl $8, %esp
# print address of start_data label
pushl $start_data
pushl $str_data_start
call printf
addl $8, %esp
# print address of end_data label
pushl $end_data
pushl $str_data_end
call printf
addl $8, %esp
# print address of start_bss label
pushl $start_bss
pushl $str_bss_start
call printf
addl $8, %esp
# print address of end_bss label
pushl $end_bss
pushl $str_bss_end
call printf
addl $8, %esp
# get last usable virtual memory address
movl $45, %eax
movl $0, %ebx
int $0x80

incl %eax # system break address
# print system break
pushl %eax
pushl $str_break
call printf
addl $4, %esp

movl $start_text, %ebx

loop:
# print address
pushl %ebx
pushl $str_mem_access
call printf
addl $8, %esp

# access address
# segmentation fault here
movb (%ebx), %dl

incl %ebx

jmp loop

end_loop:
movl $1, %eax
movl $0, %ebx
int $0x80

end_text:

И это соответствующие части вывода (это Debian 32bit):

text section starts at: 0x8048190
text section ends at: 0x804823b
Data section start at: 0x80492ec
Data section ends at: 0x80493c0
bss section starts at: 0x80493c0
bss section ends at: 0x80493c0
break at: 0x83b4001
Accessing address: 0x8048190
Accessing address: 0x8048191
Accessing address: 0x8048192
[...]
Accessing address: 0x8049fff
Accessing address: 0x804a000
Violación de segmento

Мои вопросы:

1) Почему моя программа начинается с адреса 0x8048190 вместо 0x8048000? При этом я предполагаю, что инструкция с меткой "_start" загружается не первой, так что находится между адресами 0x8048000 и 0x8048190?

2) Почему существует разрыв между концом текстового раздела и началом раздела данных?

3) Начальный и конечный адреса bss совпадают. Я предполагаю, что два буфера хранятся где-то еще, это правильно?

4) Если точка останова системы находится в 0x83b4001, почему я получаю ошибку сегментации ранее в 0x804a000?

Ответы на вопрос(1)

Ваш ответ на вопрос