How to Solve 'bootloader.asm:30: error: TIMES value -44 is negative' Problem in NASM

一个人想着一个人 提交于 2020-04-07 10:29:22

问题


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


回答1:


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.



来源:https://stackoverflow.com/questions/60980527/how-to-solve-bootloader-asm30-error-times-value-44-is-negative-problem-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!