学习操作系统:进入保护模式,理解GDT(1):TEXT
直接上代码,以及追加了自己对GDT的理解,为了理解GDT,翻遍了各种文章,但没有代码的支撑,凭空的理解很浪费时间。
下面的代码,稍微简化了原先的代码(于老师的代码^^)。把pm.asm需要的代码从pm.inc挪出来,取消了pm.inc的引入。
; ==========================================
; 32mode_TEXT.asm
; 编译方法:nasm 32mode_TEXT.asm -o 32mode_TEXT.bin
; ==========================================;=========================宏定义: GDT的定义 开始=====================================
;
; 描述符 类型 入参1(%1), 入参2(%2), 入参3(%3)
; usage: Descriptor Base, Limit, Attr
; Base: dd
; Limit: dd (low 20 bits available)
; Attr: dw (lower 4 bits of higher byte are always 0)
%macro Descriptor 3dw %2 & 0FFFFh ; 段界限1(双字节:字节1~字节2)dw %1 & 0FFFFh ; 段基址1(双字节:字节3~字节4)db (%1 >> 16) & 0FFh ; 段基址2(单字节:字节5)dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性1 + 段界限2 + 属性2(双字节:字节6~字节7)db (%1 >> 24) & 0FFh ; 段基址3(单字节:字节8)
%endmacro ; 共 8 字节
;
; 门 类型 入参1, 入参2, 入参3, 入参4
; usage: Gate Selector, Offset, DCount, Attr
; Selector: dw
; Offset: dd
; DCount: db
; Attr: db
%macro Gate 4 ; 4为参数个数dw (%2 & 0FFFFh) ; 偏移1 (双字节)dw %1 ; 选择子(双字节)dw (%3 & 1Fh) | ((%4 << 8) & 0FF00h) ; 属性 (双字节)dw ((%2 >> 16) & 0FFFFh) ; 偏移2 (双字节)
%endmacro ; 共 8 字节
;=========================GDT的定义 结束=====================================
org 07c00hjmp LABEL_BEGIN[SECTION .gdt]
; GDT
; Descriptor在pm.inc中定义,三个入参
; LABEL_GDT为(0#)描述符,创建0#描述符,它是空描述符,这是处理器的要求
; 段基址, 段界限 , 属性
LABEL_GDT: Descriptor 0, 0, 0 ; 空描述符
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, 98h + 4000h; 非一致代码段
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, 92h ; Text显存首地址:0B8000h,VGA显存首地址:0x000a0000
; GDT 结束GdtLen equ $ - LABEL_GDT ; GDT长度
GdtPtr dw GdtLen - 1 ; GDT界限dd 0 ; GDT基地址; GDT 选择子
; LABEL_GDT的地址为GDT表起始地址
; 后面的GDT的地址,都是以LABEL_GDT的地址为起始地址,计算自己的地址
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
; END of [SECTION .gdt][SECTION .s16]
[BITS 16]
LABEL_BEGIN:mov ax, csmov ds, axmov es, axmov ss, axmov sp, 0100h; 初始化 32 位代码段描述符; xor eax,eax和mov eax,0一样,由于它比mov eax,0效率高,所以一般用它!; 两者的作用没有区别,都是让eax的值为0,但是xor eax,eax 指令为2字节,mov eax,0 指令为5个字节。相比而言,前面指令更能节省空间。; 这个虽然结果是一样的,都是变成0,但是xor会影响到状态标志位,使cf of 变成0。xor eax, eaxmov ax, csshl eax, 4 ; shl:逻辑左移指令 shr:逻辑右移指令add eax, LABEL_SEG_CODE32mov word [LABEL_DESC_CODE32 + 2], axshr eax, 16mov byte [LABEL_DESC_CODE32 + 4], almov byte [LABEL_DESC_CODE32 + 7], ah; 为加载 GDTR 作准备xor eax, eax; “XOR EAX,EAX”语句已经将EAX清零了。mov ax, ds ; 然后“MOV AX,DS”将16位的段值从DS复制到AX。shl eax, 4 ; “SHL EAX,4”是计算数据段的起始物理地址,; 所以用了EAX来表示20位的物理地址(没有使用AX表示物理地址是因为AX只有16位)。 ; (注:实模式下的寻址的方式固然还是段:偏移,而且段:偏移还都是16位,; 但在实模式下却可以使用32位寄存器,如EAX……等,; 而这里的EAX既不是段值,也不是偏移,而是人工计算出的物理地址,; 相当于用EAX保存的数据,; 最后再通过“MOV DWORD[GdtPtr+2],EAX”将EAX中的物理地址送到DS:(OFFSET GdtPtr)+2表示的逻辑地址处。)add eax, LABEL_GDT ; eax <- gdt 基地址mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址; 加载 GDTRlgdt [GdtPtr]; 关中断cli; 打开地址线A20; 打开A20的其他方法:https://blog.csdn.net/longintchar/article/details/79365928; 下面写法是其中之一in al, 92h ;南桥芯片内的端口 or al, 00000010bout 92h, al; 准备切换到保护模式--除了cr0还有其他控制寄存器(CR0,CR1,CR2,CR3,CR4)mov eax, cr0; cr0是80386CPU中的控制寄存器or eax, 1 ; 第0位,即PE位,用来控制是否进入保护模式(是/否:1/0)mov cr0, eax; 设置PE位; 真正进入保护模式jmp dword SelectorCode32:0 ; 执行这一句会把 SelectorCode32 装入 cs,; 并跳转到 SelectorCode32:0 处; 【jmp dword SelectorCode32:0】的理解; http://tieba.baidu.com/p/4302738682; SelectorCode32:0的意思就是第二个描述符的第0行代码开始,这里的0是不是可以换成32位模式下的任何函数?
; END of [SECTION .s16][SECTION .s32]; 32 位代码段. 由实模式跳入.
[BITS 32]LABEL_SEG_CODE32:mov ax, SelectorVideomov gs, ax ; 视频段选择子(目的)mov ecx, 28 ; .show的循环次数mov edi, 0mov bx, BootMessage
.show:mov ah, 0Ch ; 0000: 黑底 1100: 红字mov al, [bx]mov [gs:edi], axinc ediinc ediinc bxloop .show; 到此停止jmp $BootMessage: db "Hello CPU, I'm in protected mode!"
SegCode32Len equ $ - LABEL_SEG_CODE32
; END of [SECTION .s32]
用GDB查看GDT的内容(64位GCC在Windows下模拟)
GDT和段的关系
代码:
mov ax, SelectorVideo ; SelectorVideo 为LABEL_DESC_CODE32的选择子
mov gs, ax ; gs指向GDT(LABEL_DESC_CODE32)的段基址
这时gs指向0x000b8000, 即段描述符的段基址。界限值:0xffff
剩下就和正常的段寄存器操作一样了。
gs:edi等
学习操作系统:进入保护模式,理解GDT(1):TEXT相关推荐
- 操作系统——认识保护模式
操作系统--认识保护模式 实验目的及内容 认真阅读章节资料,掌握什么是保护模式,弄清关键数据结构:GDT.descriptor.selector.GDTR, 及其之间关系,阅读pm.inc文件中数据结 ...
- 操作系统——让操作系统走进保护模式
操作系统--让操作系统走进保护模式 实验内容: 向软盘镜像文件写入一个你指定的文件,手工读取在磁盘中的信息 在软盘中找到指定的文件,读取其扇区信息 将指定文件装入指定内存区,并执行 学会在bochs中 ...
- 自己动手写操作系统--搭建保护模式下的运行环境:bochs下安装freedos
在进行保护模式的运行环境配置前,先看了了下书上的代码,编译运行结果如下:nasm 3_pmtest1.asm -o pmtest1.bin,可以看到界面出现了红色的 p 字 保护模式环境配置 1:在网 ...
- 操作系统引导--从实模式到保护模式
从开始到保护--系统开机引导 ------没有一个文档能写的通俗易懂,我希望写出来. 开机引导和实模式: 两个星期加上假期吐血整理,所述为计算机的开机引导,其中包括一系列计算机内存设置等等,由于没有老 ...
- 【OS学习笔记】二十六 保护模式八:任务门---任务切换
上一篇文章学习了:保护模式七:调用门与依从的代码段----特权级保护 主要学习了以下内容: 描述符特权级(目标对象的特权级)DPL 描述符特权级(目标对象的特权级)DPL 当前特权级CPL 低特权级的 ...
- 从零开始操作系统------探析保护模式
本文基于郑纲的<操作系统还原>,仅为个人学习笔记,前期的虚拟机配置等不再详细记录,其中不理解或者出错的地方还望提出意见! 从零开始操作系统------MBR直操硬盘.内核加载器 为什么有保 ...
- 【OS学习笔记】三十一 保护模式九:页目录、页表和页三者的关系详解
上一篇文章学习了:保护模式九:段页式内存管理机制概述 本篇文章接着学习以下内容: 页目录概念 页表概念 页目录.页表与页之间的关系 虚拟地址(线性地址)到物理地址的具体变换过程. 1.页目录.页表和页 ...
- 【OS学习笔记】十九 保护模式六:保户模式下操作系统内核如何加载用户程序并运行
上一篇文章学习了保户模式下如何进行内存保护 与 别名段的意义与作用:点击链接查看上一篇文章:点击链接 本文接着学习,在保护模式下,内核是如何加载用户程序并运行的.其实这与在实模式下很像,只不过现在保护 ...
- 【OS学习笔记】十五 保护模式三:保护模式下的内存访问机制
上一篇文章学习了段描述符与段描述符各个标志位的含义:段描述符 本篇文章学习如何进入保护模式,并学习如何在保护模式下进行内存访问. 1.如何进入保护模式 假设我们已经用汇编语言将段描述符安装到GDT中( ...
- 保护模式超强的寻址功能:天空任鸟飞
X86架构下,cpu 的运行模式分两种,一种是实模式,像早期Dos那种黑底白字的命令行操作界面,可以说是实模式最好表现形式,在实模式下也只能产生这种冰冷,呆板,机械的用户体验.后来Intel的CPU进 ...
最新文章
- 【转】NG:垂枝桦基因组图谱构建(2+3组装)及重测序分析
- Tomcat灵活配置多项目,多端口,多域名,多虚拟目录
- ASP.NET Ajax – History Support 續
- SAP Spartacus delivery mode continue button单元测试失败原因分析
- puppeteer( Nodejs 版 selenium )快速入门
- 机器学习——决策树的实现
- swift之Mac中NSView视图里的截图【ScrollView中的内容截图】
- NYOJ--448--寻找最大数
- perl引用中的闭包closure
- 安全管理:为软件供应链部署零信任方法
- 公众号H5运营如何激发用户的打开H5商城欲望?
- 光环PMP 项目资源管理、项目相关方管理
- 联想Y7000安装显卡驱动
- i.MX Yocto Project User‘s Guide
- 解决:idea运行scala程序,报错:Error:scalac: bad option: -make:transitive
- 158. 精读《Typescript 4》
- 计算机维修的入门知识
- Oracle同义词总结
- 微信小程序给电商行业创业的新曙光
- const指针的一些总结