12章其实是11章的拓展,代码基本不变,就是在保护模式下展开讨论。

★PART1:存储器的保护机制

1. 修改段寄存器的保护

当执行把段选择子传到段寄存器的选择器部分的时候,处理器固件在完成传送之前,要检查和确认选择子是正确的,并且该选择子选择的描述符也是正确的。假如索引号是正确的,也就是说明索引号8+7要小于等于边界。如果超过边界,那么处理器就会终止处理,产生异常中断13,同时段寄存器的原值保持不变。

同时处理器还要对描述符的类别进行检查,如果描述符的类别进行确认,举个例子来说,如果描述符的类型只是只执行的代码段,那么则不允许加载到除了CS之外的其他段寄存器中。首先描述符的类别字段必须是有效的值,比如0000就是个无效的值。然后,处理器会对描述符的类别是否符合段寄存器的用途,规则如图。

    

除了按照上表进行检查之外,还要检查描述符中的P位,如果P=0,表明虽然描述符已经被定义,但该段实际上并不存在于内存中,此时,处理器应该终止处理,引发异常中断11。一般来说,应当定义一个中断处理程序,把该描述符所对应的段从硬盘等外部存储器调入内存,然后置P位。中断返回时,处理器将再次尝试刚才的操作。如果P=1,则处理器将描述符加载到段寄存器的描述符高速缓存器,同时置A位(仅限于当前讨论的存储器的段描述符。)

可读的代码段相当于是一个ROM,可以使用段超越前缀来读其中的内容,也可以将他的描述符选择子加载到DS,ES,FS,GS作为数据段进行访问。代码段在任何时候都是不可写的。对于DS,ES,FS和GS的段选择器,可以向其加载数值为0的选择子,即

  

但是在真正访问内存的时候,就会引发异常中断,但是对于CS和SS来说,不允许传送为0的选择子。

2. 地址变换的保护

所谓地址变换的保护,其实就是对于偏移地址的限制,保护模式下,偏移地址不允许超过段界限。

段界限的计算方式:

G=0:则实际段界限就是描述符记载的段界限

G=1,:实际段界限是描述符的界限值*0x1000+0xFFF

对于代码段,因为代码段是向上拓展的,所以偏移地址只能是从0到段界限值,也就是:

0<=(EIP+指令长度-1)<=实际使用的段界限

上面这个限制对于向上拓展的数据段也是适用的,在向上拓展的代码段中:

0<=(EA+指令长度-1)<=实际使用的段界限

对于向下拓展的数据段,特别是栈段,实际使用的段内偏移地址不允许访问最低的段界限,而对于最高端地址没有限制,最大可以是0xFFFFFFFF(32位保护模式下),也就是:

实际使用的段界限+1<=(ESP的内容 - 操作数的长度)<=0xFFFFFFFF

对于向下拓展的数据段,假设段的描述符高速缓存器里的线性基地址位0x00007c00,段的界限为0Xffffe,粒度为4KB,则实际的有效物理地址范围是

0x00007c00+0Xfffff000~0x00007c00+0xffffffff

  即0x00006c00~0x00007bff(回绕回来了)

3. 使用别名访问代码段(alias)

有时候数据在代码段上,但是代码段是不可以读的,也不可以写,如果想对代码段做一些修改(比如调试程序加入断点int3),那只能是通过另外找一个数据段指向这个段来了(一般不推荐这么做,因为一般来说数据段和代码段要分开,不然会出现不可预料的错误。)当然别名技术并非仅仅可以用于读写代码段,如果两个程序想共享一个内存区域,可以为每个程序都创建一个描述符,使他们都指向同一个内存段。

★PART2:第12章的例程

1. 插入排序

    书上的例程用的是冒泡排序,自己改了个插入排序,感觉还不错,另外要注意的是,NASM对mov ds,ax和mov ds,eax生成的机器码都是一样的(一般来说,因为ax是16位的源操作数,理论来说应该加前缀0x66,而且有了这个前缀,处理器在执行时会多花一个时钟周期执行,很多编译器都不会区分这个区别。)

 ;---------------------主引导扇区程序---------------------
