Что делает resb NASM в двоичном формате вывода?
Я видел кусок кода NASM, который использует resb
, Однако этот код работает в операционной системе реального режима, а выходной формат - плоский двоичный. NASM не выдает ошибку при этом, но после разбора выходного файла я все еще не мог найти то, что на самом деле происходит.
bits 16
org 0x8000
start:
mov ax, msg
call os_input_string
mov si, msg
call os_print_string
ret
section .bss
msg: resb 256
Вот несколько вариантов, о которых я подумал:
resb
просто выделяет некоторое неиспользуемое пространство в конце двоичного файла- это на самом деле не работает, и все взрывается.
3 ответа
Когда NASM генерирует двоичный файл -f bin
это следует некоторым основным правилам о разделах. Руководство NASM говорит это:
7.1.3 Многосекционная поддержка формата bin
[Надрез]
- Раздел.bss будет помещен после последнего раздела progbits, если не было указано start=, vstart=, follow = или vfollows=.
progbits
флаг, обозначающий раздел, который будет физически отображаться в файле (по умолчанию .text
а также .data
секции). .bss
по умолчанию nobits
Это означает, что данные, зарезервированные в этом разделе, физически не отображаются в файле, но любые адреса меток в nobits
помеченный раздел будет разрешен (по умолчанию) в память сразу после последнего progbits
(.text
а также .data
и т.д.) раздел. Область BSS в двоичном файле не инициализируется нулем. Это будет то, что происходит в памяти, так что рассмотрите область, чтобы содержать мусор. Если вам нужна двоичная программа для инициализации этой области на ноль, вам придется сделать это самостоятельно, как только ваша программа начнет выполняться.
В вашем вопросе есть намеки на то, что вы создаете второй этап загрузчика. Я приведу пример кода, который инициализирует область BSS нулями. Этот код предполагает, что второй этап был загружен в 0x0000:0x8000:
bits 16
org 0x8000
section .text
start:
; Initialize the entire BSS area to zero
; Assume we are the second stage of a bootloader at 0x0000:0x8000
mov cx, _bss_end-_bss_start ; Length of region in CX
xor ax, ax ; AX=0 (also used for rep stos)
mov es, ax
mov ds, ax ; DS=ES=0x0000
mov di, _bss_start ; Offset of BSS region
rep stosb ; Set CX bytes of data at ES:[DI] to AL(0)
mov ax, msg
mov si, msg2
; Put second stage in halt state indefinitely.
cli
.endloop:
hlt
jmp .endloop
section .bss
_bss_start: ; Label for start of BSS
msg: resb 256
msg2: resb 10
_bss_end: ; Label at end of BSS
Хотя память для BSS не является частью двоичного файла на диске, метки для данных в этой области преобразуются в реальные смещения. Вы можете пометить начало и конец области BSS, и в этом случае я использую _bss_start
а также _bss_end
, Эти метки используются для определения степени области BSS, чтобы ее можно было инициализировать нулем, когда наш код начинает выполняться.
Это все написано в руководстве, конечно. resb
резервирует неинициализированное хранилище в .bss
раздел. Более того, bin
файлы имеют ограниченную поддержку разделов, в частности:
Разделы могут быть обозначены как прогбиты или нобиты. По умолчанию это progbits (кроме.bss, который по умолчанию равен nobits, конечно). Раздел.bss будет помещен после последнего раздела progbits, если не было указано start=, vstart=, follow = или vfollows=.
Таким образом, " resb просто выделяет некоторое неиспользуемое пространство в конце двоичного файла " - это, в основном, то, что происходит. Не уверен, почему вы не можете увидеть это из разбора выходного файла.
Поскольку раздел.bss никогда не содержит инициализированных данных (устанавливается как nobits
), это не должно быть записано в файл. При использовании плоского двоичного формата NASM просто вычислит подходящий указатель для переменной и все.
Разбирая код, вы можете легко увидеть, что происходит. Я скомпилировал этот код:
bits 16
org 0x8000
start:
mov ax, msg
ret
section .bss
msg: resb 256
При запуске полученного двоичного файла через ndisasm:
00000000 B80480 mov ax,0x8004
00000003 C3 ret
Таким образом, вы можете ясно видеть, что NASM написал четыре байта кода и определил, что раздел.bss может быть помещен сразу после этого, начиная с позиции 0x8004. Таким образом, в двоичном файле ничего не выделяется, только указатели рассчитываются на основе требуемого распределения в.bss.