接着上一篇博文说。

5.代码段执行时的保护

每个代码段都有自己的段界限。同栈段一个道理,有效界限和G位相关。

G=0:有效界限 = 描述符中的段界限

G=1:有效界限 = 描述符中的段界限值 * 0x1000 + 0xFFF

当处理器取指令的时候,偏移地址由EIP提供,EIP的范围应该在 [0,有效界限] 之间(为了说明问题,我就用数学上的闭区间表示了)。否则会引发异常。

对于本代码,代码段描述符中的界限值是0x1FF,G=0,那么有效界限=0x1FF,也就是说这个值就是段内最后一个允许访问的偏移地址。

再举一个例子,源文件中

71         mov dword [es:0x0b8000],0x072e0750 ;字符'P'、'.'及其显示属性
72         mov dword [es:0x0b8004],0x072e074d ;字符'M'、'.'及其显示属性
73         mov dword [es:0x0b8008],0x07200720 ;两个空白字符及其显示属性
74         mov dword [es:0x0b800c],0x076b076f ;字符'o'、'k'及其显示属性

这四行对应的.list文件如下

可以看到,第71行,mov dword [es:0x0b8000],0x072e0750 这条指令,其偏移地址为 0xB8~0xC2; 那么,要想这条指令顺利执行,定义代码段时,有效界限就要大于等于0xC2.当等于0xC2的时候,这条指令可以顺利执行,但是下一条指令的执行会引发异常。

