编写mbr.S汇编代码
;LOADER_BASE_ADDR equ 0x900
;LOADER_START_SECTOR equ 0x2
%include "boot.inc"SECTION MBR vstart=0x7c00mov ax,csmov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00mov ax,0xb800mov gs,axmov ax,0x0600mov bx,0x0700mov cx,0mov dx, 184fhint 10hmov byte [gs:0x00], '1'mov byte [gs:0x01], 0xA4mov byte [gs:0x02], ' 'mov byte [gs:0x03], 0xA4mov byte [gs:0x04], 'M'mov byte [gs:0x05], 0xA4mov byte [gs:0x06], 'B'mov byte [gs:0x07], 0xA4mov byte [gs:0x08], 'R'mov byte [gs:0x09], 0xA4mov eax,LOADER_START_SECTORmov bx, LOADER_BASE_ADDRmov cx,4 ; 读取的扇区数,读取4个扇区call rd_disk_m_16jmp LOADER_BASE_ADDR + 0x300rd_disk_m_16:mov esi,eaxmov di,cxmov dx,0x1f2mov al,clout dx,almov eax,esimov dx,0x1f3out dx,almov cl,8shr eax,clmov dx,0x1f4out dx,alshr eax,clmov dx,0x1f5out dx,alshr eax,cland al,0x0for al,0xe0mov dx,0x1f6out dx,almov dx,0x1f7mov al,0x20out dx,al.not_ready:nopin al,dxand al,0x88cmp al,0x08jnz .not_readymov ax,dimov dx,256mul dxmov cx,axmov dx,0x1f0
.go_on_ready:in ax,dxmov [bx],axadd bx,2loop .go_on_readyrettimes 510-($-$$) db 0db 0x55,0xaa
编写loader.S汇编代码
;LOADER_BASE_ADDR equ 0x900
;LOADER_START_SECTOR equ 0x2
%include "boot.inc"SECTION LOADER vstart=LOADER_BASE_ADDRLOADER_STACK_TOP equ LOADER_BASE_ADDRGDT_BASE: dd 0x00000000dd 0x00000000CODE_DESC: dd 0x0000FFFFdd DESC_CODE_HIGH4DATA_STACK_DESC: dd 0x0000FFFFdd DESC_DATA_HIGH4VIDEO_DESC: dd 0x80000007dd DESC_VIDEO_HIGH4GDT_SIZE equ $-GDT_BASEGDT_LIMIT equ GDT_SIZE-1times 60 dq 0SELECTOR_CODE equ (0x0001 << 3) + TI_GDT + RPL0SELECTOR_DATA equ (0x0002 << 3) + TI_GDT + RPL0SELECTOR_VIDEO equ (0x0003 << 3) + TI_GDT + RPL0;用于保存内存容量,以字节为单位,此位置好记; 0x900 + 32 + 480 = 0xb00total_mem_bytes dd 0gdt_ptr dw GDT_LIMITdd GDT_BASE; 人工对齐ards_buf times 244 db 0ards_nr dw 0loader_start:
;------- int 15h eax = 0000E820h ,edx = 534D4150h ('SMAP') 获取内存布局 -------xor ebx,ebxmov edx,0x534d4150mov di,ards_buf
.e820_mem_get_loop:mov eax, 0x0000e820mov ecx,20int 0x15jc .e820_failed_so_try_e801add di,cxinc word[ards_nr]cmp ebx,0jnz .e820_mem_get_loopmov cx,[ards_nr]mov ebx,ards_bufxor edx,edx.find_max_mem_area:mov eax,[ebx]add eax,[ebx+8]add ebx,20cmp edx,eaxjge .next_ardsmov edx,eax.next_ards:loop .find_max_mem_areajmp .mem_get_ok;------ int 15h ax = E801h 获取内存大小,最大支持4G ------.e820_failed_so_try_e801:mov ax,0xe801int 0x15jc .e801_failed_so_try88; 先算出低15M的内存mov cx,0x400mul cxshl edx,16 ; 左移16位and eax,0x0000FFFFor edx,eaxadd edx,0x100000mov esi,edx; 再将16M以上的内存xor eax,eaxmov ax,bxmov ecx,0x10000mul ecxadd esi,eaxmov edx,esijmp .mem_get_ok ;----------------- int 15h ah = 0x88 获取内存大小,只能获取64M之内 ----------
.e801_failed_so_try88:mov ah,0x88int 0x15jc .error_hltand eax,0x0000FFFFmov cx,0x400mul cx,shl edx,16or edx,eaxadd edx,0x100000 .mem_get_ok:mov [total_mem_bytes], edx;----------------- 准备进入保护模式 -------------------
;1 打开A20
;2 加载gdt
;3 将cr0的pe位置1;准备进入保护模式in al,0x92or al,0000_0010bout 0x92,allgdt [gdt_ptr]mov eax,cr0or eax,0x00000001mov cr0,eaxjmp dword SELECTOR_CODE:p_mode_start.error_hlt: ;出错则挂起hlt[bits 32]p_mode_start:mov ax,SELECTOR_DATAmov ds,axmov es,axmov ss,axmov esp,LOADER_STACK_TOPmov ax,SELECTOR_VIDEOmov gs,axmov byte[gs:160],'p'jmp $
宏文件boot.inc和读书笔记七中一致。
编译代码
nasm -I include/ -o mbr.bin mbr.S
nasm -I include/ -o loader.bin loader.Sdd if=/home/truthos/oscode/c5/a/boot/mbr.bin of=/home/truthos/bochs/hd60M.img bs=512 count=1 conv=notruncdd if=/home/truthos/oscode/c5/a/boot/loader.bin of=/home/truthos/bochs/hd60M.img count=4 seek=2 conv=notrunc
xp 0xb00 查看物理内存0xb00出的内容
程序正常运行