7.07 王爽汇编语言(四)
检测点 2.3
8086 CPU 有4个段寄存器,CS、DS、SS、ES,这次只研究 CS 段寄存器; CS 为代码段寄存器、IP为指令指针寄存器;
# CPU 从内存中读取指令的过程简要总结如下
CS 寄存器保存段地址,IP 寄存器中保存偏移地址,CS 中的值和 IP 中的值通过内部总线送入地址加法器进行计算出
物理地址:物理地址 = 段地址 * 16 + 偏移地址;
然后将计算出的物理地址通过输入输出电路从 CPU 由外部宽度为 20 的地址总线将地址送往存储器,存储器根据地址
将指令数据由CPU和存储器相连的数据总线送往 CPU,然后 IP 寄存器根据传输过来的指令数据大小,增加自己的值,进而让 CS:IP 指向下一条将要执行的指令的地址;CPU 从输入输出电路获取到指令数据后由内部总线送往指令缓冲
器,进而再送往执行控制器;进而执行指令,改变其他寄存器的值
由于指令和数据在内存中都是以二进制的形式保存的,那么 CPU 怎么识别传输过来的数据是指令还是数据呢? 学习这一章之后可以知道,CPU 将 CS:IP 指向的数据看作是指令;
作业答案
(1): 4 次修改 IP,最后 IP 的值是 ax; (2):实验 1 需要记住 Debug 功能的常用命令;
# Debug 的 R 命令查看、改变 CPU 寄存器的内容:
直接使用 r 命令可以查看当前所有 CPU 寄存器的内容;
r ax 类似这样可以修改 CPU 寄存器的内容;
# Debug 的 D 命令查看内存中的内容:
直接使用 d 命令可以查看从下一条指令执行地址开始 128 个内存单元中的内容;
"d 段地址:偏移地址" 可以列出从"段地址:偏移地址"开始往后 128 个内存单元的地址;
"d 段地址:偏移地址 偏移量" 可以列出从"段地址:偏移地址"加上偏移量的内存单元;
可以采用不同的段地址和偏移地址来查看同一个物理内存单元的内容,因为只要相加的和是同一个物理地址即可;
# Debug 的 E 命令改写内存中的内容:
"e 起始地址 数据 数据 数据..."这样的格式来修改内存单元中的内容:如"e 1000:0 1 2 3"修改了从
1000:0 地址及往后两个地址的内存单元;
也可以直接 "e 起始地址",然后修改值这样,按一下空格,就继续修改下一个值;
还可以用 e 命令向内存中写入字符:例如 "e 1000:0 'a' 'b'"这样向内存中写入字符'a','b',对应通
过 ASCII 字符映射成 16 进制编码;
还可以用 e 命令向内存中写入字符串:例如 "e 1000:0 'this is bug'",这里字符串用单引号或者双引号
括起来都可以;
# Debug 的 U 命令将内存中的机器指令翻译成汇编指令:
向内存中写入机器码后,可以通过"u 地址"的方式从给出的地址往下将机器码翻译成汇编指令;
# Debug 的 T 命令执行一条 CS:IP 指向的机器指令:
直接写 t 即可执行下一条指令;
# Debug 的 A 命令以汇编指令的格式在内存中写入一条机器指令:
前面用 e 命令往内存里键入一个一个字节的形式来写入机器指令,是不方便的,所以可以用 a 命令
来向内存直接写入汇编指令,它自动转化为机器指令;
使用方式:"a 内存地址"
Debug 的 Q 命令退出 Debug 模式;
(3)实验任务: 1: 简单,没啥说的;
2:
# 以下是 debug 模式中的操作
a 2000:0 # 向 2000:0 地址中写入汇编指令
mov ax, 1
add ax, ax
jmp 2000:0003
r cs # 然后将 cs 寄存器的值改为 2000
r ip # 然后将 ip 寄存器的值改为 0
t # 接下来就是 t 挨个执行指令就能算出 8 了
# 疑问?但是我怎么终止呢?每次我执行刀 2000:0005是的时候都会跳转到 2000:0003 ....
3:
# 解析
FFF00H 物理地址换算: fff0:0
FFFFFH 物理地址换算:ffff:f
所以使用 d 命令查看方式如下:
d fff0:0 ff
我发现日期从 FFF0:00F5 地址开始,那么我们尝试做修改,但是改不了,
应该是属于 ROM,只读;
4: 向 B810:0000 这段内存写地址,会发现屏幕有新的图案出现,据说这部分是 显存的空间?不清楚唉,但是我发现用 d 命令查看这部分内存的时候,我之前 对这段内存的改变似乎是没有改变的呢?不太懂; 这道题参考了别人的链接: https://www.songbingjia.com/shida/show-212548.html
总结
下一章准备进入寄存器(内存访问)的章节了,很期待,明天再看吧! 一路走来,真的很有意思,终端安全这块,一步一步来,成为大牛只是时间 问题罢了。