《80x86汇编语言程序设计》保护模式第一个例题

《80x86汇编语言程序设计》保护模式第一个例题的一些个人理解和注释

; 16位偏移的段间直接转移指令的宏定义
02.jump macro selector, offsetv
03.
04.    db 0eah                 ; jmp far 的操作码
05.    dw offsetv
06.    dw selector
07.
08.endm
09.
10.; 字符显示宏指令定义
11.echoch macro ascii
12.
13.    mov ah, 2
14.    mov dl, ascii
15.    int 21h
16.
17.endm
18.
19.; 存储段描述符结构类型的定义
20.descriptor struc
21.
22.limitl      dw 0                ; 段界限低16位
23.basel       dw 0                ; 基地址低16位
24.basem       db 0                ; 基地址中8位
25.attributes  dw 0                ; 段属性,包含段界限高4位
26.baseh       db 0                ; 基地址高8位
27.
28.descriptor ends
29.
30.; 伪描述符结构类型的定义
31.pdesc struc
32.
33.limit       dw 0                ; 16位段界限
34.base        dd 0                ; 32位基地址
35.
36.pdesc ends
37.
38.; 常量定义
39.atdw = 92h                      ; 存在的可读写数据段属性值
40.atce = 98h                      ; 存在的只执行代码段属性值
41.
42..386p
43.
44.; 数据段
45.dseg segment use16
46.
47.gdt     label byte              ; 全局描述符表GDT
48.dummy       descriptor <>             ; 空描述符
49.code        descriptor <0ffffh, , , atce, >
50.code_sel    = code - gdt                ; 代码段描述的选择子
51.datas       descriptor <0ffffh, 0h, 11h, atdw, 0>
52.datas_sel   = datas - gdt               ; 源数据段描述符的选择子
53.datad       descriptor <0ffffh, , , atdw, >
54.datad_sel   = datad - gdt               ; 目标数据段描述符的选择子
55.gdtlen      = $ - gdt
56.
57.vgdtr       pdesc <gdtlen - 1, >          ; 伪描述符
58.
59.bufferlen   = 256                   ; 缓冲区字节长度
60.buffer      db bufferlen dup (0)            ; 缓冲区
61.
62.dseg ends
63.
64.; 代码段
65.cseg segment use16
66.
67.        assume cs:cseg, ds:dseg
68.
69.start:
70.
71.        mov ax, dseg
72.        mov ds, ax
73.
74.        ; 准备要加载到gdtr的伪描述符
75.        mov bx, 16
76.        mul bx
77.        add ax, offset gdt
78.        adc dx, 0
79.        mov word ptr vgdtr.base, ax
80.        mov word ptr vgdtr.base + 2, dx
81.
82.        ; 设置代码段描述符
83.        mov ax, cs
84.        mul bx
85.        mov code.basel, ax
86.        mov code.basem, dl
87.        mov code.baseh, dh
88.
89.        ; 设置目标数据段描述符
90.        mov ax, ds
91.        mul bx
92.        add ax, offset buffer
93.        adc dx, 0
94.        mov datad.basel, ax
95.        mov datad.basem, dl
96.        mov datad.baseh, dh
97.
98.        ; 加载gdtr
99.        lgdt fword ptr vgdtr
100.
101.        cli
102.        call enablea20
103.
104.        ; 切换到保护方式
105.        xchg bx, bx
106.        mov eax, cr0
107.        or eax, 1
108.        mov cr0, eax
109.
110.        ; 清指令欲取队列,并真正进入保护方式
111.        jump <code_sel>, <offset virtual>
112.
113.virtual:
114.        mov ax, datas_sel
115.        mov ds, ax
116.        mov ax, datad_sel
117.        mov es, ax
118.        cld
119.        xor si, si
120.        xor di, di
121.        mov cx, bufferlen / 4
122.        repz movsd
123.
124.        ; 切换回实方式
125.        mov eax, cr0
126.        and eax, 0fffffffeh
127.        mov cr0, eax
128.
129.        ; 清指令预取队列,进入实方式
130.        jump <seg real>, <offset real>
131.
132.real:
133.        call disablea20
134.        sti
135.
136.        mov ax, dseg
137.        mov ds, ax
138.        mov si, offset buffer
139.        cld
140.        mov bp, bufferlen / 16
141.
142.nextline:
143.        mov cx, 16
144.
145.nextch:
146.        lodsb
147.        push ax
148.        shr al, 4
149.        call toascii
150.        xchg bx, bx
151.        echoch al
152.        xchg bx, bx
153.        pop ax
154.        call toascii
155.        echoch al
156.        echoch ‘ ‘
157.        loop nextch
158.        echoch 0dh
159.        echoch 0ah
160.        dec bp
161.        jnz nextline
162.
163.        mov ax, 4c00h
164.        int 21h
165.
166.toascii  proc
167.
168.        and al, 0fh
169.        add al, 30h
170.        cmp al, ‘9‘
171.        jbe quit
172.        add al, 7
173.
174.quit:
175.        ret
176.
177.toascii endp
178.
179.enablea20 proc
180.
181.        push ax
182.        in al, 92h
183.        or al, 2
184.        out 92h, al
185.        pop ax
186.        ret
187.
188.enablea20 endp
189.
190.disablea20 proc
191.
192.        push ax
193.        in al, 92h
194.        and al, 0fdh
195.        out 92h, al
196.        pop ax
197.        ret
198.
199.disablea20 endp
200.
201.cseg ends
202.
203.end start    

