📄 bootblk.asm
字号:
include comstruc.inc
cseg segment byte public 'code'
assume cs:cseg
start:
cli
mov ax,9000h
mov ss,ax
mov sp,0fffeh
sti
mov es,ax
push bp
mov bp,sp
sub sp,10
; stack arranges like this
; [bp-2] : load loop time
; [bp-4] : current index entry address
; [bp-6] : base address of each load modual
; [bp-8] : patch loop time
; [bp-10] : current redirection table entry address
push cs
pop ds
mov si,7c00h
mov di,0f000h ; mov to 9000h:0f000h
mov cx,512
cld
repnz movsb
; we issue al long jump to execute the
; code segment we just move
db 0eah ; long jump opercode
dw $+0f000h+4 ; resume execution after long jump
dw 9000h ; new code segment
; new code segment start here
; set ds correspond to cs
mov ax,9000h
mov ds,ax
; we first call getzone to get the
; second half of bootblock, and move
; it to the proper address
mov ax,0 ; get whole bootblock
push ax
call getzone
pop cx
mov si,0f600h ; second half of bootblk
mov di,0f200h
mov cx,512
cld
repnz movsb
; check the validate of stuix file system
; we have patched already
mov si,0f000h
mov ax,[si+200h] ; get modual count
cmp ax,0
ja bnext1 ; must > 0
mov ax,1
push ax
call panic ; never go back
bnext1:
mov [bp-2],ax
mov word ptr [bp-4],0f202h ; first entry address of zone array
mov word ptr [bp-6],0 ; from 9000:0000 ~ 9000:f000
bw1loop:
cmp word ptr [bp-2],0
jbe bnext2 ; load over
; verify if the entry of data zone exist
mov di,[bp-4]
cmp word ptr [di],0
jne bnext3
mov ax,2
push ax
call panic
bnext3:
push [di]
call getzone
pop cx
mov si,0f400h
mov di,[bp-6]
mov cx,1024
cld
repnz movsb
add word ptr [bp-4],2
dec word ptr [bp-2]
add word ptr [bp-6],400h ; next modual
jmp bw1loop
bnext2:
; now patch the modual we just load
; first locate the redirection table
; determine how many address need
; patch and how to
xor si,si
mov ax,[si]
cmp ax,5a4dh
je bnext4
mov ax,3
push ax
call panic ; no magic # present
bnext4:
; set stack and code segment prototype
; for stuix loader according to the
; information found in exe header
mov si,0eh
mov ax,[si] ; patch ss
add ax,9020h
mov si,0f000h
mov [si+502],ax
mov si,10h
mov ax,[si]
mov si,0f000h
mov [si+504],ax ; set sp
mov si,16h
mov ax,[si] ; patch cs
add ax,9020h
mov si,0f000h
mov [si+508],ax
mov si,14h ; set ip
mov ax,[si]
mov si,0f000h
mov [si+506],ax
; start to patch all the data segment
; determine the count
mov si,6
mov ax,[si] ; number of relocation entries
mov [bp-8],ax
; get first entry address of patch table
mov si,18h
mov ax,[si]
mov [bp-10],ax
bw2loop:
cmp word ptr [bp-8],0
jbe bnext5 ; patch over
; patch data segment one by one
mov si,[bp-10]
mov di,[si+2] ; segment
mov si,[si] ; offset
push es
mov ax,9020h ; segment after 512 byte header
add ax,di
mov es,ax
add word ptr es:[si],9020h
pop es
add word ptr [bp-10],4
dec word ptr [bp-8]
jmp bw2loop
bnext5:
; patch over, before pass control to
; stuix loader, we will set the stack
; segment properly, after stack is
; changed, our bootstrap program local
; variable is completely obsoleted so
; move the prototype of cs, ip, ss, sp
; from the data segment just before 55aah
mov si,0f000h
mov ss,[si+502] ; load stack segment
mov sp,[si+504]
mov si,0f000h+506
db 0ffh ; memory indirect long jump
db 2ch
; control pass to stuix loader
;/============================================================================
;
; panic
;
;============================================================================/
panic proc near
push bp
mov bp,sp
mov si,0f000h+475 ; diagmes base address
diagmes:
lodsb
cmp al,0
jz disperr
push si
mov bx,7
mov ah,0eh
int 10h
pop si
jmp diagmes
disperr:
mov al,4[bp]
add al,30h ; convert to ASCII
mov bx,7
mov ah,0eh
int 10h
die:
jmp die ; stop here
panic endp
;/============================================================================
;
; getzone
;
;============================================================================/
getzone proc near
push ds
push es
push bp
mov bp,sp
mov ax,8[bp] ; get parameter
; we use only 16 bit addressing zones because
; it is big enough for such a small diskette
; but we still need to implement C H S translation
sub sp,6 ; alloc for C H S varible storage
mov bx,2
mul bx
inc ax ; covert base number from 0 to 1
mov bx,36 ; 2*18
xor dx,dx
div bx
mov [bp-2],ax ; cylinder #
cmp dx,17
ja znext
mov word ptr [bp-4],0 ; head 0#
jmp zcombin
znext:
mov word ptr [bp-4],1 ; head 1#
zcombin:
mov ax,dx
xor dx,dx
mov bx,18
div bx
mov [bp-6],dx ; sector #
; start floppy I/O
mov cx,5
push cx ; set retry times
zretry:
mov bx,0f400h ; physical address 9000:f400h
mov dl,0 ; floppy A
mov dh,[bp-4] ; load head #
mov ch,[bp-2] ; load cylinder #
mov cl,[bp-6] ; load sector #
mov al,2 ; 1 blk = 1024 byte
mov ah,2 ; select read function
int 13h
mov ah,1 ; get diskette status
int 13h
cmp ah,0
je znext1 ; no error
dec word ptr [bp-8] ; decrease the retry time
cmp word ptr [bp-8],0 ; if we can try again
ja znext2
mov al,ah ; get error code
xor ah,ah
add ax,6 ; avoid overlap DOS file I/O error code
push ax
call panic ; we can't move on
znext2:
mov ah,0
int 13h ; do disk controller reset
mov ah,2
jmp zretry ; we have the opportunity to retry
znext1:
mov sp,bp ; obsolet the stack frame
pop bp
pop es
pop ds
ret
getzone endp
org 475
db 'fail to load, error code ',0
org 502
nss dw 0
nsp dw 0
ncs dw 0
nip dw 0
db 0aah
db 055h
cseg ends
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -