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距离设置的刚好一样, 修改任何一个部分都有可能出错。