我自己以前的疑问与我自己的答案:

Q:为什么要设置GDTR?

A:应为需要他来找到GDT

Q:mul bx什么意思?

A:转换为物理地址,就是段值*16

Q:jump <code_sel>, <offset virtual>什么意思?

A:这条指令是在转换到保护模式之前预取到指令队列的,如果不预取,转换到保护模式后系统会把cs中的值以为是选择子,但其实他是段值,就无法执行下一条指令,也就是jmp,所以要预取这条宏,然后执行时把cs设置为选择子,刷新预取指令队列,引用:

“由此可见,执行这条jmp指令时CPU已经处于“保护方式”了(因为cr0中的PE已经被置成“保护方式”)。如果此条jmp指令如果不是在“实方式”下被预取到指令队列中,就无法执行到它,因为“cr0中的PE被置成保护方式”之后,cs中的值仍为实方式的段值,此时将当前ip加1,然后用cs:ip去取下面的这条jmp指令显然会失败,因为此时处于“保护方式”下的cpu会把cs中的内容理解为“选择子”,所以自然无法取得“紧接着的”jmp指令。”

Q:shr al, 4啥意思?

A:是要显示其高4位,然后下面pop后显示低四位

Q:mov ax, datas_sel什么意思?
A:datas_sel为选择子,值为8,换为二进制是1000,低三位分别是0位、1位为RPL,2位为TI,3~15位是描述符表索引,也即第一个描述符
>>>>>>>>>>>>>>>琐碎记忆>>>>>>>>>>>>>>>>>
保护方式下通过选择子的3~15位来定位在描述符表中的描述符,然后获得基地址、界限、属性

时间: 2024-08-01 06:31:16

《80x86汇编语言程序设计》保护模式第一个例题的相关文章

《80X86汇编语言程序设计教程》十 实模式与保护模式的切换实例

1.  再次声明,需要纯DOS系统才能看到满意测试效果.内容是演示实模式与保护模式切换实例,实现功能是16进制显示从110000H开始的256个字节的值 2.  源代码如下: 1 ;功能:演示实模式与保护模式的切换,16进制显示从110000H开始的256个字节的值 2 ;16位偏移的段间直接转移指令的宏定义,这是一个JMP指令到所描述的地址 3 4 JUMP macro selector,offsetv 5 db 0eah ;操作码 6 dw offsetv ;16位偏移 7 dw selec

《80X86汇编语言程序设计教程》二十四 进入与离开V86模式实例

1.  这是我这本书调得最失败的一个实例,而且问题都是超出了这本书能教会我的范畴.作者对调试环境几乎只字不提,这让我有点费解.原作者使用TASM的编译代码,而我使用的MASM加虚拟机进行测试,不知道这两样东西哪里有问题还是源代码要做哪些修正.理论知识参考"<80X86汇编语言程序设计教程>二十二 分页管理机制与虚拟8086模式". 2.  进入和离开V86模式实例:各2种方式进入和离开V86模式.V86模式下8086程序调用实模式软中断处理程序.逻辑功能:以驻留方式结束程序

《80X86汇编语言程序设计教程》十九 操作系统类指令与输入输出保护