也就是说,如果某条指令的偏移地址为M~N,那么这条指令被顺利执行的必要条件是集合[M,N]属于集合[0,代码段的有效界限]。(请原谅我借用集合来描述,可是我再也想不出什么简明的表达了

6.数据访问时的保护

这里所说的数据段,特指向上扩展的数据段,有别于栈段和向下扩展的数据段。

访问数据段时,是否越界与操作数的长度有关。

对于向上扩展的数据段,有效界限的计算方法依然是:

G=0:有效界限 = 描述符中的段界限

G=1:有效界限 = 描述符中的段界限值 * 0x1000 + 0xFFF

举例来说,第74行

74         mov dword [es:0x0b800c],0x076b076f ;字符'o'、'k'及其显示属性

这条指令的目的是把0x076b076f写入偏移地址为0x0b800c~0x0b800f的4个存储单元。如果要成功写入,那么0x0b800c~0x0b800f必须在数据段的有效界限内。也就是要求:

[0xb800c, 0xb800f] 属于 [0, 上扩数据段的有效界限]

本代码中,数据段的有效界限值是0xFFFF_FFFF,也就是说可以访问4GB空间内的任何一个单元。

7.使用别名段访问代码段对字符排序

104;-------------------------------------------------------------------------------
105     string           db 's0ke4or92xap3fv8giuzjcy5l1m7hd6bnqtw.'
106;-------------------------------------------------------------------------------

第105行,定义了一串字符。作者要对这串字符进行升序排序,其实“醉翁之意不在酒”——排序是假,使用别名段是真。因为代码段是不允许写入的,所以要修改代码段,就需要为之创建一个别名描述符。第33、34行,程序为代码段创建了一个可读写的数据段描述符。也就是说,我们可以把代码段当成数据段来用。

33         mov dword [ebx+0x18],0x7c0001ff    ;基地址为0x00007c00,512字节
34         mov dword [ebx+0x1c],0x00409200    ;粒度为1个字节,数据段描述符,可读写

第59、60行,把这个别名段的选择子加载到DS

59         mov eax,0x0018
60         mov ds,eax

这里我们用冒泡排序法,虽然这个方法效率低,但是很适合初学者入门。关于冒泡排序的知识,请参考其他资料。

为了说明问题,我绘制了一张图,假如一共有5个数,要把它们从左至右按照升序排列,示意图如下。

每比较一次,就把较大的数放在右边。那么第一次外循环后,最大的数就冒到了最右边;第二次外循环后,第二大的数冒到了从右边数第二个位置;……

如果N个数参加排序,那么外循环需要(N-1)次。第1次需要(N-1)次比较,第2次需要(N-2)次比较,……第(N-1)次需要一次比较。

说了这么多,我就是想说清楚代码。

76         ;开始冒泡排序
77         mov ecx,pgdt-string-1              ;遍历次数=串长度-1
78  @@1:
79         push ecx                           ;32位模式下的loop使用ecx
80         xor bx,bx                          ;32位模式下,偏移量可以是16位,也可以
81  @@2:                                      ;是后面的32位
82         mov ax,[string+bx]
83         cmp ah,al                          ;ah中存放的是源字的高字节
84         jge @@3
85         xchg al,ah
86         mov [string+bx],ax
87  @@3:
88         inc bx
89         loop @@2
90         pop ecx
91         loop @@1

第77行,刚开始,ECX保存着外循环的次数(字符数-1)。

79行把ECX压栈是因为内循环也要用这个值(这个值就是本循环比较的次数),而且在内循环中,这个次数会变化。为了不破坏外循环的次数,所以要压栈保存。

第81~89行,是内循环,完成字符对比的工作。首先一次性读入2个字符到AX中,AL中存放的是前一个(低地址处的)字符,AH中存放的是后一个(高地址处的)字符,如果前者大,则交换AL和AH的内容,然后把AX重写入原来的存储单元。接下来,BX加1,以指向下一个字符。

93         mov ecx,pgdt-string
94         xor ebx,ebx                        ;偏移地址是32位的情况
95  @@4:                                      ;32位的偏移具有更大的灵活性
96         mov ah,0x07
97         mov al,[string+ebx]
98         mov [es:0xb80a0+ebx*2],ax          ;演示0~4GB寻址。
99         inc ebx
100        loop @@4
101
102        hlt

排序完毕后,第93~100,用于显示最终的排序结果。

第98行表示从显存的第2行第1列(0xb8000 + 0xa0(=160D) = 0xb80a0)开始显示字符串。当EBX=0、1、2……时,对应的地址是0xb80a0、0xb80a2、0xb80a4……(使用比例因子就是这么方便),注意,“0xb80a0 + ebx * 2”,这个表达式的值是在指令执行时,由处理器计算出来的。

(12章完)

存储器的保护(二)——《x86汇编语言:从实模式到保护模式》读书笔记19相关推荐

  1. x86汇编语言从实模式百度云_x86汇编语言:从实模式到保护模式

    x86汇编语言:从实模式到保护模式2013年1月由电子工业出版社出版发行,总共6000行的源代码,全方位地向读者展现汇编语言程序设计之美.尽管汇编语言也是一种计算机语言,但却是与众不同的,与它的同类们 ...

  2. x86汇编语言从实模式百度云_Intel x86 CPU 32位保护模式杂谈之任务切换 上

    目录: 什么是任务 任务由什么组成 任务门描述符是什么东东?有了TSS描述符为什么要有任务门描述符? 参考文献 什么是任务 任务(task)是处理器可以分配.执行.挂起的工作单位,笔者认为和我们操作系 ...

  3. 【OS修炼指南目录】----《X86汇编语言-从实模式到保护模式》读书笔记目录表

    学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 本文是将个人 ...

  4. X86汇编语言从实模式到保护模式12:存储器的保护

    目录 1. 进入32位保护模式 1.1 创建GDT表 1.1.1 空描述符 1.1.2 数据段描述符 1.1.3 代码段描述符 1.1.4 代码段别名描述符 1.1.5 栈段描述符 1.2 mov d ...

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

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

  6. X86汇编语言从实模式到保护模式15:任务和任务的创建

    目录 1. 任务的概念与组成 1.1 任务的概念 1.2 多任务系统 1.3 任务的组成 1.3.1 局部描述符表LDT 1.3.2 任务状态段TSS 2. 任务控制块和TCB链表 2.1 为何需要任 ...

  7. X86汇编语言从实模式到保护模式10:进入保护模式

    目录 1. 全局描述符表GDT 1.1 段描述符与描述符表 1.2 全局描述符表的定义 1.3 全局描述符表寄存器GDTR 1.3.1 GDTR用途 1.3.2 GDTR构成 1.3.3 lgdt指令 ...

  8. X86汇编语言从实模式到保护模式16:特权级和特权级保护

    目录 1. 特权级保护机制 1.1 基础段保护机制的不足 1.2 特权级划分 1.3 特权级的表示 1.3.1 当前特权级CPL 1.3.2 描述符特权级DPL 1.3.3 请求特权级RPL 1.4 ...

  9. X86汇编语言从实模式到保护模式11:指令格式及操作尺寸

    目录 1. 80286的16位保护模式 1.1 80286寄存器 1.2 80286段描述符 1.3 80286保护模式内存访问 2. 指令操作尺寸 2.1 指令操作尺寸的概念 2.2 16位处理器的 ...

  10. [书]x86汇编语言:从实模式到保护模式 -- 第13章 mbr加载内核、内核加载应用程序

    # mbr加载内核 1.0x7c00,16位实模式 2.进入保护模式前的准备工作:创建段描述符(代码段.数据段.堆栈段.显示缓冲区),构建gdt 3.进入保护模式 ; 开启保护模式 ; CR0的第1位 ...

最新文章

  1. ads1115寄存器操作
  2. OpenCV下利用傅里叶变换和逆变换实现图像卷积算法,并附自己对于卷积核/模板核算子的理解
  3. 传输参数【JAX-WS入门系列】第06章_使用MTOM处理二进制文件
  4. bash环境(变量与bash配置文件)
  5. 尺度空间(Scale space)理论
  6. CF442C-Artem and Array【贪心】
  7. 缓存jQuery对象来提高性能
  8. mysql tx read only_DB为何大量出现select @@session.tx_read_only 详解
  9. 石墨烯和富勒烯的区别?-供应石墨烯微片粉末/单层的多孔石墨烯前驱物/三维石墨烯网络结构复合材料块体定制
  10. 0ctf-2017-pwn-char 题解
  11. 【数字化常识】浅谈互联网企业的利器——“网络效应”
  12. eclipse里把Servers视图弄出来
  13. 简述使用计算机对会计工作的影响,会计电算化对会计工作的影响有哪些
  14. 一文详解elasticsearch的索引生命周期管理—rollover+curator—ilm
  15. hibernate之HQL实体更新与删除
  16. 【经验分享】如何使用校园账号登录WOS(Web of Science)
  17. (转)WAVE PCM 声音文件格式
  18. 使用python为Excel插入附件
  19. goproxy和go modules的初步使用
  20. 【STM32】标准库与HAL库对照学习教程八--串口通信详解

热门文章

  1. CSS之box-shadow
  2. 如何看待水氢发动机事件
  3. SQL Server事务回滚对自增键的影响
  4. Navicat for mysql导入.sql数据库大小受限制
  5. 第二冲刺阶段个人博客7
  6. 关于重载函数的一些学习
  7. unix cheatsheet
  8. 时光已荏苒,我还怎么让你遇见最美年华里的我
  9. [转载] Win7下MATLAB 7.0下载地址和详细安装
  10. 寄存器(CPU工作原理)04 - 零基础入门学习汇编语言09