0

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

fuz
  • 88,405
  • 25
  • 200
  • 352
Arda AKKAYA
  • 13
  • 1
  • 2
  • 2
    The problem is that both `kernel.asm` and `bootloader.asm` have the `time 512 - ($ - $$)` trick in them despite being assembled into the same section. Thus, `kernel.asm` already fills 512 bytes and the offset to get to 512 bytes is negative in `bootloader.asm`. What are you trying to achieve? – fuz Apr 01 '20 at 21:27
  • 2
    While this is, as @fuz pointed out, due to the doubled `times` usage, here's another question involving the same error message. In that other question the reason was that the content grew beyond the 510 bytes allowed: [How to fix "os.asm:113: error: TIMES value -138 is negative" in assembly language](https://stackoverflow.com/questions/53858770/how-to-fix-os-asm113-error-times-value-138-is-negative-in-assembly-languag) (Posted here because someone coming across this question may actually have that other problem.) – ecm Apr 01 '20 at 22:29
  • @fuz i fixed it. Now as you can see i have a problem of 512 bytes... I tried to make a kernel-loader. How can i get more space on my kernel? – Arda AKKAYA Apr 02 '20 at 01:19
  • @ArdaAKKAYA You have not fixed your problem. You have merely removed the `TIMES 512 ...` line from your code. This does not fix your problem, it simply removes the error message. That's why I asked: what are you trying to achieve? What layout is your code supposed to have in memory at the end? – fuz Apr 02 '20 at 01:42
  • 3
    @ArdaAKKAYA Your code looks like it's trying to load a “kernel” on the second sector of your disk into RAM at address `1000:0000` and then tries to jump there. Is this what you are trying to achieve? If yes, I can write an answer that shows how to set up such a memory layout. – fuz Apr 02 '20 at 01:47
  • Yes,Please help me – Arda AKKAYA Apr 02 '20 at 16:53

1 Answers1

3

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.

ecm
  • 2,583
  • 4
  • 21
  • 29