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

NASM汇编错误:TIMES值为负数(-23/-323)求助

问题描述

我是汇编语言新手,在制作简易操作系统时遇到以下NASM错误:

src/bootloader/bootloader.asm:292: error: TIMES value -23 is negative
make: *** [build/bootloader.bin] Error 1

尝试减少代码行数后,负数数值变为-323,但问题仍未解决。以下是我的bootloader.asm代码:

org 0x7C00
bits 16

%define ENDL 0x0D, 0x0A

jmp short start
nop

bdb_oem:                    db 'MSWIN4.1'       
bdb_bytes_per_sector:       dw 512
bdb_sectors_per_cluster:    db 1
bdb_reserved_sectors:       dw 1
bdb_fat_count:              db 2
bdb_dir_entries_count:      dw 0E0h
bdb_total_sectors:          dw 2880                 
bdb_media_descriptor_type:  db 0F0h                 
bdb_sectors_per_fat:        dw 9 
bdb_sectors_per_track:      dw 18
bdb_heads:                  dw 2
bdb_hidden_sectors:         dd 0
bdb_large_sector_count:     dd 0

ebr_drive_number:           db 0
                            db 0
ebr_signature:              db 29h
ebr_volume_id:              db 12h, 34h, 56h, 78h
ebr_volume_label:           db 'BESTMAT OS' 
ebr_system_id:              db 'FAT12   '

start:
    jmp main

main:
    mov ax, 0
    mov ds, ax
    mov es, ax

    mov ss, ax
    mov sp, 0x7C00

    push es
    push word .after
    retf

.after:
    mov [ebr_drive_number], dl

    mov si, msg_hello
    call puts

    push es
    mov ah, 08h
    int 13h
    jc floppy_error
    pop es

    and cl, 0x3F
    xor ch, ch
    mov [bdb_sectors_per_track], cx

    inc dh
    mov [bdb_heads], dh

    mov ax, [bdb_sectors_per_fat]
    mov bl, [bdb_fat_count]
    xor bh, bh
    mul bx
    add ax, [bdb_reserved_sectors]
    push ax

    mov ax, [bdb_dir_entries_count]
    shl ax, 5
    xor dx, dx
    div word [bdb_bytes_per_sector]

    test dx, dx
    jz .root_dir_after
    inc ax

.root_dir_after:
    mov cl, al
    pop ax
    mov dl, [ebr_drive_number]
    mov bx, buffer
    call disk_read

    xor bx, bx
    mov di, buffer

.search_kernel:
    mov si, file_kernel_bin
    mov cx, 11
    push di
    repe cmpsb
    pop di
    je .found_kernel

    add di, 32
    inc bx
    cmp bx, [bdb_dir_entries_count]
    jl .search_kernel

    jmp kernel_not_found_error

.found_kernel:
    mov ax, [di + 26]
    mov [kernel_cluster], ax

    mov ax, [bdb_reserved_sectors]
    mov bx, buffer
    mov cl, [bdb_sectors_per_fat]
    mov dl, [ebr_drive_number]
    call disk_read

    mov bx, KERNEL_LOAD_SEGMENT
    mov es, bx
    mov bx, KERNEL_LOAD_OFFSET

.load_kernel_loop:
    mov ax, [kernel_cluster]
    add ax, 31
    mov cl, 1
    mov dl, [ebr_drive_number]
    call disk_read
    
    add bx, [bdb_bytes_per_sector]

    mov ax, [kernel_cluster]
    mov cx, 3
    mul cx
    mov cx, 2
    div cx

    mov si, buffer
    add si, ax
    mov ax, [ds:si]
    
    or dx, dx
    jz .even

.odd:
    shr ax, 4
    jmp .next_cluster_after

.even:
    and ax, 0x0FFF

.next_cluster_after:
    cmp ax, 0x0FF8
    jae .read_finish

    mov [kernel_cluster], ax
    jmp .load_kernel_loop

.read_finish:
    mov dl, [ebr_drive_number]
    mov ax, KERNEL_LOAD_SEGMENT
    mov ds, ax
    mov es, ax

    jmp KERNEL_LOAD_SEGMENT:KERNEL_LOAD_OFFSET

    jmp wait_key_and_reboot

    cli
    hlt

floppy_error:
    mov si, msg_read_failed
    call puts
    jmp wait_key_and_reboot

kernel_not_found_error:
    mov si, msg_kernel_not_found
    call puts
    jmp wait_key_and_reboot

wait_key_and_reboot:
    mov ah, 0
    int 16h            
    jmp 0FFFFh:0   

.halt:
    cli
    hlt

puts:
    push si
    push ax
    push bx

.loop:
    lodsb
    or al, al
    jz .done

    mov ah, 0x0E
    mov bh, 0
    int 0x10

    jmp .loop

.done:
    pop bx
    pop ax
    pop si    
    ret

lba_to_chs:
    push ax
    push dx

    xor dx, dx
    div word [bdb_sectors_per_track]    

    inc dx                               
    mov cx, dx                           

    xor dx, dx                           
    div word [bdb_heads]                

    mov dh, dl                           
    mov ch, al                           
    shl ah, 6
    or cl, ah                            

    pop ax
    mov dl, al                           
    pop ax
    ret

disk_read:
    push ax
    push bx
    push cx
    push dx
    push di

    push cx

    call lba_to_chs
    pop ax

    mov ah, 02h
    mov di, 3

.retry:
    pusha
    stc
    int 13h
    jnc .done
    popa
    call disk_reset
    dec di
    test di, di
    jnz .retry

.fail:
    jmp floppy_error

.done:
    popa

    pop di
    pop dx
    pop cx
    pop bx
    pop ax

    ret

disk_reset:
    pusha
    mov ah, 0
    stc
    int 13h
    jc floppy_error
    popa
    ret

msg_hello:                      db "Hello World!", ENDL, 0
msg_read_failed:                db "BESTMAT: Read from disk failed!", ENDL, 0
msg_kernel_not_found:           db "BESTMAT: KERNEL.BIN file not found!", ENDL, 0
file_kernel_bin:                db "KERNEL    BIN"
kernel_cluster:                 dw 0

KERNEL_LOAD_SEGMENT             equ 0x2000
KERNEL_LOAD_OFFSET              equ 0


times 510-($-$$)                db 0
dw 0AA55h

buffer:
解决方案

问题根源

times 510-($-$$) db 0 的作用是填充空字节,确保引导扇区(含末尾的0xAA55签名)总长度恰好为512字节。其中$-$$代表当前行到段起始(org 0x7C00)的字节数。出现负数错误,说明当前代码(包括末尾的buffer)的总长度已经超过了510字节。

你把buffer:放在了引导扇区签名之后,这部分会被计入$-$$的长度统计,直接导致总长度超标。而BIOS只会加载引导扇区的前512字节,缓冲区属于磁盘读取的临时存储,应该放在引导扇区之外的内存区域,不能占用引导扇区的空间。

修复步骤

  1. 删除代码末尾的buffer:定义
  2. 定义缓冲区到引导扇区之外的内存:
    在代码开头(org 0x7C00之后)添加缓冲区地址的定义:
    org 0x7C00
    bits 16
    
    %define ENDL 0x0D, 0x0A
    BUFFER_ADDR equ 0x7E00  ; 引导扇区加载在0x7C00,0x7E00是后续的空闲内存区域,安全可用
    
  3. 替换代码中所有的buffer引用:
    把所有用到buffer的地方替换为BUFFER_ADDR,比如:
    ; 原代码:mov bx, buffer
    mov bx, BUFFER_ADDR
    call disk_read
    
    ; 原代码:mov di, buffer
    mov di, BUFFER_ADDR
    
    ; 原代码:mov si, buffer
    mov si, BUFFER_ADDR
    

额外说明

引导扇区有严格的长度限制:前510字节用于代码和必要数据,最后2字节必须是0xAA55签名。任何超过510字节的内容都会导致times指令计算出负数,因为510 - 总长度会变成负数。将缓冲区移到0x7E00开始的内存区域,既符合BIOS的加载规则,也不会占用引导扇区的宝贵空间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:32:04