8086CPU寻址范围的思考与研究
文章作者:duckgaga
给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为()到()?
这个小题的关键点在于,求出偏移的变化范围,再利用公式“段地址*16+偏移地址=物理地址”即可求得CPU的寻址范围。
关于这个小题的偏移变化范围,据我所知,好像有两种,一个是0~FFFFH,另一种则是0~15。那么两种答案到底谁对谁错呢?或者说,哪一个答案更加合理呢?为此,笔者设计了一个实验对此进行测试,具体情况如下:
一、设计思路:
两个答案中,一个是0~15,另一个是0~FFFFH,两个答案中都包含0~15这个部分,因此只要验证超出15部分(即16~FFFFH)能否正确寻址,就可以达到检测的目的。如果偏移使用16~FFFFH范围内的值进行寻址时出错,则说明答案0~FFFFH是不合理的;反之亦然。
二、实现方案介绍:
1)背景知识:在系统中,0:200h~300h空间的内容为空,值默认为0,即是没有值的。而系统1000:0~1000:200h空间的内容也为空,值也默认为0。这一点可自行验证,方法是进入CMD后,输入debug回车,然后分别用d 0:200和d 1000:0查看即可。
2)方法步骤:
i.在0:200h~300h空间的内容为空,我们先给从0:200H开始的16个字节赋值,值分别是0,1,2……,15.即从0:200h~20fh的值分别为0~15;
ii.设置DS,ES的段值为0001H,分别设置SI,DI初始值为0fff0h,1f0h。通过公式“段地址*16+偏移地址=物理地址”可以得知,ds:si初始时指向的物理地址为10000H,而es:di初始时指向的物理地址则为00200H,es:di与0:200H所指向的物理地址是相同的。
iii.将ds:si所指向物理地址开始的16个内存单元中的内容复制到es:di所指向的物理地址开始的16个内存单元中,这其中复制了16个字节。复制完毕后0:200h开始的16个内存单元中的内容应该跟ds:si所指向的内存单元中的值一样,即为0.
iv.在debug跟踪观察ds,es,si,di的值,并且看程序是否能够正确执行。
三、测试程序的代码:
assume cs:code
code segment
start:
mov cx,16
mov ax,0
mov es,ax
mov si,200h
s: mov es:[si],al
inc al
inc si
loop s ;将0:200h开始的16个内存单元的值设置为0~15.
mov ax,0001
mov ds,ax
mov es,ax ;设置ds,es段值都为0001H
mov si,0fff0h
mov di,1f0h
mov cx,16
cld
rep movsb ;将ds:si指向开始的16个内存单元复制到es:di所指向的16个内存单元中
mov ax,4c00h
int 21h
code ends
end start
编译情况:编译时没有提示出错,成功通过编译和连接。
四、debug跟踪情况
1.装载test.exe后:
-u
0B68:0000 B91000 MOV CX,0010
0B68:0003 B80000 MOV AX,0000
0B68:0006 8EC0 MOV ES,AX
0B68:0008 BE0002 MOV SI,0200
0B68:000B 26 ES:
0B68:000C 8804 MOV [SI],AL
0B68:000E FEC0 INC AL
0B68:0010 46 INC SI
0B68:0011 E2F8 LOOP 000B
0B68:0013 B80100 MOV AX,0001
0B68:0016 8ED8 MOV DS,AX
0B68:0018 8EC0 MOV ES,AX
0B68:001A BEF0FF MOV SI,FFF0
0B68:001D BFF001 MOV DI,01F0
0B68:0020 B91000 MOV CX,0010
0B68:0023 FC CLD
0B68:0024 F3 REPZ
0B68:0025 A4 MOVSB
0B68:0026 B8004C MOV AX,4C00
0B68:0029 CD21 INT 21
2.在开始跟踪运行test.exe之前,先查看内存0:200h处的内容:
-d 0:200
0000:0200 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0210 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0220 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0230 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0240 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0260 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0270 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
由此可以看出,程序执行前,0:200开始的内容为空。
3.直接用g 13命令,使程序执行到mov ax,0001处停止(此时mov ax,0001并未执行,它是下一条待执行的指令),则有:
-g13
AX=0010 BX=0000 CX=0000 DX=0000 SP=0100 BP=0000 SI=0210 DI=0000
DS=0B58 ES=0000 SS=0B68 CS=0B68 IP=0013 NV UP EI PL NZ AC PO NC
0B68:0013 B80100 MOV AX,0001
4.此时,我们再去查看0:200h处的内容,按照预计,0:200H开始的16个内存单元中的内容应该被修改了,好,我们此时用d 0:200命令进行查看,结果为:
-d 0:200
0000:0200 00 01 02 03 04 05 06 07-08 09 0A 0B 0C 0D 0E 0F ................
0000:0210 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0220 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0230 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0240 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
由上面,我们可以清楚地看到,0:200h~20fh处的内容如我们所想的,被修改了。它们的值分别是0,1……14,15.
5.好,我们继续下一步,用g 20命令使程序直接运行至mov cx,16处停止,此时,我们的程序应该已经执行完了给ds,es,si,di赋值。
-g20
AX=0001 BX=0000 CX=0000 DX=0000 SP=0100 BP=0000 SI=FFF0 DI=01F0
DS=0001 ES=0001 SS=0B68 CS=0B68 IP=0020 NV UP EI PL NZ AC PO NC
0B68:0020 B91000 MOV CX,0010
由上可以看到,ds,es分别被设置为0001,而si,di分别被设置为fff0,01f0。
6.经过给ds,es,si,di赋值后没有出错,说明偏移大于15时是合法的(此时SI,DI的内容为偏移),好,我们继续下步,看程序是否能成功运行。我们用g 26命令,使程序直接运行止mov ax,4c00h处停止(中间的rep movsb是循环执行的,为避免烦琐,故直接跳至此处),
-g 26
AX=0001 BX=0000 CX=0000 DX=0000 SP=0100 BP=0000 SI=0000 DI=0200
DS=0001 ES=0001 SS=0B68 CS=0B68 IP=0026 NV UP EI PL NZ AC PO NC
0B68:0026 B8004C MOV AX,4C00
我们可以看到ds,es的内容还是0001,没有改变,即段地址的值没有发生改变。而si,di在加上0fh之后,分别变为0000h,0200h了。
7.程序执行到mov ax,4c00h处时,此时程序已经完成了将DS:SI指向内存单元开始的16个字节复制到ES:DI所指向内存单元的指令。我们再来查看结果,用d 0:200命令进行查看,看其中的内容是否如我们所想,又重新变为空了(因为1000:0h开始处的内容为空,复制到0:200h处后,0:200h的数据被覆盖,因此变成与1000:0h处的内容一样,即为空,值为0):
-d 0:200
0000:0200 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0210 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0220 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0230 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0240 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
0000:0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
大家可以清晰地看到:0:200h~20fH处的内容又全部变成0了!说明此程序成功执行了!
这也就说明,在给定段地址为0001H的情况下,仅通过变化偏移地址寻址时,使用16~ffffH范围内的偏移(这里我们分别使用了0fff0~0ffffh和1f0~1ffh)进行寻址是合法的,也即偏移地址的变化范围仍然为0~ffffH,而不会被局限为0~15.
五、结论
OK,我们通过上面的实验证实偏移地址的变化范围仍然是0~FFFFH的。但是题目要求的是CPU的寻址范围,即求其物理地址范围。因此,我们还得用“段地址*16+偏移地址=物理地址”这个公式进行求解一次。
∵段地址=0001,偏移地址变化范围为0~FFFFH,由“段地址*16+偏移地址=物理地址”有:
物理地址=0001*16+0~FFFFH
=00010H+0~FFFFH
=00010~1000FH
综上所述,我个人认为,检测2.2的第一小题的答案应为(00010H)到(1000FH)。
六、题外探讨
那么,许多人以为问题到此已经解决了,但大家是否会想想:为什么有人会得出偏移变化范围为0~15的答案呢?
个人见解:
我想之所以有人会得出0~15的答案来,这与是否真正理解了“段地址*16+偏移地址=物理地址”的本质含义密切相关的。
好,我们进行一次错误(个人认为是错误的,请指教)的思维过程:
1)由“给定段地址0001H,仅通过变化偏移地址进行寻址”+“段地址*16+偏移地址=物理地址”有:
段地址*16=0001H*16=00010H
2)又由关键字眼“给定段地址”,“仅通过变化偏移地址进行寻址”则有:
CPU寻址的范围只能从00010H~0001fH,因为如果再加1的话,就变为00020H了,就不再是00010h这个“给定的段地址”了,就不符合题目的要求了!所以答案应为:0到15.
OK,错误思维旅程结束,我们跳出来(不要掉进这个陷阱出不来了,否则我罪过就大了)探讨上面错误思维产生的原因。不难看出,这是由于对“段地址*16+偏移地址=物理地址”的本质含义没有真正理解,并且没有真正理解“段”概念、物理地址及其之间关系的缘故。
七、结语
王爽老师的《汇编语言》看起来虽然简单,但是里面讲述的都是一些原理性的、本质性的东西,因此希望大家认真理解、深入研究和探讨,只有这样才能真正达到学习的目的。就像本题,虽然“段地址*16+偏移地址=物理地址”这个公式看起来是很简单,但是又有多少人掉进了这个“陷阱”?
八、题外话
学完一遍,感觉轻松了不少,因为不用再像以前一样,不再急着往下学(以前就算不赶进度,但还是要考虑时间关系的),所以就想找点事做。所谓“三人必有我师”,故决定从第一章开始,把论坛里所有章节的帖子都看完,然后再逛别人的博客,呵呵。这几天都在逛论坛,今天把第1章的所有帖子看完了。感觉这几天学习到了不少东西,大多是与课本学习密切相关,但课本上没有的基础类的东西或者是从课本上来,但又高于课本的一些思考类的东西。
虽然是重新回头读《汇编语言》这本书,但还是从中发掘到了许多东西,因此速度愈放愈慢(所以更新博客会比较慢),自己也逐渐感到有一种研究性学习的精神在自己身上慢慢产生,虽然是一点点,但是有了开头,只要坚持,一定会有所成的。
每当看到谁谁说自己速度多快,一下子看了几十页时,心里不知作何感想。如果他真的是个牛人,我羡慕他,佩服他;但是如果单纯是为了进度而不求甚解的话,我又会为其担心,这样子学下去又能学到什么实质性的东西呢?不管怎么都好吧,希望大家都能克制浮躁的心情,同时希望学得快的人都是比我理解能力强的人。
虽然自己有点笨,不像他们那样能一飞冲天,但是贵在坚持吧。许三多说得对:“不抛弃,不放弃!”
发表日期:08/06/26 00:00
网友评论(1)
【游客 发表于:18/02/02 21:08】
妙哉
当前1/1页 首页 上一页下一页 尾页