- [035][x86汇编语言]第十四章 √√文件的OO的XX特权级
- x86 reading Note(2):Task Switch
- [013][x86汇编语言]从硬盘主引导扇区启动,显示hello
- [033][x86汇编语言]第十四章 子程序load_reloc
- [034][x86汇编语言]第十四章 内核程序c14_core.
- [036][x86汇编语言]第十四章 本章习题解答
- [049][x86汇编语言]控制转移到其他任务 jmp/call
- [060][x86汇编语言]第16章内核程序执行逻辑:load_
- [061][x86汇编语言]第16章 源码分析 过程[alloc
- [038][x86汇编语言]第十五章 中断描述符表 任务门描述符
学习笔记
《x86汇编语言:从实模式到保护模式》
https://www.jianshu.com/p/d481cb547e9f
代码参考
- 配书代码
c11_mbr.asm
运行结果
第11章 程序运行结果.png参考图例
图11-3 进入保护模式前的内存映象.png
《x86汇编语言:从实模式到保护模式》 第187页
完整源码(增加注释)
;代码清单11-1
;文件名:code_11.asm
;文件说明: 硬盘主引导扇区代码
;创建日期: 16:52 2018/5/29
;设置堆栈段和栈指针
mov ax,cs
mov ss,ax
mov sp,0x7c00
;计算GDT所在的逻辑段地址
mov ax,[cs:gdt_base+0x7c00] ;低16位
mov dx,[cs:gdt_base+0x7c00+0x02] ;高16位
mov bx,16
div bx
mov ds,ax ;令DS指向该段以进行操作
mov bx,dx ;段内起始偏移地址0x0000
;创建0#描述符,它是空描述符,这是处理器的要求
mov dword [bx+0x00],0x00
mov dword [bx+0x04],0x00
;创建1#描述符,保护模式下的代码段描述符
; 段基地址0x00007C00
; 段界限0x001ff (段的长度=段界限+1=0x0200=512kb)
; G=0 粒度为字节
; S=1 这是代码段
; D=1 这是32位段
; DPL=00 段的特权级是0
; P=1 该段目前在内存中
; TYPE=1000 只执行
mov dword [bx+0x08],0x7c0001ff
mov dword [bx+0x0c],0x00409800
;创建2#描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区)
; 段基地址0x000b8000
; 段界限0x0ffff
; G=0 粒度为字节
; S=1 这是数据段
; D=1 这是32位段
; DPL=00 段的特权级是0
; P=1 该段目前在内存中
; TYPE=0010 这是一个可读可写,向上扩展的数据段
mov dword [bx+0x10],0x8000ffff
mov dword [bx+0x14],0x0040920b
;创建3#描述符,保护模式下的堆栈段描述符
;段基地址0x00000000
;段界限07a00
;G=0 粒度为字节
;S=1 栈段
;D=1 这是32位段
;DPL=00 段的特权级是0
;P=1 该段目前在内存中
;TYPE=0110 这是一个可读可写、向下扩展的栈段
mov dword [bx+0x18],0x00007a00
mov dword [bx+0x1C],0x00409600
;初始化描述符表寄存器GDTR
;4*8-1=31
;4个描述符:空白段描述符、代码段描述符、数据段描述符、栈段描述符
;每个描述符占8个字节
mov word [cs:gdt_size+0x7c00],31 ;描述符表的界限(总字节数减一)
lgdt [cs:gdt_size+0x7c00]
in al,0x92 ;南桥芯片内的端口
or al,0000_0010B
out 0x92,al ;打开A20:第21根地址线
cli ;保护模式下中断机制尚未建立,应该禁止中断
mov eax,cr0
or eax,1
mov cr0,eax ;设置PE位,置为1,进入保护模式
;以下进入保护模式... ...
jmp dword 0x0008:flush ;16位的描述符选择子 : 32位偏移
;dword修饰的是偏移地址
;清空流水线
;串行化处理器,让指令重新按自然顺序执行
[bits 32]
flush:
mov cx,00000000000_10_000B ;加载选择子(0x10)
mov ds,cx
;以下在屏幕上显示“Protect mode OK."
mov byte [0x00],'P'
mov byte [0x02],'r'
mov byte [0x04],'o'
mov byte [0x06],'t'
mov byte [0x08],'e'
mov byte [0x0a],'c'
mov byte [0x0c],'t'
mov byte [0x0e],' '
mov byte [0x10],'m'
mov byte [0x12],'o'
mov byte [0x14],'d'
mov byte [0x16],'e'
mov byte [0x18],' '
mov byte [0x1a],'O'
mov byte [0x1c],'K'
mov byte [0x1e],'.'
ghalt:
hlt ;已经禁止中断,将不会被唤醒
;-------------------------------------------------------
gdt_size dw 0
gdt_base dd 0x00007e00 ;GDT的物理地址
times 510-($-$$) db 0
db 0x55,0xaa
代码说明
加载段选择子0x0008 索引号是1.png-
jmp dword 0x0008:flush
,这条指令,用bits16编译,在16位模式下译码,按照32位执行;
段选择子0x0008
展开成二进制是
0000-0000-0000-1000
再按照段选择子的格式来分
0000-0000-00001-0-00
这一部分 0000-0000-00001 就是索引号
这样就是用13位来表示索引号
为什么是13位?
因为GDT最大是64kb
64kb=2^16Byte
单个描述符占用8个字节,也就是占用2^3个字节
(2^16)/(2^3)=2^13 即索引号个数。
- 处理器遇到
jmp或者call 指令
,一般会清空流水线,并串行化执行(让指令重新按照自然顺序执行); - ESP寄存器要满足
ESP>段界限*粒度
网友评论