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: