汇编语言 -> 实验8

assume cs:codesg 
codesg segment 
             mov ax,4c00H 
             int 21H 
start:  
             mov ax,0 
s:     
             nop 
             nop 
             mov di,offset s 
             mov si,offset s2 
             mov ax,cs:[si] 
             mov cs:[di],ax 
s0: 
            jmp short s 
s1: 
            mov ax,0 
            int 21H 
            mov ax,0 
s2: 
            jmp short s1 
            nop 
codesg ends 
end start 

说实话这个程序的却不好懂,翻了好多博客才渐渐搞懂,下面我把自己解题思路分享给大家:

一开始做这题,我的关注重点只是放在了两个jmp语句处,毕竟这一章讲的都是与jmp有关的东西,
对于中间的s 段就一带而过了,觉得只是把一些无关紧要的数据移入寄存器罢了。

但做到后面才发现,原来一直想不通的一个点,就是因为忽视了中间这段东西的内容(当然这是后
话了,我会在接下来的解析中告诉你为什么)

好,假设我只是一带而过的看完S段代码,接下来就是进行 s0: jmp short s

然后下一步又回到S,重复操作,死循环????

直觉告诉我这题没那么简单。

果然把它编写成一个EXE文件后用DEBUG执行是可以正常运行的。
并且注意到,在执行了s0处的 jmp short s之前,一切都是符合我认知的;只不过在执行了  jmp short s后,
紧接着又执行了一次jmp 指令,这就很令人不解,明明 s 位置的指令是 nop应该什么也不干,重复以上操作
才对???

我把两次 jmp 对应的机器指令记录下来,发现都是 EBF6

既然这样,那就先按自己的思路来,把无关东西去掉,逐个逐个排除

我呢,先把s1部分删除了,结果再次运行的时候出错了!!!!

不应该,程序里面没有用到s1的地方,删了应该不会有影响啊......

一定是哪里出错了,难道是先前忽略掉的s段中的内容???

再次回看,发现是把 s2 中的一条指令复制到 s 处

但是,复制过去的也是跳到s1啊...

想不通,查博客,发现是自己对jmp语句理解不到位:
jmp指令是同过ip + 位置差移动的,而不是直接给出像0000:0001这样目标地址移动;

换句话说,我只告诉你从当前方向要往上还是往下走多少步,却没有告诉你具体是门牌号是多少。

那么自然的,从s2中复制到s 处的指令的作用,也只是告诉ip,当它指向s时,要向上或者向下走多少步,
那么具体走多少步,那就是s2与s1之间的距离,已经给好了。

很自然的:为什么之前把s1删了程序不能正常结束?因为删掉的部分使得s1与s2之间的间位差减少,
s不能跳到mov ax, 4c00h处,也就不能正常结束。
为什么两次jmp 的机器码全为 EBF6?s1,s2之间的间位差为10字节,那么是s2跳到s1往上跑,也就是-10B,
那么对应的补码就为F6, EB是jmp指令对应机器码。两次一样原因就很好解释了,本来就是复制过去的嘛~

其实,再回看这道题的时候,不得不惊叹王爽老师设计之妙啊!巧妙运用jmp的跳转原理,环环相扣,就像
s2到s1的距离 和 s到 mov ax, 4c00h距离设置的刚好一样, 修改任何一个部分都有可能出错。

猜你喜欢

转载自blog.csdn.net/desporado/article/details/80207428