最近几天我尝试制作一个引导加载程序,结果如下:
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
现在我有两个问题:
在第 43 行,我必须使用带绝对地址的跳转,但我想使用
ES
and的值BX
。因此,我尝试了您可以在评论中看到的两种替代方案,但它们对我不起作用。我究竟做错了什么?我对低级编程很陌生。我的代码中是否存在一些重大或次要错误?有没有我没有考虑过的代码风格约定?
我不想格式化代码,所以这里是 asm 文件的链接,你可以用你最喜欢的编辑器阅读它: https ://www.dropbox.com/s/i3jpprf66nlmzz2/mybootloader.asm?m