我看到一段使用resb
的NASM代码。但是,此代码在实模式操作系统中运行,并且输出格式是平面二进制。 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
只是在二进制文件末尾分配一些未使用的空间- 它根本不起作用,而且东西会爆炸。
最佳答案
当NASM生成二进制-f bin
时,它遵循有关各部分的一些基本规则。 NASM manual说的是:
7.1.3 Multisection Support for the bin Format
[snip]
- The .bss section will be placed after the last progbits section, unless start=, vstart=, follows=, or vfollows= has been specified.
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区域的范围,以便在我们的代码开始执行时将其初始化为零。
关于assembly - NASM的resb以二进制输出格式做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34268699/