I tried to make a bootloader the last few days and this is the result:
BITS 16
;CONSTANTS
BOOTSEG equ 07C0h
STACKSEG equ 1BC0h ; BOOTSEG + 512 Byte (bootloader) + 512 Byte (second stage) + 4096 Byte (buffer) = 1BC0h
STACKSIZE equ 0400h ; 1KB stack
; INIT
mov AX, BOOTSEG
mov DS, AX ; set data segment to adress where bootloader will be loaded to
mov AX, STACKSEG
cli ; disable interrupts while set up stack
mov SS, AX
mov SP, STACKSIZE ; set up stack
sti ; restore interrupts
mov [bootdev], DL ; save boot device number
;START
mov SI, string ; get the adress of the string to print into SI
call _printstring
;LOAD 2nd STAGE
mov AH, 02h ; int 13h subfunction ah=02
mov AL, 01h ; read 1 sector
mov CX, 02h ; begin read at track 0, sector 2
mov DH, 00h ; head = 0 ????
mov DL, [bootdev] ; read from boot device
mov BX, BOOTSEG
add BX, 512
mov ES, BX ; write second stage right after first stage
mov BX, 00h
int 13h ; do it
jc fail
mov SI, success ; OK
call _printstring
jmp 09C0h:0000h ; jump to second stage, execute it
; does not work:
; 1) jmp ES:BX
;
; 2) push ES
; push BX
; retf
fail:
mov SI,error ; error on reading second stage
call _printstring
loop:
jmp loop ; infinite loop at the end
_printhex:
; AX: hex value to print
; Modifies: AX, BX, DX, CX
mov CX, 4
start: mov DX, 00h
mov BX, 10h
div BX
cmp DX, 9
jg letter
add DL, 30h
jmp store
letter: add DL, 37h
store: push DX
dec CX
jnz start
mov CX,4
print: pop AX
call _printchar
dec CX
jnz print
mov AL, 13
call _printchar
mov Al, 10
call _printchar
ret
_printchar:
; print char in AL
; Modifies: AX, BX
mov AH, 0Eh
mov BX, 07h
int 10h
ret
_printstring:
; SI : start adress of string
; Modifies: AX , BX , SI
m1: lodsb ; Loads [SI] into AL and increases SI by one
or AL, AL ; check if AL = 0
jz finish ; then finish
call _printchar ; else print charakter
jmp m1
finish:
ret ; return from the printstring call
;DATA
string db 'Started my first Bootloader', 13, 10, 0
success db 'Success', 13, 10, 0
error db 'Error', 13, 10, 0
bootdev db 0
; MAKE BOOTSECTOR
times 510-($-$$) db 0 ; fill up the sector to 512 - 2 = 510 bytes
dw 0AA55h ; set the two bootsector identifying bytes
; SECOND STAGE
add BX, 10
mov AL, 'A'
mov AH, 0Eh
mov BX, 07h
int 10h ; test output
loop2:
jmp loop2 ; infinite loop at the end
Now I have two questions:
In line 43 I have to use a jump with an absolute adress, but I want to use the values of
ES
andBX
. So I tried the two alternatives you can see in the comments but they did not work for me. What am I doing wrong?I am quite new to low-level programming. Are there some major or minor mistakes in my code? Are there code style conventions I did not consider?
I do not want to format the code, so here is the link to the asm file and you can read it with your favourite editor: https://www.dropbox.com/s/i3jpprf66nlmzz2/mybootloader.asm?m