The assembly loader does not jump to the kernel

I am trying to write a bootloader and a kernel in an assembly for training. When I compile my code and boot the virtual machine with it, the bootloader seems to work correctly, but the kernel never starts. I think I am retelling the wrong instruction, but I don’t know what corrections I need to make in order to solve my problem. It is also likely that I am trying to make a floppy disk incorrectly, but I do not think this is a problem. When I look at image files in a hex editor, it seems that they were added correctly. Another reason might be reading the wrong sector from the floppy disk. I am trying to get the kernel to be turned on and read from the sector right after the bootloader.

To create and run this code, I do the following in Windows Vista x64:

nasm bootloader_2.asm -f bin -o bootloader_2.bin nasm kernel_2.asm -f bin -o kernel.bin partcopy bootloader_2.bin bootloader_2.img 0d 511d partcopy kernel_2.bin kernel_2.img 0d 511d copy bootloader.img /b + kernel.img POS_2.img 

Then I use Virtual VM Virtual Box to mount POS_2.img as a floppy drive and run it on the guest system.

results

The Patrick bootloader started. Floppy was reset. Reading kernel Loaded kernel sector

. And the kernel never starts.

Here is my code

bootloader_2.asm

 bits 16 org 0x7C00 boot: jmp loader ; OEM Parameter block / BIOS Parameter block (wtf is this for?) times 0Bh-$+boot DB 0 bpbBytesPerSector: DW 512 bpbSectorsPerCluster: DB 1 bpbReservedSectors: DW 1 bpbNumberOfFATs: DB 2 bpbRootEntries: DW 224 bpbTotalSectors: DW 2880 bpbMedia: DB 0xF0 bpbSectorsPerFAT: DW 9 bpbSectorsPerTrack: DW 18 bpbHeadsPerCylinder: DW 2 bpbHiddenSectors: DD 0 bpbTotalSectorsBig: DD 0 bsDriveNumber: DB 0 bsUnused: DB 0 bsExtBootSignature: DB 0x29 bsSerialNumber: DD 0xa0a1a2a3 bsVolumeLabel: DB "MOS FLOPPY" bsFileSystem: DB "FAT12" ; END PARAMETER BLOCK ; ----- Variables ----- started db "Patrick Bootloader Started...", 0x0D, 0x0A, 0 floppy_reset_done db "Floppy has been reset.", 0x0D, 0x0A, 0 loading_msg db "Reading Kernel Sector", 0x0D, 0x0A, 0 loading_sucess db "Kernel Sector Loaded", 0x0D, 0x0A, 0 done db "Bootloader Done.", 0x0D, 0x0A, 0 ; ----- End Variables ----- ; ----- Calls ----- reset_floppy: mov ah, 0 mov dl, 0 int 0x13 jc reset_floppy mov si, floppy_reset_done call print_string ret read_kernel: mov si, loading_msg call print_string mov si, 0x0 mov ax, 0x1000 ; setting up the address to read into mov es, ax ; moving the value in to es xor bx, bx ; clearing bx mov ah, 0x02 ; floppy function mov al, 1 ; read 1 sector mov ch, 1 ; track mov cl, 2 ; sector to read mov dh, 0 ; head number mov dl, 0 ; drive number int 0x13 ; BIOS Interrupt Call jc read_kernel mov si, loading_sucess call print_string ret print_string: lodsb or al, al jz .done mov ah, 0x0E int 0x10 jmp print_string .done: ret ; input is ax, cx is destroyed print_hex: mov cx, 4 .next_digit: push cx mov cl, 4 rol ax, cl push ax and al, 0x0F add al, '0' cmp al, '9' jle .not_a_leter add al, 'A'-'9'-1 .not_a_leter: mov ah, 0x0E int 0x10 pop ax pop cx loop .next_digit ret ; ----- End of Calls ----- ; ===== Bootloader Main ===== loader: mov si, started call print_string call reset_floppy call read_kernel jmp 0x1000:0x0 mov si, done ; never reached. Intentional for debugging call print_string ; these lines failure to produce a result tell us that the jmp was attempted ; ===== End of Bootloader Main ===== times 510-($-$$) db 0 dw 0xAA55 

kernel_2.asm

 kernel: jmp k_main welcome_msg db "Welcome to Patrick Operating System!", 0x0D, 0x0A, 0 print_string: lodsb or al, al jz .done mov ah, 0x0E int 0x10 jmp print_string .done: ret k_main: mov si, welcome_msg call print_string .k_main_loop: jmp .k_main_loop cli hlt times 512-($-$$) db 0 
+6
source share
1 answer

If you pointed out the obvious, your script will not copy the correct file. In some places, you refer to kernel.bin , and in others, kernel_2.bin . Try instead:

 nasm bootloader_2.asm -f bin -o bootloader_2.bin nasm kernel_2.asm -f bin -o kernel_2.bin partcopy bootloader_2.bin bootloader_2.img 0d 511d partcopy kernel_2.bin kernel_2.img 0d 511d copy bootloader.img /b + kernel_2.img POS_2.img 

It may also be easier for you to use such things instead of dd . It is available as part of Cygwin and has the advantage of being able to write files or physical devices such as a true floppy disk.

In addition, you should use a Makefile instead of a script. This will help with the further expansion of your project.

However, there are three main problems with the code. First, the next sector to be loaded is on cylinder 0, not cylinder 1. Second, the code cannot simply safely ret to the kernel β€” you must jump there explicitly. This piece of code will look like this:

 read_kernel: mov si, loading_msg call print_string mov si, 0x0 mov ax, 0x1000 ; setting up the address to read into mov es, ax ; moving the value in to es xor bx, bx ; clearing bx mov ah, 0x02 ; floppy function mov al, 1 ; read 1 sector mov ch, 0 ; cylinder mov cl, 2 ; sector to read mov dh, 0 ; head number mov dl, 0 ; drive number int 0x13 ; BIOS Interrupt Call jc read_kernel push es ; either push the address and retf or use far jmp push bx ; mov si, loading_sucess call print_string ; jmp 0x1000:0 ; alternative to push/retf is simple long jump retf 

The third problem is the core. You have not changed the DS register to indicate a new offset, so even if you go to this code, it will not print the line that you are going to use. Change this code instead:

 k_main: push cs ; save the cs reg pop ds ; use as ds also mov si, welcome_msg call print_string .k_main_loop: jmp .k_main_loop 
+5
source

Source: https://habr.com/ru/post/974585/


All Articles