我看到一段使用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
只是在二进制文件末尾分配一些未使用的空格答案 0 :(得分:4)
当 NASM 生成二进制文件-f bin
时,它遵循有关这些部分的一些基本规则。 NASM manual说明了这一点:
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 区域的范围,以便在我们的代码开始执行时将其初始化为零。
答案 1 :(得分:3)
这当然都写在手册中。 resb
reserves uninitialized storage in the .bss
section。此外,bin
个文件有limited section support,特别是:
章节可以指定为progbits或nobits。默认是progbits(除了 .bss,默认为nobits,当然)。 .bss部分将放在最后一个progbits部分之后, 除非start =,vstart =,follow =,或者已经指定了vfollows =。
因此," resb只是在二进制文件的末尾分配一些未使用的空间"基本上是发生了什么。不确定为什么你无法通过剖析输出文件来看到这一点。
答案 2 :(得分:2)
由于.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中所需的分配计算指针。