Hey guys, i'm trying to compile this piece of code with nasm in Ubuntu. It's a boot loader for a simple operational system i'm doing as a university project.

[BITS 16]       ; 16 bit instructions

[ORG 0x7C00]

jmp word load

                db "ONYXDISK"           ; OEM Label String
                dw 512                  ; Bytes per sector
                db 1                    ; Sectors per FAT cluster
                dw 36                   ; Resered sector count
                db 2                    ; number of FATs
                dw 224                  ; Root dir entries
                dw 2880                 ; Total Sectors
                db 240                  ; Double sided, 18 sectors per track
                dw 9                    ; Sectors per FAT
                dw 18                   ; Sectors per track
                dw 2                    ; Head count (double sided)
                dd 0                    ; Hidden sector count 
        
load:
        mov ah, 0               ; floppy drive reset command
        int 13h                 ; bios floppy interrupt
        or ah, ah               ; check for error code
        jnz load                ; repeat if error

        mov 6ax, 0
        mov es, ax
        mov bx, 0x1000          ; destination address of kernel = 0000:1000

        mov ah, 02h             ; floppy read sector command
        mov al, 02h             ; number of sectors to read
        mov ch, 0               ; cylinder
        mov cl, 02h             ; sector
        mov dh, 0               ; head
        int 13h                 ; bios floppy interrupt
        or ah, ah               ; check for error code
        jnz load                ; repeat if error

        cli                     ; Disable interrupts

        xor ax, ax
        mov ds, ax              ; Set DS-register to 0 - used by lgdt

        lgdt [gdt_desc]         ; Load the GDT descriptor

        mov eax, cr0            ; Copy the contents of CR0 into EAX
        or eax, 1               ; Set bit 0
        mov cr0, eax            ; Copy the contents of EAX into CR0

        jmp 08h:kernel_seg      ; Jump to code segment, offset clear_pipe


[BITS 32]
kernel_seg:
        mov ax, 10h             ; save data segment
        mov ds, ax              ; setup data segment
        mov ss, ax              ; setup stack segment
        mov esp, 090000h        ; move the stack pointer to 090000h

        jmp 08h:01000h          ; jump to our kernel


gdt:                    ; address for the GDT

gdt_null:               ; null Segment
        dd 0
        dd 0

gdt_code:               ; code segment, read/execute, nonconforming
        dw 0FFFFh
        dw 0
        db 0
        db 10011010b
        db 11001111b
        db 0

gdt_data:               ; data segment, read/write, expand down
        dw 0FFFFh
        dw 0
        db 0
        db 10010010b
        db 11001111b
        db 0

gdt_end: 

gdt_desc: 
        dw gdt_end - gdt - 1    ; limit (size)
        dd gdt                  ; address of the GDT

times 510-($-$$) db 0           ; fill up the file with zeros

        dw 0AA55h               ; boot sector identifier

I'm using the following command at the terminal to compile:

nasm -f bin boot.asm -o boot.bin

But I keep getting this error:

nasm "boot.asm" (in directory: /home/luiseduardo14/Projects/simple os)
Compilation failed.
boot.asm:29: error: invalid combination of opcode and operands

I don't know what's wrong! Help me guys.

Recommended Answers

All 3 Replies

Well, I haven't written an x86 boot loader since about 1986 or 1987... Since there isn't anything at line 29, the assembler has probably skipped over the empty lines, meaning that the error is really at (just a guess) line 34 or 35 in your code. However, I see that you are using the 32bit eax and similar registers. Standard BIOS's boot in 16-bit mode (still, AFAIK), which means you have ax, bx, cx, and dx 16-bit registers at boot, so even if it compiles (assembles), it may not work as a boot loader. I am right now looking at my Intel 8086 User's Manual from October 1979... :-) In any case, once you load the boot code from disc, you can switch to 32-bit mode (setting up the GDT and such as I see you are doing) on todays' computers and go from there. The general operation as I recall it was simply to call the disc load bios interrupt (13h) which will load the sector read (512 bytes) into memory at a specific location, which you then jump to + the current offset, and continue executing the instructions found there. As I said, I haven't done this for about 25 years so 1) things change, and 2) I don't remember all of the details, though somewhere in my boxes of old floppies I have the original code. Less the partition table on a HD, it is amazing how much you can do in 512 bytes of pure machine code! :-)

Anyway, unless your professor has explicitly forbidden it, you should disassemble the boot code on a modern computer to see what they are doing, assuming you haven't done that already. There are systems with 32-bit bioses, but they are not compatible with older operating systems (MS-DOS for example), so they also have to support the old 16-bit mode as well.

Finally, FWIW, here is a link to a good Wikipedia article on x86 bootloaders: http://en.wikibooks.org/wiki/X86_Assembly/Bootloaders

There is nothing in line 29, but there is a typo in line 26.

mov 6ax, 0

you probably meant

mov ax, 0

How are you accessing 32-bit registers without a prefix before
going into protected mode?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.