NASM的resb在二进制输出格式中做了什么?

时间:2015-12-14 13:51:08

标签: assembly x86 nasm x86-16

我看到一段使用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只是在二进制文件末尾分配一些未使用的空格
  • 它根本不起作用,而且东西爆炸了。

3 个答案:

答案 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中所需的分配计算指针。