2015-12-14 54 views
3

我看到一段使用resb的NASM代碼。但是,此代碼在實模式操作系統中運行,輸出格式爲平面二進制。這樣做時NASM不會給出錯誤,但解剖完輸出文件後,我仍然無法找到實際發生的情況。NASM的resb以二進制輸出格式做什麼?

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只是在分配的二進制
  • 年底一些未使用的空間,它並沒有真正在所有的工作,和東西爆炸了。

回答

4

NASM生成一個二進制-f bin它遵循一些有關章節的基本規則。該NASM manual這樣說:

7.1.3多分支持的bin格式

[剪斷]

  • .bss段將被放置在最後一節PROGBITS後,除非啓動=, 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_start_bss_end。這些標籤用於確定區域的範圍,以便在我們的代碼開始執行時將其初始化爲零。

+0

供參考:NASM創建一個符號'section.bss.start',所以你不需要手動指定它。不過不知道結束,因此無論如何手動定義符號可能會更清晰。 –

+0

@AnonymousShadow你是非常正確的,但確實如此,但爲了清晰起見,我指定了開始標籤,以便您瞭解機制的工作原理。這種技術也可以用於可能不會像NASM那樣創建隱藏標籤的彙編程序。我不相信NASM產生的結束標籤,只是一開始。 –

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中所需的分配計算的。

3

這一切都寫在手冊當然。 resb reserves uninitialized storage in the .bss section。此外,bin文件具有limited section support,特別是:

段可以被指定爲progbits或nobits。默認是progbits(除了 .bss,當然默認爲nobits)。 除非指定了start =,vstart =,following =或vfollows =,否則.bss部分將放在最後一個progbits部分 之後。

因此,「RESB只是簡單的分配在二進制結束一些未使用的空間」基本上是發生了什麼。不知道爲什麼你不能解剖輸出文件。