mov eax,[cs:gdt_base+0x7c00]
xor edx,edx
mov ebx,0x10
div ebx ;在AX得到线性基地址 mov ds,ax ;把gdt_base线性基地址地址给ds
mov bx,dx ;偏移地址 ;描述符很容易错的地方是:会把高地址的32位和低地址的32位弄反
;------------------------描述符#0------------------------
mov dword[ebx+0x00],0x00000000 ;NULL
mov dword[ebx+0x04],0x00000000
;------------------------描述符#1------------------------
mov dword[ebx+0x08],0x7c00fffe ;栈段
mov dword[ebx+0x0c],0x00cf9600
;------------------------描述符#2------------------------
mov dword[ebx+0x10],0x7c0001ff ;数据段
mov dword[ebx+0x14],0x00409200
;------------------------描述符#3------------------------
mov dword[ebx+0x18],0x7c0001ff ;代码段
mov dword[ebx+0x1c],0x00409800
;------------------------描述符#4------------------------
mov dword[ebx+0x20],0x0000ffff ;数据段
mov dword[ebx+0x24],0x00cf9200
;--------------------------------------------------------
mov word[cs:gdt_size+0x7c00], ;40个字节-1 ;易错:容易漏加载大小
lgdt [cs:gdt_size+0x7c00] ;加载段描述符
;--------------------------------------------------------
in al,0x92
or al,0x02
out 0x92,al ;快速开启A20 cli ;一定要记得关闭中断!!!!!很容易遗忘
;--------------------------------------------------------
mov eax,cr0
or eax,0x01
mov cr0,eax ;开启保护模式
;--------------------------------------------------------
jmp 0x0018:flush ;清空流水线并且串行化
[bits ]
flush:
mov ax,0x0008
mov ss,ax ;加载栈段
mov sp, mov ax,0x0010 ;加载数据段
mov ds,ax ;-----------------------插入排序-------------------------
mov ecx,gdt_size-string ;易错:字符串有一个\0,所以大小要减去1
cmp ecx,
je print mov ebx, ;这个就要求至少要大于等于2
@1:
push ecx
mov al,[ebx+string]
mov [tmp],al
mov ecx,ebx
@2:
mov al,[ecx+string-]
cmp al,[tmp]
jl @3
mov al,[ecx+string-]
mov [ecx+string],al
dec ecx
cmp ecx,
jg @2
@3:
mov al,[tmp]
mov [ecx+string],al
pop ecx
inc bx
loop @1
;-----------------------打印已序序列------------------------
print:
mov ax,0x0020 ;4GB大小的段的寻址,其实是一样的
mov es,ax mov ecx,gdt_size-string
mov edi,
mov ebx,0xb8000
@4:
mov ah,0x07
mov al,[edi+string]
mov [es:ebx+edi*],ax
inc di
loop @4
;-------------------------停机---------------------------
stop:
hlt
;--------------------------------------------------------
tmp: db ;定义一个临时变量,注意这个东西千万不能在代码区出现!
;--------------------------------------------------------
string: db 's0ke4or92xap3fv8giuzjcy5l1m7hd6bnqtw.'
;--------------------------------------------------------
gdt_size: dw 0x00
gdt_base: dd 0x00007e00
;--------------------------------------------------------
times -($-$$) db
dw 0xaa55

2. 课后习题第一题

 ;---------------------------12.1----------------------------
