如何解决'bootloader.asm:30:错误:TIMES值-44为负'NASM中的问题 [英] How to Solve 'bootloader.asm:30: error: TIMES value -44 is negative' Problem in NASM

查看:295
本文介绍了如何解决'bootloader.asm:30:错误:TIMES值-44为负'NASM中的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Hello World内核和引导程序...我编写了这段代码,但是当我尝试通过NASM编译它时,它说:"bootloader.asm:30:error:TIMES value -44 is negative"./p>

bootloader.asm:

    [BITS 16]
[ORG 0x7C00]

MOV DL, 0x80
MOV DH, 0x0 
MOV CH, 0x0 
MOV CL, 0x02 
MOV BX, 0x1000 
MOV ES, BX 
MOV BX, 0x0 

ReadFloppy:
MOV AH, 0x02
MOV AL, 0x01
INT 0x13
JC ReadFloppy 


MOV AX, 0x1000
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX

JMP 0x1000:0x0



TIMES 510 - ($ - $$) db 0 
DW 0xAA55

kernel.asm:

MOV AH, 0x0E 
MOV BH, 0x00 
MOV BL, 0x07 

MOV SI, msg 
CALL PrintString 

JMP $ 

PrintString:
nextch:
MOV AL, [SI] 
OR AL, AL
JZ exit 
INT 0x10 
INC SI 
JMP nextch
RET

exit:
RET

msg db 'Hello world from the kernel!', 13, 10, 0

TIMES 512 - ($ - $$) db 0 

我用过; nasm -f bin bootloader.asm -o bootloader.bin -p kernel.asm

解决方案

与双重使用times相比,您有一个更根本的问题:您正在使用NASM的-p开关预先包含文件kernel.asm,而建立bootloader.asm.即使您放弃了一个或两个times用法,内核也会被首先组装并首先执行,而不是您的加载器首先执行.

我修复了您的示例以执行应做的事情:将kernel.asm输出写入第二个512字节扇区,然后在加载程序中,从引导单元加载该扇区并跳转到该扇区.

这是固定源bootloader.asm:

        cpu 8086
        bits 16
        section loader vstart=7C00h start=0

MOV AX, 0x1000
MOV DS, AX
MOV ES, AX
MOV SS, AX
        xor sp, sp

MOV DH, 0x0
MOV CH, 0x0
MOV CL, 0x02
        xor bx, bx

        mov di, 16

ReadFloppy:
        dec di
        jz .error

MOV AH, 0x02
MOV AL, 0x01
INT 0x13
JC ReadFloppy

JMP 0x1000:0x0


.error:
        mov ax, '!' | 0E00h
        mov bx, 7
        int 10h
.halt:
        sti
        hlt
        jmp .halt


TIMES 510 - ($ - $$) db 0
DW 0xAA55

%include "kernel.asm"

这是kernel.asm:

        section kernel vstart=0 follows=loader

MOV AH, 0x0E
MOV BH, 0x00
MOV BL, 0x07

MOV SI, msg
CALL PrintString

halt:
        sti
        hlt
        jmp halt

PrintString:
nextch:
MOV AL, [SI]
OR AL, AL
JZ exit
INT 0x10
INC SI
JMP nextch

exit:
RET

msg db 'Hello world from the kernel!', 13, 10, 0

TIMES 512 - ($ - $$) db 0

这是构建和运行整个示例的方法:

$ nasm -f bin bootloader.asm -o bootloader.bin && qemu-system-i386 -drive file=bootloader.bin,if=floppy,format=raw,index=0,media=disk
$ nasm -f bin bootloader.asm -o bootloader.bin && qemu-system-i386 -drive file=bootloader.bin,format=raw,index=0,media=disk

请注意,我更改了以下内容:

  • 代替org,我使用了带有vstart=7C00hstart=0的加载程序的段指令.这基本上与您的原始作品相同,但与其他部分比较合适.

  • 使用%include指令包含内核,并将其放置在加载器的 之后,而不是加载器的前面(例如您使用-p的情况).

  • 因此,kernel.asm文件不再出现在NASM命令行上.

  • 内核放置在一个单独的节中,该节具有vstart=0(计算标签,就像该节在段的开头加载一样)和follows=loader(将其正确地放置在输出文件中)第二部门).

  • 在设置ss之后的指令中,我设置了sp,因为在此之前我们无法确定sp的值.置零sp(使用xor)意味着堆栈从段的顶部开始,这与我们读取内核扇区的方式不符.

  • 我在JMP nextch之后放下了RET.从未达到.

  • 我将暂停循环从JMP $更改为sti \ hlt \ jmp,使其在暂停时变为空闲.这意味着qemu进程在运行此循环时不会浪费CPU时间.

  • 我放弃了您的MOV DL, 0x80.这允许从硬盘单元或软盘引导;在我们的入口点,ROM-BIOS已使用要加载的单元初始化了dl.

  • 我将这些段和堆栈初始化移动到了扇区读取之前.这样可以确保堆栈不与读取目标重叠.

  • 我在di中添加了一个循环计数器以进行读取尝试.我添加了一个额外的分支,如果它用完了,它会显示一个感叹号,然后停止.重试读取操作没有错,但是,如果读取操作永久失败,则应进行最大量的重试.

  • 我放弃了fsgs的设置,因为它们从未使用过.

