第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > 【OS学习笔记】三十七 保护模式十:中断和异常的处理与抢占式多任务对应的汇编代码--

【OS学习笔记】三十七 保护模式十:中断和异常的处理与抢占式多任务对应的汇编代码--

时间:2022-08-24 19:49:13

相关推荐

【OS学习笔记】三十七 保护模式十:中断和异常的处理与抢占式多任务对应的汇编代码--

本文是以下几篇文章对应的主引导扇区代码汇编代码:

【OS学习笔记】三十四 保护模式十:中断和异常区别【OS学习笔记】三十五 保护模式十:中断描述符表、中断门和陷阱门【OS学习笔记】三十六 保护模式十:通过中断发起任务切换----中断任务

;代码清单17-1;文件名:c17_mbr.asm;文件说明:硬盘主引导扇区代码 ;创建日期:-07-13 11:20 ;设置堆栈段和栈指针 core_base_address equ 0x00040000 ;常数,内核加载的起始内存地址 core_start_sector equ 0x00000001 ;常数,内核的起始逻辑扇区号 ;===============================================================================SECTION mbr vstart=0x00007c00 mov ax,csmov ss,axmov sp,0x7c00;计算GDT所在的逻辑段地址mov eax,[cs:pgdt+0x02] ;GDT的32位物理地址 xor edx,edxmov ebx,16div ebx ;分解成16位逻辑地址 mov ds,eax;令DS指向该段以进行操作mov ebx,edx ;段内起始偏移地址 ;跳过0#号描述符的槽位 ;创建1#描述符,保护模式下的代码段描述符mov dword [ebx+0x08],0x0000ffff ;基地址为0,界限0xFFFFF,DPL=00 mov dword [ebx+0x0c],0x00cf9800 ;4KB粒度,代码段描述符,向上扩展 ;创建2#描述符,保护模式下的数据段和堆栈段描述符 mov dword [ebx+0x10],0x0000ffff ;基地址为0,界限0xFFFFF,DPL=00mov dword [ebx+0x14],0x00cf9200 ;4KB粒度,数据段描述符,向上扩展 ;初始化描述符表寄存器GDTRmov word [cs: pgdt],23 ;描述符表的界限 lgdt [cs: pgdt]in al,0x92;南桥芯片内的端口 or al,0000_0010Bout 0x92,al ;打开A20cli ;中断机制尚未工作mov eax,cr0 or eax,1mov cr0,eax ;设置PE位;以下进入保护模式... ...jmp dword 0x0008:flush ;16位的描述符选择子:32位偏移;清流水线并串行化处理器[bits 32]flush: mov eax,0x00010;加载数据段(4GB)选择子mov ds,eaxmov es,eaxmov fs,eaxmov gs,eaxmov ss,eax;加载堆栈段(4GB)选择子mov esp,0x7000 ;堆栈指针;以下加载系统核心程序mov edi,core_base_addressmov eax,core_start_sectormov ebx,edi ;起始地址call read_hard_disk_0 ;以下读取程序的起始部分(一个扇区);以下判断整个程序有多大mov eax,[edi] ;核心程序尺寸xor edx,edxmov ecx,512 ;512字节每扇区div ecxor edx,edxjnz @1 ;未除尽,因此结果比实际扇区数少1dec eax ;已经读了一个扇区,扇区总数减1@1:or eax,eax;考虑实际长度≤512个字节的情况jz pge ;EAX=0 ?;读取剩余的扇区mov ecx,eax ;32位模式下的LOOP使用ECXmov eax,core_start_sectorinc eax ;从下一个逻辑扇区接着读@2:call read_hard_disk_0inc eaxloop @2 ;循环读,直到读完整个内核pge:;准备打开分页机制。从此,再也不用在段之间转来转去,实在晕乎~ ;创建系统内核的页目录表PDTmov ebx,0x00020000 ;页目录表PDT的物理地址;在页目录内创建指向页目录表自己的目录项mov dword [ebx+4092],0x00020003 mov edx,0x00021003 ;MBR空间有限,后面尽量不使用立即数;在页目录内创建与线性地址0x00000000对应的目录项mov [ebx+0x000],edx;写入目录项(页表的物理地址和属性);此目录项仅用于过渡。;在页目录内创建与线性地址0x80000000对应的目录项mov [ebx+0x800],edx;写入目录项(页表的物理地址和属性);创建与上面那个目录项相对应的页表,初始化页表项 mov ebx,0x00021000 ;页表的物理地址xor eax,eax ;起始页的物理地址 xor esi,esi.b1: mov edx,eaxor edx,0x00000003 mov [ebx+esi*4],edx;登记页的物理地址add eax,0x1000 ;下一个相邻页的物理地址 inc esicmp esi,256 ;仅低端1MB内存对应的页才是有效的 jl .b1;令CR3寄存器指向页目录,并正式开启页功能 mov eax,0x00020000 ;PCD=PWT=0mov cr3,eax;将GDT的线性地址映射到从0x80000000开始的相同位置 sgdt [pgdt]mov ebx,[pgdt+2]add dword [pgdt+2],0x80000000;GDTR也用的是线性地址lgdt [pgdt]mov eax,cr0or eax,0x80000000mov cr0,eax ;开启分页机制;将堆栈映射到高端,这是非常容易被忽略的一件事。应当把内核的所有东西;都移到高端,否则,一定会和正在加载的用户任务局部空间里的内容冲突,;而且很难想到问题会出在这里。 add esp,0x80000000 jmp [0x80040004] ;-------------------------------------------------------------------------------read_hard_disk_0: ;从硬盘读取一个逻辑扇区;EAX=逻辑扇区号;DS:EBX=目标缓冲区地址;返回:EBX=EBX+512 push eax push ecxpush edxpush eaxmov dx,0x1f2mov al,1out dx,al;读取的扇区数inc dx ;0x1f3pop eaxout dx,al;LBA地址7~0inc dx ;0x1f4mov cl,8shr eax,clout dx,al;LBA地址15~8inc dx ;0x1f5shr eax,clout dx,al;LBA地址23~16inc dx ;0x1f6shr eax,clor al,0xe0;第一硬盘 LBA地址27~24out dx,alinc dx ;0x1f7mov al,0x20 ;读命令out dx,al.waits:in al,dxand al,0x88cmp al,0x08jnz .waits;不忙,且硬盘已准备好数据传输 mov ecx,256 ;总共要读取的字数mov dx,0x1f0.readw:in ax,dxmov [ebx],axadd ebx,2loop .readwpop edxpop ecxpop eaxret;-------------------------------------------------------------------------------pgdt dw 0dd 0x00008000;GDT的物理/线性地址;------------------------------------------------------------------------------- times 510-($-$$) db 0db 0x55,0xaa

【OS学习笔记】三十七 保护模式十:中断和异常的处理与抢占式多任务对应的汇编代码----主引导扇区代码

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。