LBA_ADDR equ 250
section bootload align=16 vstart=0x7c00
start:
mov ax, 0
mov ss, ax
mov sp, ax
mov ax, [cs:phy_addr]
mov dx, [cs:phy_addr + 2]
mov bx, 16
div bx
mov ds, ax
mov es, ax
push 0xe0
push 0
push 0
push LBA_ADDR
push 0x01
xor bx, bx
call _readHd
;jmp showTest ;本句话可以测试是否先从硬盘的250扇区开始的用户读到内存地址0x10000
;接下来准备设置地址0x10000后面用户程序的各种段的地址
;用户程序长度
mov bx, 0
mov ax, [ds:bx]
mov dx, [ds:bx+2]
;填充开始执行的地址即0x04的两个字节
;计算原来的地址
;code段地址
;mov ax, 4098
;mov [ds:0x06], ax
;mov ax, 4098
;mov [ds:0x0c], ax
;mov ax, 4101
;mov [ds:0x10], ax
;jmp far [0x04]
;计算入口点代码段基址
direct:
mov dx,[0x08]
mov ax,[0x06]
call _calc_segment_base
mov [0x06],ax ;回填修正后的入口点代码段基址
;开始处理段重定位表
mov cx,[0x0a] ;需要重定位的项目数量
mov bx,0x0c ;重定位表首地址
realloc:
mov dx,[bx+0x02] ;32位地址的高16位
mov ax,[bx]
call _calc_segment_base
mov [bx],ax ;回填段的基址
add bx,4 ;下一个重定位项(每项占4个字节)
loop realloc
;jmp far [0x04]
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;用于测试,测试加载到内存0x10000开始后用户程序地址
mov ax, 0xb800
mov es, ax
mov ax,[cs:number]
;计算各个数位
mov bx,ax
mov cx,5 ;循环次数
mov si,10 ;除数
mov ax, [ds:0x12]
digit:
xor dx,dx
div si
mov [bx],dl ;保存数位
inc bx
loop digit
;显示各个数位
mov bx,[cs:number]
mov si,4
xor di, di
show:
mov al,[bx+si]
add al,0x30
mov ah,0x04
mov [es:di],ax
add di,2
dec si
jns show
mov word [es:di],0x0744
jmp near $
;-------------------------------------------------------------------------------
_calc_segment_base: ;计算16位段地址 ;输入:DX:AX=32位物理地址 ;返回:AX=16位段基地址
push dx
add ax,[cs:phy_addr]
adc dx,[cs:phy_addr + 0x02]
shr ax,4
ror dx,4
and dx,0xf000
or ax,dx
pop dx
ret
;@showTest:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;mov cx, 512
;xor si, si
;xor di, di
;mov ax, 0xb800
;mov es, ax
;@showStr:
; mov al, [ds:si]
; mov [es:di], al
; inc si
; inc di
; mov byte [es:di], 0x07
; inc di
; loop @showStr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
_readHd:
push bp
mov bp, sp
mov dx, 0x1f2
mov al, [bp+4]
out dx, al
mov dx, 0x1f3
mov al, [bp+6]
out dx, al
mov dx, 0x1f4
mov al, [bp+8]
out dx, al
mov dx, 0x1f5
mov al, [bp+10]
out dx, al
mov dx, 0x1f6
mov al, [bp+12]
out dx, al
mov dx, 0x1f7
mov al, 0x20
out dx, al
@wait:
in al, dx
and al, 0x88
cmp al, 0x08
jnz @wait
mov cx, 512
mov dx, 0x1f0
@readHd:
in al, dx
mov [bx], al
inc bx
loop @readHd
pop bp
ret
phy_addr dd 0x10000
number db 0,0,0,0,0,0,0
times 510 - ($ - $$) db 0
dw 0xaa55
section header align=16 vstart=0
prog_length dd prog_end ;0x00
code_entry dw start ;0x04
dd section.code.start ;0x06
table_size dw (header_end - codeSegAddr)/4 ;0x0a
codeSegAddr dd section.code.start ;0x0c
dataSegAddr dd section.data.start ;0x10
header_end:
;用户程序
section code align=16 vstart=0
start:
mov ax, [dataSegAddr]
mov ds, ax
mov ax, 0xb800
mov es, ax
mov si, 0
mov di, 0
mov bx, szInfor
mov cx, data_end - szInfor
@ShowStr:
mov al, [ds:si+bx]
mov [es:di], al
inc si
inc di
mov byte [es:di], 0x07
inc di
loop @ShowStr
@Hlt:
hlt
jmp @Hlt
section data align=16 vstart=0
szInfor db "Now we are in user space Fuck!"
data_end:
section trail align=16
prog_end:
汇编引导区和测试
最新推荐文章于 2024-11-27 02:57:59 发布