I'm developing a Hello World kernel and bootloader...I wrote this code but when I try to compile it via NASM It says : "bootloader.asm:30: error: TIMES value -44 is negative".

bootloader.asm:

    [BITS 16]
[ORG 0x7C00]

MOV DL, 0x80
MOV DH, 0x0 
MOV CH, 0x0 
MOV CL, 0x02 
MOV BX, 0x1000 
MOV ES, BX 
MOV BX, 0x0 

ReadFloppy:
MOV AH, 0x02
MOV AL, 0x01
INT 0x13
JC ReadFloppy 


MOV AX, 0x1000
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX

JMP 0x1000:0x0



TIMES 510 - ($ - $$) db 0 
DW 0xAA55

kernel.asm:

MOV AH, 0x0E 
MOV BH, 0x00 
MOV BL, 0x07 

MOV SI, msg 
CALL PrintString 

JMP $ 

PrintString:
nextch:
MOV AL, [SI] 
OR AL, AL
JZ exit 
INT 0x10 
INC SI 
JMP nextch
RET

exit:
RET

msg db 'Hello world from the kernel!', 13, 10, 0

TIMES 512 - ($ - $$) db 0 

I used; nasm -f bin bootloader.asm -o bootloader.bin -p kernel.asm

解决方案

You have a more fundamental problem than your doubled usage of times: You are using NASM's -p switch to pre-include the file kernel.asm while building bootloader.asm. Even if you drop one or both times usages, the kernel will be assembled first and executed first, instead of your loader executing first.

I fixed your example to do what it seems supposed to do: Write the kernel.asm output into the second 512-bytes sector, then in the loader, load that sector from the boot unit and jump to it.

Here's the fixed source, bootloader.asm:

        cpu 8086
        bits 16
        section loader vstart=7C00h start=0

MOV AX, 0x1000
MOV DS, AX
MOV ES, AX
MOV SS, AX
        xor sp, sp

MOV DH, 0x0
MOV CH, 0x0
MOV CL, 0x02
        xor bx, bx

        mov di, 16

ReadFloppy:
        dec di
        jz .error

MOV AH, 0x02
MOV AL, 0x01
INT 0x13
JC ReadFloppy

JMP 0x1000:0x0


.error:
        mov ax, '!' | 0E00h
        mov bx, 7
        int 10h
.halt:
        sti
        hlt
        jmp .halt


TIMES 510 - ($ - $$) db 0
DW 0xAA55

%include "kernel.asm"

This is kernel.asm:

        section kernel vstart=0 follows=loader

MOV AH, 0x0E
MOV BH, 0x00
MOV BL, 0x07

MOV SI, msg
CALL PrintString

halt:
        sti
        hlt
        jmp halt

PrintString:
nextch:
MOV AL, [SI]
OR AL, AL
JZ exit
INT 0x10
INC SI
JMP nextch

exit:
RET

msg db 'Hello world from the kernel!', 13, 10, 0

TIMES 512 - ($ - $$) db 0

This is how to build and run the entire example:

$ nasm -f bin bootloader.asm -o bootloader.bin && qemu-system-i386 -drive file=bootloader.bin,if=floppy,format=raw,index=0,media=disk
$ nasm -f bin bootloader.asm -o bootloader.bin && qemu-system-i386 -drive file=bootloader.bin,format=raw,index=0,media=disk

Note that I changed the following:

  • Instead of org I used a section directive for the loader, with vstart=7C00h and start=0. This is essentially the same as your original, but fits better with the other section.

  • The kernel is included using the %include directive, and is placed after the loader, not before it (like with your -p use).

  • The file kernel.asm thus does not occur on the NASM command line any longer.

  • The kernel is put in a separate section, which has vstart=0 (calculates labels as if that section was loaded at the start of a segment) and follows=loader (to correctly place it in the output file as the second sector).

  • In the instruction immediately after setting ss I set sp, as we cannot be sure of the value of sp prior to this. Zeroing sp (with xor) means the stack starts at the top of the segment, that is out of the way of where we read the kernel sector to.

  • I dropped the RET after JMP nextch. It was never reached.

  • I changed the halting loop from JMP $ to sti \ hlt \ jmp to idle while halting. This means the qemu process won't waste CPU time while running this loop.

  • I dropped your MOV DL, 0x80. This allows booting from either a hard disk unit or a diskette; at our entrypoint the ROM-BIOS has initialised dl with the unit we're being loaded from.

  • I moved the segments and stack initialisation to before the sector reading. This insures the stack does not overlap with the read destination.

  • I added a loop counter in di for the read attempts. I added an additional branch for if this runs out, which displays an exclamation mark then halts. Retrying the read operation is not wrong, but if it fails permanently then there should be a maximum amount of retries.

  • I dropped setting fs and gs as they are never used.

这篇关于如何解决'bootloader.asm:30:错误:TIMES值-44为负'NASM中的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