Writing a boot loader in assembler
From Organic Design wiki
======================================== Daniels NASM bootstraps tutorial ======================================== author: Daniel Marjamäki (daniel.marjamaki@home.se) Preface ------- This tutorial is a guide for those who want to create their own bootstraps. The basics ---------- These are the rules that you must follow: - The BIOS will load your bootstrap to address 07C00h. Sadly, the segment and offset varies. - Bootstraps must be compiled as plain binary files. - The filesize for the plain binary file must be 512 bytes. - The file must end with AA55h. A minimal bootstrap ------------------- This bootstrap just hangs: ; HANG.ASM ; A minimal bootstrap hang: ; Hang! jmp hang times 510-($-$$) db 0 ; Fill the file with 0's dw 0AA55h ; End the file with AA55 The line starting with "times" is a command that only NASM understands. The line will insert 0's until the filesize is 510 bytes. The whole file will therefore be 512 bytes. The last instruction puts AA55 at the end of the file. To compile the bootstrap, use this command: nasm hang.asm -o hang.bin If you want to test the bootstrap, you must first put it on the first sector on a floppy disk. You can for example use 'dd' or 'rawrite'. When the bootstrap is on the floppy, test it by restarting your computer with the floppy inserted. The computer should hang then. The memory problem ------------------ There is a memory problem. As I've written bootstraps are always loaded to address 07C00. We don't know what segment and offset the BIOS has put us in. The segment can be anything between 0000 and 07C0. This is a problem when we want to use variables. The solution is simple. Begin your bootstrap by jumping to your bootstrap, but jump to a known segment. Here is an example: ; JUMP.ASM ; Make a jump and then hang ; Tell the compiler that this is offset 0. ; It isn't offset 0, but it will be after the jump. [ORG 0] jmp 07C0h:start ; Goto segment 07C0 start: ; Update the segment registers mov ax, cs mov ds, ax mov es, ax hang: ; Hang! jmp hang times 510-($-$$) db 0 dw 0AA55h If you compile and test this bootstrap, there will be no visible difference to the minimal bootstrap presented earlier. The computer will just hang. Some exercises -------------- 1. Create a bootstrap that outputs "====" on the screen, and then hangs. Tip: modify the jump.asm program. 2. Create a bootstrap that outputs "Hello Cyberspace!" and hangs. 3. Create a bootstrap that loads a program off the floppy disk and jumps to it. Solutions to the exercises -------------------------- 1. ; 1.ASM ; Print "====" on the screen and hang ; Tell the compiler that this is offset 0. ; It isn't offset 0, but it will be after the jump. [ORG 0] jmp 07C0h:start ; Goto segment 07C0 start: ; Update the segment registers mov ax, cs mov ds, ax mov es, ax mov ah, 9 ; Print "====" mov al, '=' ; mov bx, 7 ; mov cx, 4 ; int 10h ; hang: ; Hang! jmp hang times 510-($-$$) db 0 dw 0AA55h 2. ; 2.ASM ; Print "Hello Cyberspace!" on the screen and hang ; Tell the compiler that this is offset 0. ; It isn't offset 0, but it will be after the jump. [ORG 0] jmp 07C0h:start ; Goto segment 07C0 ; Declare the string that will be printed msg db 'Hello Cyberspace!' start: ; Update the segment registers mov ax, cs mov ds, ax mov es, ax mov si, msg ; Print msg print: lodsb ; AL=memory contents at DS:SI cmp al, 0 ; If AL=0 then hang je hang mov ah, 0Eh ; Print AL mov bx, 7 int 10h jmp print ; Print next character hang: ; Hang! jmp hang times 510-($-$$) db 0 dw 0AA55h 3. ; 3.ASM ; Load a program off the disk and jump to it ; Tell the compiler that this is offset 0. ; It isn't offset 0, but it will be after the jump. [ORG 0] jmp 07C0h:start ; Goto segment 07C0 start: ; Update the segment registers mov ax, cs mov ds, ax mov es, ax reset: ; Reset the floppy drive mov ax, 0 ; mov dl, 0 ; Drive=0 (=A) int 13h ; jc reset ; ERROR => reset again read: mov ax, 1000h ; ES:BX = 1000:0000 mov es, ax ; mov bx, 0 ; mov ah, 2 ; Load disk data to ES:BX mov al, 5 ; Load 5 sectors mov ch, 0 ; Cylinder=0 mov cl, 2 ; Sector=2 mov dh, 0 ; Head=0 mov dl, 0 ; Drive=0 int 13h ; Read! jc read ; ERROR => Try again jmp 1000h:0000 ; Jump to the program times 510-($-$$) db 0 dw 0AA55h This is a small loadable program. ; PROG.ASM mov ah, 9 mov al, '=' mov bx, 7 mov cx, 10 int 10h hang: jmp hang This program creates a disk image file that contains both the bootstrap and the small loadable program. ; IMAGE.ASM ; Disk image %include '3.asm' %include 'prog.asm' Finally ------- Thanks for reading. Email me any suggestions, comments, questions, ... If you don't use NASM and are having problems with the code, you should contact me. Together we can solve it.