You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何.data段的HELLO_WORLD字符串无法在引导加载程序中加载?

引导加载程序中.data段字符串无法加载的原因分析

在编写16位实模式引导加载程序时,尝试用section组织代码,发现将HELLO_WORLD字符串放在.data段时,自定义printf函数无法加载该字符串,程序无输出;但把字符串移到.text段的printf函数下方时,程序能正常输出Hello World!,具体代码和运行结果如下:

第一段代码(.data段存放字符串)

; Set Code to run at 0x7c00
org 0x7c00
; Put into real mode
bits 16 

; Variables without values
section .bss

; Our constant values
section .data
    HELLO_WORLD: db 'Hello World!', 0

; Where our code runs
section .text
    _start:
        mov si, HELLO_WORLD ; Moves address for string into si register
        call printf ; Calls printf function
        jmp $ ; Jump forever
        
    printf:
        lodsb ; Load the next character
        cmp al, 0 ; Compares al to 0
        je _printf_done ; If they are equal...
        call print_char ; Call Print Char
        jmp printf ; Jump to the loop
    _printf_done:
        ret ; Return
    
    print_char:
        mov ah, 0x0e ; tty mode
        int 0x10 ; Video interrupt
        ret ; Return

; Fills the rest of the data with 0
times 510-($-$$) db 0
; BIOS boot magic number
dw 0xaa55   

运行结果

Booting into hard drive...

第二段代码(.text段存放字符串)

; Set Code to run at 0x7c00
org 0x7c00
; Put into real mode
bits 16 

; Variables without values
section .bss

; Our constant values
section .data

; Where our code runs
section .text
    _start:
        mov si, HELLO_WORLD ; Moves address for string into si register
        call printf ; Calls printf function
        jmp $ ; Jump forever
        
    printf:
        lodsb ;  Loads next character
        cmp al, 0 ; Compares al to 0
        je _printf_done ; If they are equal...
        call print_char ; Call Print Char
        jmp printf ; Jump to the loop
    _printf_done:
        ret ; Return
    
    print_char:
        mov ah, 0x0e ; tty mode
        int 0x10 ; Video interrupt
        ret ; Return

    HELLO_WORLD: db 'Hello World!', 0

; Fills the rest of the data with 0
times 510-($-$$) db 0
; BIOS boot magic number
dw 0xaa55   

运行结果

Booting into hard drive...
Hello World!

问题原因

核心原因是引导扇区的加载范围限制:

  • BIOS只会从磁盘加载前512字节到内存的0x7c00位置,这512字节必须包含完整的引导代码和结束标志0xaa55。
  • 汇编器默认按.text→.data→.bss的顺序排列段内容。第一段代码中,.data段在.text段之后,而.text段末尾的times 510-($-$$) db 0指令会填充当前.text段到510字节,再加上0xaa55刚好占满512字节,导致.data段的字符串被放到512字节之外,BIOS根本没有加载这部分内容到内存中。
  • 当程序执行mov si, HELLO_WORLD时,SI寄存器指向的是内存中不存在的地址,lodsb读取不到预期字符,自然无法输出内容。
  • 第二段代码中,字符串放在.text段内部且位于times指令之前,属于512字节的引导扇区范围内,会被BIOS正常加载到内存,因此程序能正确读取并输出字符串。

补充说明:$代表当前汇编地址,$$代表当前段的起始地址,times 510-($-$$)的作用是填充字节,让当前.text段的总长度达到510字节,确保最后的0xaa55刚好在第511和512字节位置,符合BIOS引导扇区的要求。

内容的提问来源于stack exchange,提问作者ThatPrimitive_Remastered

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 12:15:35