汇编网首页登录博客注册
lwbfq的学习博客
博客首页博客互动【做检测题】论坛求助

我的博客

个人首页 |  我的文章 |  我的相册 |  我的好友 |  最新访客 |  文章收藏 |  论坛提问 |  友情链接 |  给我留言  
图片载入中
  •  不去想接下来的瞬间可能发生的事,只体味捕捉那瞬间的心情,这才是幸福的人。
  • 『姓名』:不告诉你
  • 『性别』:保密『发送消息
  • 个人说明:说汇编难学,我不信。别人说的不算,我得试验一下。
  • 详细信息『加为好友』
学习动态
友情链接

[2008-10-22 16:46] 检测点13.1(1)转移最大位移求解

一个小小的问题,耗费了我近一天的精力,不容易呀。看了做过这个检测点的学习者的答案,发现很不一致,有很多人对自己的答案都表示怀疑。也有很多人对自己的答案很自信,但是有的答案根本就是错的,因为在debug下就能证明。下面,贴出我的劳动成果给大家看看,我的结论是65529(FFF9H)。
首先这里说的是模拟loop指令的功能,这里的“模拟”应该理解为和loop指令的表现形式上是一致的,但是有一定区别,然后我们再来看这个问题。
对这道题基本有四种看法:
第一种人认为:既然是模拟loop指令的功能,那么就应该是和loop指令功能一模一样,既然loop指令的最大转移位移为[-128~127],很容易就 得出int 7ch的最大位移也是一样,即-[128~127]。如果这样想,那这个问题出的就没有多大的意义。
第二种人认为:这里存放跳转范围的寄存器是16位(BX),并且因为转移有向前转移和向后转移,根据以往jmp near ptr  等近转移指令的经验,这里的变化范围应该在[-32768~32767]之间。 
第三种人认为:这与以前学习的跳转指令没有太大关系,要想得到具体范围得看具体实现。由于BX的最大值为65535,所以7ch所能进行的最大转移位移为65535。
前三种人大部分都是通过想象得出的结论,然而还有些人根据试验结果得出了更深一层的结论。
我刚做这道题时,很随意的就认为答案应该是FFFFH,但是又感觉没有什么理论依据,于是打开别人的博客,才发现了这五花八门的结果。很多人都对自己的答案不太自信。发现有个人的答案是[-32768~32767],忽然感觉我的答案好像错了(因为后面的评论有人说答案是正确的),但是我始终感觉BX能够表示比32767更大的数,因此转移位移应该比它要大,于是开始试验,由于向上跳转理解起来有困难(总要和有符号数联系起来,可能是个人问题),就写了个简单的向下跳转的例子。
assume cs:code
code segment
start:
mov bx,offset se - offset s
mov cx,3
int 7ch
s:
db 0ffe0H dup(0);
se:
nop
code ends
end start
结果能够正确执行,说明转移位移能够超过32767,所以[-32768~32767]的结果是错误的,于是又写了一个向上跳转的例子,跳转同样正常。
程序如下:
assume cs:code 
code segment
start:  mov bx,offset s - offset se
mov cx,3
s:      
db 0ffe0H dup(0);
int 7ch
se:
nop
code ends
end start
很多人做题这道题时,都受到了以前所学转移指令的影响,没有认真分析7CH的执行过程,段转移和近转移都是根据位移进行计算的,而7CH中实现就是直接修改IP地址,我看了书的附注3,介绍了编译器对jmp指令的处理方法,实际上它是对向上向下转移的最大位移作了限制(实现方法不一样)。
在这里我们假设所进行的都是无符号数运算,可以知道offset s - offset se应该小于0,但实际结果是进行了借位,而使结果与真实结果不符。相当于offset s最高位再加一位变为1, 而offset se最高位也加一位变为0,然后相减得到的值。
当程序执行int 7ch后,此时栈中存放的原ip地址为offset se,而中断程序执行时又会在原有ip地址的基础上加上转移位移即(offset s - offset se),那么最终的值为offset se + (offset s - offset se) = offset s。仍然是原来程序中标号s处,所以能正确返回。而实际的位移就是|offset s - offset se|(绝对值),即offset se - offset s。那么这个绝对值最大为多少呢?按上面的程序所写最大值就是64K(65536)-1(nop指令)-6(前两条指令所占空间)=65529;
所以我的答案是:FFF9H(65529),个人感觉只要能够理解到趋紧于FFFFH(65535)就可以了。在这里,向上跳转感觉理解起来非常费劲,总想跟有符号数运算联系在一起,结果是越想越乱,后来想到上述方法来解释,感觉很好理解,不知有没有漏洞。

看了abcrazy的分析,我发现我的结论有点问题,最大位移应该是FFFFH,程序如下:
assume cs:code
code segment
start:
mov bx,offset start - offset s
db 65530 dup(0)
int 7ch
s:nop
code ends 
end start
如果
assume cs:code
code segment
start:
mov bx,offset start - offset s
db 65531 dup(0)
int 7ch
s:
code ends 
end start

那么s标号的偏移就为0了。
评论次数(6)  |  浏览次数(1831)  |  类型(汇编作业) |  收藏此文  | 

[  fairyhuang   发表于  2008-10-24 21:46  ]

研究的真深啊,佩服:)

[  lwbfq   发表于  2008-10-25 11:18  ]

不知道哪个答案是对的,只有自己试着摸索了 呵呵

[  游客   发表于  2009-05-11 22:19  ]

我想过了,还是bx表示的数值范围,因为两个标号都同在一个代码段中,也就是两个数64k范围内做减法运算,因为bx中的值是正值还是负数,可以有我们说了算,但总之还是16比特数;举个例子说明吧,从0-9之间任意选两个值做差运算,你说得到的范围是多少呢?我觉得这题就是这个意思。明白这点就好了!

[  游客   发表于  2010-12-26 14:42  ]

"按上面的程序所写最大值就是64K(65536)-1(nop指令)-6(前两条指令所占空间)=65529; "楼主这里我觉得有点问题。如果像这样分析,我觉得就不用减nop指令跟前两条指令所占的空间了。除此之外,我觉得向上或者向下跳转的最大位移应该还跟执行int指令时IP入栈得值。反正向上向下能转移的最大位移加起来就是65535.一己之见,还望指正。

[  游客   发表于  2011-03-26 20:51  ]

你向下跳转的例子显然不符合题意,用7ch向下跳转那就相当与jmp指令的效果了(没有循环),要知道loop指令中loop一定要在标号s的后面!.
如果这个题意义在于说7ch能实现的最大位移,那答案当然是bx能保存的最大值65535,但实际应用7ch去转移时,那就要考虑向上跳和向下跳(向下跳不会循环的哦!),这时由于考虑了向上和向下那偏移范围在[-32768~32767],答案就是32768;
如果题目意思说,用7ch实现loop指令的话,就没必要讨论向下跳,它只能是向上偏移,偏移量必为负数,答案为32768
loop指令只能短转转移,处理方式仍是偏移,

[  rotapple   发表于  2011-08-16 15:00  ]

感觉只要理解了跳转的过程及ip修改的方式。就不难理解了。

 
 请输入验证码  (提示:点击验证码输入框,以获取验证码