code_start equ 0x7c00
pos1 equ 0x0050
pos2 equ 0x00a0 mov eax,[cs:gdt_base+code_start]
xor edx,edx
mov ebx,
div ebx ;基地址在AX上,偏移地址在DX上 mov ds,eax
mov ebx,edx
;--------------------------描述符#0--------------------------
mov dword[ebx+0x00],0x00000000
mov dword[ebx+0x04],0x00000000
;--------------------------描述符#1--------------------------
mov dword[ebx+0x08],0x7c0001ff ;代码段
mov dword[ebx+0x0c],0x00409800
;--------------------------描述符#2--------------------------
mov dword[ebx+0x10],0x00000fff ;要扫描的数据段,长65536*4个字节
mov dword[ebx+0x14],0x00c09210
;--------------------------描述符#3--------------------------
mov dword[ebx+0x18],0x80000fff ;屏幕显示段
mov dword[ebx+0x1c],0x0040920b
;--------------------------描述符#4--------------------------
mov dword[ebx+0x20],0x7c0001ff ;代码段别名段
mov dword[ebx+0x24],0x00409200
;--------------------------描述符#5--------------------------
mov dword[ebx+0x28],0x7c00fffe ;栈段
mov dword[ebx+0x2c],0x004f9600
;------------------------------------------------------------
mov word[cs:gdt_size+code_start], ;设定选择子界限值
lgdt [cs:gdt_size+code_start]
;------------------------------------------------------------
in al,0x92
or al,0x02
out 0x92,al ;快速开启A20
cli ;关中断
;------------------------------------------------------------
mov eax,cr0
or eax,0x01 ;设定PE位
mov cr0,eax
;------------------------------------------------------------
jmp 0x0008:flush ;清空流水线并且串行化处理器,进入保护模式
[bits ]
flush:
mov eax,0x0028
mov ss,eax ;设置栈段
mov sp, mov eax,0x0018
mov es,eax ;设定显示段
mov eax,0x0020
mov ds,eax ;设定别名段
mov eax,0x0010
mov gs,eax ;设定要搜索的段 mov edi,0x0000
mov esi,string
mov ecx,gdt_size-string
call print_string mov esi,nums
mov ecx, ;统计总数
@scan:
;先显示总数
inc dword[tmp] mov di,pos1 ;设定显示位置
call cal_nums ;再看下能不能找到一个有效块
mov di,pos2 ;设定显示位置
call compare inc ecx
cmp ecx,0xfffff
jle @scan
;-------------------------停机------------------------------
hlt
;code_end ;------------------------------------------------------------
;------------------------------------------------------------
;------------------------函数部分----------------------------
;------------------------------------------------------------
print_string:
push eax
push ebx
push ecx
push edx mov ebx,edi
mov edx,esi
print_start:
mov al,[edx]
mov [es:ebx*],al
mov byte[es:ebx*+],0x07
inc ebx
inc edx
loop print_start pop edx
pop ecx
pop ebx
pop eax
ret
;------------------------------------------------------------
cal_nums:
push eax
push ecx mov eax,[tmp]
mov ebx,
mov ecx,
@1:
xor edx,edx
div ebx
push edx
inc ecx
cmp eax,
jne @1
mov ebx,ecx
mov edx,
@2:
pop eax
add al,0x30
mov [edx+nums],al
inc edx
loop @2
mov ecx,ebx ;恢复要打印的数量
call print_string pop ecx
pop eax
ret
;------------------------------------------------------------
compare:
push eax cmp dword[gs:ecx*],0x55aa55aa
je Found_a_Block
cmp dword[gs:ecx*],0xaa55aa55
je Found_a_Block out_func:
pop eax
ret
Found_a_Block:
inc dword[found_num]
mov eax,[found_num]
mov [tmp],eax call cal_nums pop eax
ret
;function_end ;------------------------------------------------------------
;-------------------------数据区-----------------------------
;------------------------------------------------------------
tmp: dd
;------------------------------------------------------------
found_num dd
;------------------------------------------------------------
nums: times db
;------------------------------------------------------------
string: db 'Protect mode has been started'
;------------------------------------------------------------
gdt_size: dw
gdt_base: dd 0x00007e00
;------------------------------------------------------------
times -($-$$) db
dw 0xaa55

  结果一个0xaa55aa55或者0x55aa55aa的值都没有。

