赞
踩
BIOS中断0x15的3个子功能:BIOS中断是实模式下的用法,不能在保护模式下使用。若全部失败了就只好让机器挂起了。运行成功再启动保护模式。
返回地址消息,通过地址范围描述符
Type字段的含义:
BIOS中断0x15中的0xe820子功能需要的参数。
因为是在32位下工作,所以只用到BaseAddrLow+lengthLow是一片内存区域上限。
操作步骤
最大只能识别4GB,对于32位也算可以了。
即使内存容量大于64MB,也只会显示63MB。因为此中断只会显示1MB之上的内存,所以记得手动加上1MB。
更改的内容:将第44行jmp到load的代码改为:
jmp LOADER_BASE_ADDR+0x300
%include "boot.inc" section mbr vstart=0x7c00 mov ax,cs mov ds,ax mov es,ax mov ss,ax mov fs,ax mov sp,0x7c00 mov ax,0xb800 mov gs,ax ;清屏 mov ax,0600h mov bx,0700h mov cx,0 mov dx,184fh int 10h ;输出字符串:MBR mov byte[gs:0x00],'1' mov byte[gs:0x01],0xA4 mov byte[gs:0x02],' ' mov byte[gs:0x03],0xA4 mov byte[gs:0x04],'M' mov byte[gs:0x05],0xA4 mov byte[gs:0x06],'B' mov byte[gs:0x07],0xA4 mov byte[gs:0x08],'R' mov byte[gs:0x09],0xa4 mov eax,LOADER_START_SECTOR ;其实栓去lba地址 mov bx ,LOADER_BASE_ADDR ;写入的地址 mov cx ,4 ;这里的cx就是读取扇区数 call rd_disk_m_16 mov byte[gs:160],'r' mov byte[gs:162],'d' jmp LOADER_BASE_ADDR+0x300 ;===读取硬盘n个扇区=== rd_disk_m_16: mov esi, eax mov di,cx ;第一步,读取扇区 mov dx,0x1f2 mov al,cl out dx,al mov eax,esi ;第二步,将LBA地址存入0x1f3~0x1f6 ;lba地址7~0写入端口0x1f3 mov dx,0x1f3 out dx,al ;lba地址15-8写入端口0x1f4 mov cl,8 shr eax,cl mov dx,0x1f4 out dx,al ;lba地址32~16写入端口0x1f5 shr eax,cl mov dx,0x1f5 out dx,al ;lba14~27 shr eax,cl and al,0x0f or al,0xe0 ;设置7-4位1110,表示lba模式。 mov dx,0x1f6 out dx,al ;第3步:向0x1f7端口写入命令,0x20 mov dx,0x1f7 mov al,0x20 out dx,al ;第4步:检测硬盘状态 .not_ready: nop in al,dx and al,0x88 cmp al,0x08 jnz .not_ready ;第5步:从0x1f0端口读数据 mov ax,di mov dx,256 mul dx mov cx,ax ;di为要读取的扇区数,一个扇区512字节,每读取一个字;共需要di*512/2次,所以是256 mov dx,0x1f0 .go_on_read: in ax,dx mov [bx],ax add bx,2 loop .go_on_read ret times 510-($-$$) db 0 db 0x55,0xaa
让调整数据结构为了让total_mem_bytes在0xb00位置上。
%include "boot.inc" section loader vstart=LOADER_BASE_ADDR ;------------------------------ ;构建gdt及其内部的描述符 GDT_BASE: dd 0x00000000 dd 0x00000000 CODE_DESC: dd 0x0000FFFF dd DESC_CODE_HIGH4 DATA_STACK_DESK: dd 0x0000FFFF dd DESC_DATA_HIGH4 VIDEO_DESC: dd 0x80000007 ;limit=(0xbffff-0xb8000)/4k=0x7 dd DESC_VIDEO_HIGH4 ;此时dp1为0 GDT_SIZE equ $-GDT_BASE GDT_LIMIT equ GDT_SIZE-1 times 60 dq 0 SELECTOR_CODE equ (0x0001<<3)+TI_GDT+RPL0 SELECTOR_DATA equ (0x0002<<3)+TI_GDT+RPL0 SELECTOR_VIDEO equ (0x0003<<3)+TI_GDT+RPL0 total_mem_bytes dd 0;存放内存大小 gdt_ptr dw GDT_LIMIT dd GDT_BASE ;------- 记录 ARDS结构体数 ---------- ards_buf times 244 db 0 ards_nr dw 0 ;------------------------------ mov byte[gs:480],'G' mov byte[gs:482],'D' mov byte[gs:484],'T' loader_start: ;打印字符串 mov byte[gs:640],'L' mov byte[gs:642],'O' mov byte[gs:644],'A' mov byte[gs:646],'D' mov byte[gs:648],'E' mov byte[gs:650],'R' mov byte[gs:652],'_' mov byte[gs:654],'S' mov byte[gs:656],'T' mov byte[gs:658],'A' mov byte[gs:660],'R' mov byte[gs:662],'T' ; mov sp,LOADER_BASE_ADDR ; mov bp,loadermsg ; mov cx,17 ; mov ax,0x1301 ; mov bx,0x001f ; mov dx,0x1800 ; int 0x10 ;--- 获取内存布局 --- xor ebx, ebx mov edx, 0x534d4150 mov di, ards_buf .e820_mem_get_loop: mov eax, 0x0000e820 mov ecx,20 int 0x15 jc .e820_failed_so_try_e801 add di,cx inc word [ards_nr] cmp ebx, 0 jnz .e820_mem_get_loop mov cx, [ards_nr] mov ebx, ards_buf xor edx,edx .find_max_mem_area: mov eax,[ebx] add eax,[ebx+8] add ebx, 20 cmp edx,eax jge .next_ards mov edx,eax .next_ards: loop .find_max_mem_area jmp .mem_get_ok ;------ int 15h ax=E801和------ .e820_failed_so_try_e801: mov ax,0xe801 int 0x15 jc .e801_failed_so_try88 mov cx,0x400 mul cx shl edx,16 and eax,0x0000FFFF or edx,eax add edx, 0x100000 mov esi,edx xor eax,eax mov ax,bx mov ecx,0x10000 mul ecx add esi,eax mov edx,esi jmp .mem_get_ok ;------ int 15h ah=0x88 ------ .e801_failed_so_try88: mov ah,0x88 int 0x15 jc .error_hlt and eax,0x0000FFFF mov cx,0x400 mul cx shl edx,16 or edx,eax add edx,0x100000 .mem_get_ok: mov [total_mem_bytes],edx ;---准备进入保护模式--- ;---打开A20--- in al,0x92 or al,0000_0010B out 0x92,al ;---加载GDT--- lgdt [gdt_ptr] ;---cr0第0个位置1 mov eax,cr0 or eax,0x00000001 mov cr0,eax jmp dword SELECTOR_CODE:p_mode_start ;刷新流水线 .error_hlt hlt [bits 32] p_mode_start: mov ax,SELECTOR_DATA mov ds,ax mov es,ax mov ss,ax mov esp,LOADER_STACK_TOP mov ax,SELECTOR_VIDEO mov gs,ax mov byte [gs:800], 'P' jmp $
按照书中的调试方法进行调试。
得到结果:
更新:
loader.asm
%include "boot.inc" section loader vstart=LOADER_BASE_ADDR LOADER_STACK_TOP equ LOADER_BASE_ADDR ;jmp loader_start GDT_BASE: dd 0x00000000 dd 0x00000000 CODE_DESC: dd 0x0000FFFF dd DESC_CODE_HIGH4 DATA_STACK_DESC: dd 0x0000FFFF dd DESC_DATA_HIGH4 VIDEO_DESC: dd 0x80000007 dd DESC_VIDEO_HIGH4 GDT_SIZE equ $-GDT_BASE GDT_LIMIT equ GDT_SIZE-1 times 60 dq 0 ;预留60个描述符的位子 ;选择子 SELECTOR_CODE equ (0x0001<<3) + TI_GDT + RPL0 SELECTOR_DATA equ (0x0002<<3) + TI_GDT + RPL0 SELECTOR_VIDEO equ (0x0003<<3) + TI_GDT + RPL0 total_mem_bytes dd 0 ;4 保存内存容量 ;gdt指针 gdt_ptr dw GDT_LIMIT ;6 dd GDT_BASE ards_buf times 244 db 0 ;244 ards结构体缓存 ards_nr dw 0 ;2 ards结构体数量,一共 4+6+244+2 = 256字节 loader_start: ;==== 读取内存数 ;int 15h eax,ebx,es:di,ecx,edx xor ebx,ebx ;ARDS后续值,第一次为0 mov edx,0x534d4150 ;固定为签名标记 mov di,ards_buf ;ards结构缓冲区 .e820_mem_get_loop: mov eax,0x0000e820 mov ecx,20 ;ards 地址范围描述符结构是20字节 int 0x15 jc .e820_failed_so_try_e801 ;若cf为1,则发生错误,常识0xe801 add di,cx ;cx是读到的结构缓冲区中数据的字节数 inc word [ards_nr] cmp ebx,0 ;如果是0说明这是最后一个ARDS结构 jnz .e820_mem_get_loop ;找出(base_add_low + length_low)的最大值,也就是内存容量 mov cx,[ards_nr] mov ebx,ards_buf xor edx,edx .find_max_mem_area: mov eax,[ebx] add eax,[ebx+8] add ebx,20 ;ebx存放 ARDS缓存内容地址 cmp edx,eax ;比较 edx 与 eax大小 jge .next_ards mov edx,eax .next_ards: loop .find_max_mem_area jmp .mem_get_ok ;0x15 0xe801 .e820_failed_so_try_e801: mov ax,0xe801 int 0x15 jc .e801_failed_so_try88 ;1 先算出低15MB的内存 mov cx,0x400;ax KB单位2^10 ,0x400-> 1024 mul cx shl edx,16 and eax,0x0000FFFF or edx,eax add edx, 0x100000 ;补上1MB mov esi,edx ;先放在esi中 ;2 算>16MB的内存 bx 64KB为单位 xor eax,eax mov ax,bx mov ecx,0x10000 ;将64KB单位转为byte mul ecx add esi,eax ;<=15 + >16 jmp .mem_get_ok .e801_failed_so_try88: mov ah,0x88 int 0x15 jc .error_hlt and eax,0x0000FFFF ;ax*1024+1MB mov cx,0x400 mul cx ;ax*1024->dx,ax shl edx,16 or edx,eax add edx,0x100000 ;+1MB .mem_get_ok: mov [total_mem_bytes],edx .error_hlt: mov byte [gs:160],'2' mov byte [gs:162],' ' mov byte [gs:164],'0' mov byte [gs:166],'x' mov byte [gs:168],'1' mov byte [gs:170],'5' ;==== ;1 打开 A20 in al,0x92 or al,0x02 out 0x92,al ;2 加载 GDT lgdt [gdt_ptr] ;3 cr0 pe置1 mov eax,cr0 or eax,0x01 mov cr0,eax jmp dword SELECTOR_CODE:p_mode_start [bits 32] p_mode_start: mov ax,SELECTOR_DATA mov ds,ax mov es,ax mov ss,ax mov esp,LOADER_STACK_TOP mov ax,SELECTOR_VIDEO mov gs,ax mov byte [gs:320],'3' mov byte [gs:322],' ' mov byte [gs:324],'P' mov byte [gs:326],'r' mov byte [gs:328],'o' mov byte [gs:330],'t' mov byte [gs:332],'e' mov byte [gs:334],'c' mov byte [gs:336],'t' mov byte [gs:338],'i' mov byte [gs:340],'o' mov byte [gs:342],'n' mov byte [gs:344],' ' mov byte [gs:346],'m' mov byte [gs:348],'o' mov byte [gs:350],'d' mov byte [gs:352],'e' mov byte [gs:354],'.' jmp $
mbr.asm
%include "boot.inc" section MBR vstart=0x7c00 mov ax,cs mov ds,ax mov es,ax mov ss,ax mov fs,ax mov sp,0x7c00 mov ax,0xb800 mov gs,ax ;使用 int 0x10 功能号 0x06 清屏 mov ah,0x06 mov al,0x00 ;上卷行数 0->全部 mov bl,0x00 mov bh,0x07 mov cx,0x0000 ;左上( 0, 0) mov dx,0x184f ;右下(80,25) int 0x10 ; ---------- 在显存中输入信息 --------- ; 输出背景为 黄 色,前景 红 色,并且跳动的字符串 "HELLO WORLD" mov bx,0 mov cx,14 mov si,0 print: mov al,[s+si] mov [gs:bx],al inc bx mov byte [gs:bx],0x24 inc bx add si,1 loop print mov eax, LOADER_START_SECTOR mov bx, LOADER_BASE_ADDR mov cx, 4 call rd_disk_m_16 jmp LOADER_BASE_ADDR+0x300 rd_disk_m_16: mov esi,eax mov di,cx ;指定扇区数0x1f2 8bit mov dx,0x1f2 mov al,cl out dx,al mov eax,esi ;LBA 0-7 8bit mov dx,0x1f3 out dx,al ;LBA 8-15 8bit mov cl,8 shr eax,cl mov dx,0x1f4 out dx,al ;LBA 16-23 shr eax,cl mov dx,0x1f5 out dx,al ;LBA Device | 24-27 shr eax,cl and al,0000_1111b or al,1110_0000b ;LBA, DEV主盘 mov dx,0x1f6 out dx,al ;写入命令 mov dx,0x1f7 mov al,0x20 out dx,al ;检测硬盘状态 .not_ready: nop ;相当于个停顿 in al,dx and al,1000_1000b ;忙/准备好 cmp al,0000_1000b jnz .not_ready ;读数据 mov ax,di mov dx,256 ;512/2 mul dx mov cx,ax ;一共ax个字节 mov dx,0x1f0 .read_data: in ax,dx mov [bx],ax add bx,2 loop .read_data ret s db "1 MBR_start!!!" times 510 - ($-$$) db 0 db 0x55, 0xaa
运行结果:
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。