计算机通电启动时,第一件事时需要找到BIOS的入口地址,首先cpu 的 cs:ip 寄存器被强制初始化为 0xF000:0xFFF0,由实模式下寻址可知,BIOS的入口地址即为0xFFFF0,而这个地址并不是BIOS的起始代码而是一个长跳转指令 jmp far f000:e05b,如下图:
而f000:e05b处才是真正的BIOS起始代码,然后接下来 BIOS 便马不停蹄地检测内存、显卡等外设信息,当检测通过,并初始化好硬件后,开始在内存中 0x000~0x3FF 处建立数据结构,中断向量表 IVT 并填写中断例程。BIOS工作完后会将0盘0道1扇区的硬盘内容加载到以 0x7c00开头的内存区域,即加载MBR程序。之后MBR会加载loader内核加载程序代码。loader内核加载器会实现由实模式向保护模式的转换。值得注意的是BIOS是自动加载MBR到内存0x7c00处,而MBR是通过操作磁盘将扇区里loader加载到内存里的。实模式下具体磁盘操作函数如下:
;功能:读取硬盘n个扇区 rd_disk_m_16: ;------------------------------------------------------------------------------- ; eax=LBA扇区号 ; ebx=将数据写入的内存地址 ; ecx=读入的扇区数 mov esi,eax ;备份eax mov di,cx ;备份cx ;读写硬盘: ;第1步:设置要读取的扇区数 mov dx,0x1f2 mov al,cl out dx,al ;读取的扇区数 mov eax,esi ;恢复ax ;第2步:将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地址23~16位写入端口0x1f5 shr eax,cl mov dx,0x1f5 out dx,al shr eax,cl and al,0x0f ;lba第24~27位 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 ;第4位为1表示硬盘控制器已准备好数据传输,第7位为1表示硬盘忙 cmp al,0x08 jnz .not_ready ;若未准备好,继续等。 ;第5步:从0x1f0端口读数据 mov ax, di mov dx, 256 mul dx mov cx, ax ; di为要读取的扇区数,一个扇区有512字节,每次读入一个字, ; 共需di*512/2次,所以di*256 mov dx, 0x1f0 .go_on_read: in ax,dx mov [bx],ax add bx,2 loop .go_on_read ret
原文地址:https://www.cnblogs.com/HonkerYblogs/p/10385485.html
时间: 2024-11-06 17:25:05