1.  通常只在操作系统代码中使用,80386支持4个特权等级,操作系统指令也可分3种:实模式和任何特权级下可执行指令.实模式及特权级0下可执行的指令和仅在保护模式下执行的指令. 1)  实模式和任何特权级下可执行的指令 a)存储全局和中断描述符表寄存器指令 GDT与IDT整个系统各只有一张,它们的定位信息分别保存在GDTR与IDTR中,这两个寄存器的值可以被保存.须注意,LDT表示任务私有,存储LDTR值的指令不属于这一类. i)存储全局描述符表寄存器指令:SGDT  DST DST是48位(

《80X86汇编语言程序设计教程》十五 任务切换实例

1.  理论知识参考"<80X86汇编语言程序设计教程>十二 任务状态段.控制门和控制转移",演示内容:直接通过TSS段的任务切换.通过任务门的任务切换.任务内特权级的变换及参数传递.实现的逻辑功能是:从Temp任务切换到Demo任务以后显示原任务(Temp)的挂起点EIP的值. 2.  源代码 "386scd.asm"不再贴上来.参考"<80X86汇编语言程序设计教程>十三 任务内无特权级变换转移实例",演示代码如下:

《80X86汇编语言程序设计教程》十一 32位代码段和16位代码段切换实例

1.  演示32位代码段与16位代码段之间的切换.实现的功能是以十六进制和ASCII码字符两种形式显示从内存地址100000H开始的16个字节的内容. 2.  源代码如下: 1 ;DosTest.Asm 2 ;16位偏移的段间转移指令的宏定义 3 ;使用于16位段,用于跳转到32位目的段 4 ;注意:标号偏移必须在16位二进制符号数数能表示的范围之内 5 JUMP16 macro selector,offsetv 6 db 0eah ;操作码 7 dw offsetv ;16位偏移 8 dw s

《80X86汇编语言程序设计教程》二十五 结语(读后感:这本书怎么样)

这本书的推荐星级是:5星.毕竟是经典书籍,没什么好说的. 就汇编本身而言,在编写高效率程序以及对程序的优化,调试,工程的逆向都是一门基础:就理论上的操作系统而言,汇编让你了解CPU,了解计算机的体系结构,它是阅读操作系统源码的前提,这也是<80X86汇编语言程序设计教程>做得比较好的一点,它对386的保护方式下的编程写得比较详实,读完整本书,会发现这学的不仅仅是汇编语言,还有CPU的体系架构,它让你基本猜测得到在编写基于80386CPU的操作系统时,大概要做一些什么事情. 阅读前,我选过几本书

《80X86汇编语言程序设计教程》二十三 分页管理机制实例

1.  理论知识参考"<80X86汇编语言程序设计教程>二十二 分页管理机制与虚拟8086模式".演示分页机制实例:初始化页目录表和部分页表:启用分页管理机制:关闭分页管理机制等.逻辑功能:在屏幕上显示一条表示已启用分页管理机制的提示信息.大体步骤是:在实模式下拷贝显示串程序的代码到预定义区域,转保护模式,初始化页目录和2个页表,开启分页机制,转入预定义区执行显示代码,然后关闭分页机制,重新回到实模式,程序终止. 2.  源代码 "386scd.asm"

《X86汇编语言 从事模式到保护模式》问题

书中的42页,监测点4.2第一题,代码如下: mov ax, 0xb800 mov ds, ax mov [0x00], 'a' mov [0x02], 's' mov [0x04], 'm' jmp $ 编译会报错 提示没有指定操作数长度,修改后为 mov ax, 0xb800 mov ds, ax mov byte [0x00], 'a' mov byte [0x02], 's' mov byte [0x04], 'm' jmp $ 然后用书中提供的工具fixvhdwr.exe写入到虚拟机的

程序的载入和运行(五)——《x86汇编语言:从实模式到保护模式》读书笔记25

程序的载入和运行(五)--<x86汇编语言:从实模式到保护模式>读书笔记25 前面几篇博文最终把代码分析完了.这篇就来说说代码的编译.运行和调试. 1.代码的编译及写入镜像文件 之前我们都是在命令行输入命令进行编译和写入.源文件少的时候还不认为麻烦,当源文件多了,就会认为特别麻烦.有没有简单的方法呢? 当然有,就是用make工具. 1.1.什么是make工具 make是一个命令工具,它解释Makefile中的指令.在Makefile文件里描写叙述了整个project全部文件的编译顺序.编译规则