ASM:《X86汇编语言-从实模式到保护模式》第12章:存储器的保护的更多相关文章

  1. ASM:《X86汇编语言-从实模式到保护模式》第15章:任务切换

    15章其实应该是和14章相辅相成的(感觉应该是作者觉得14章内容太多了然后切出来了一点).任务切换和14章的某些概念是分不开的. ★PART1:任务门与任务切换的方法 1. 任务管理程序 14章的时候 ...

  2. ASM:《X86汇编语言-从实模式到保护模式》第14章:保护模式下的特权保护和任务概述

    ★PART1:32位保护模式下任务的隔离和特权级保护  这一章是全书的重点之一,这一张必须要理解特权级(包括CPL,RPL和DPL的含义)是什么,调用门的使用,还有LDT和TSS的工作原理(15章着重 ...

  3. ASM:《X86汇编语言-从实模式到保护模式》第10章:32位x86处理器的编程架构

    ★PART1:32位的x86处理器执行方式和架构 1. 寄存器的拓展(IA-32) 从80386开始,处理器内的寄存器从16位拓展到32位,命名其实就是在前面加上e(Extend)就好了,8个通用寄存 ...

  4. ASM:《X86汇编语言-从实模式到保护模式》第8章:实模式下硬盘的访问,程序重定位和加载

        第八章是一个非常重要的章节,讲述的是实模式下对硬件的访问(这一节主要讲的是硬盘),还有用户程序重定位的问题.现在整理出来刚好能和保护模式下的用户程序定位作一个对比. ★PART1:用户程序的重 ...

  5. ASM:《X86汇编语言-从实模式到保护模式》第9章:实模式下中断机制和实时时钟

    中断是处理器一个非常重要的工作机制.第9章是讲中断在实模式下如何工作,第17章是讲中断在保护模式下如何工作. ★PART1:外部硬件中断 外部硬件中断是通过两个信号线引入处理器内部的,这两条线分别叫N ...

  6. ASM:《X86汇编语言-从实模式到保护模式》第16章:Intel处理器的分页机制和动态页面分配

    第16章讲的是分页机制和动态页面分配的问题,说实话这个一开始接触是会把人绕晕的,但是这个的确太重要了,有了分页机制内存管理就变得很简单,而且能直接实现平坦模式. ★PART1:Intel X86基础分 ...

  7. ASM:《X86汇编语言-从实模式到保护模式》第11章:进入保护模式

    ★PART1:进入保护模式 1. 全局描述符表(Global Descriptor Table,GDT)        32位保护模式下,如果要使用一个段,必须先登记,登记的信息包括段的起始地址,段的 ...

  8. ASM:《X86汇编语言-从实模式到保护模式》第17章:保护模式下中断和异常的处理与抢占式多任务

    ★PART1:中断和异常概述 1. 中断(Interrupt) 中断包括硬件中断和软中断.硬件中断是由外围设备发出的中断信号引发的,以请求处理器提供服务.当I/O接口发出中断请求的时候,会被像8259 ...

  9. ASM:《X86汇编语言-从实模式到保护模式》第13章:保护模式下内核的加载,程序的动态加载和执行

    ★PART1:32位保护模式下内核简易模型 1. 内核的结构,功能和加载 每个内核的主引导程序都会有所不同,因为内核都会有不同的结构.有时候主引导程序的一些段和内核段是可以共用的(事实上加载完内核以后 ...

随机推荐

  1. jQuery1.9.1源码分析--数据缓存Data模块

    jQuery1.9.1源码分析--数据缓存Data模块 阅读目录 jQuery API中Data的基本使用方法介绍 jQuery.acceptData(elem)源码分析 jQuery.data(el ...

  2. ie8及其以下浏览器的document.getElementsByClassName兼容性问题

    使用JavaScript访问DOM的一个重大问题是,此过程需要一种通过元素类名称来选择类的类函数,对DOMContentReady,这种类函数的缺失导致开发人员需要自己编写自定义脚本业执行上述任务,许 ...

  3. 关于学习session的一二

    session作为一种服务器端技术,在网页中与cookie相配合可谓相得益彰,今天学习了进一步session的相关知识,在这里记录一二,以便于以后查阅 /*问题:当我们浏览网页的时候,张三和李四可以购 ...

  4. Jquery中的事件和动画

    在学习Jquery中的过程中我们绝大部分都用到了事件的操作,也可以说事件是Jquery中必不可少的一部分,我们常见的一些事件有单击事件,鼠标事件,键盘事件等等.在Jquery中的学习中为了能使让页面以 ...

  5. int (*p)[4] 与 int* p[4]

    碰到一道题: ][] = {,,,,,,,,,,,}; ]; ] = (a+); cout<<*(p+)<<endl; cout<<(*ptr+)[]<< ...

  6. Java File 常用操作回顾

    最近项目中要用到File这个类,温故而知新,回过头来回顾下这个File类,File类主要是对磁盘目录,文件进行操作的Api,具体其实查JDK api 的File全能获取到. 下面写一些文件目录的基本操 ...

  7. EditorGUILayout.EnumPopup 枚举弹出选择菜单

    http://www.unity蛮牛.com/thread-25490-1-1.html http://www.unity蛮牛.com/m/Script/EditorGUILayout.EnumPop ...

  8. [RouterOS] ROS对接碧海威或PA等流控实现完美流控详细教程(附脚本全免费)

    前言: 经常在群里看到不少朋友争论海蜘蛛 ROS 维盟 爱快 碧海威 流控大师 Woyos等等软路由,哪个好.实际上,网络产品是复杂的,现在的软路由功能上已经远远不是单独的路由了.每种产品都有他本身的 ...

  9. NOIP2015 斗地主

    Sol 暴力搜索...不用搜1,2张的情况,直接统计出来就可以了. 还有处理一下2和大王小王的位置,扔到最后面或者最前面就可以了. 搜索就搜 3+3,2+2+2,1+1+1+1+1 这三个就可以了. ...

  10. 解压.tar.gz出错gzip: stdin: not in gzip format tar: /Child returned status 1 tar: Error is not recoverable: exiting now

    先查看文件真正的属性是什么? [root@xxxxx ~]# tar -zxvf tcl8.4.16-src.tar.gz  gzip: stdin: not in gzip format tar: ...