再次循环将重复多少次?
mov bx,0
mov cx,0
again:
shr cx,1
inc bx
loop again
答案是16,但为什么?
当我们shl
shr
时,答案是:无限循环。为什么呢?
答案 0 :(得分:4)
有两种基本方法可以理解这样的问题:
请注意,这些基本相同;一个只是让机器做所有的工作,你只是看着魔术发生。如果您对汇编语言比较熟悉,那么在这样的简单情况下,您只需要方法#1即可。如果你只是在学习并且对骨骼里的感觉不太满意,那么“欺骗”并让调试人员帮忙就会非常有用。
由于Stack Overflow上没有可用的调试器(尽管我仍然鼓励你自己尝试这个),让我们使用我们的大脑采用手动方法:
mov bx,0 mov cx,0
显然,这会将bx
和cx
寄存器初始化为0。
请注意,没有真正的汇编程序员会像这样编写代码。他们总是写
xor bx, bx
xor cx, cx
这具有相同的效果(任何数字XOR本身都是0),但它更快并且使用更少的代码字节。
在循环内部,此代码运行:
shr cx,1 inc bx
SHR
将目标操作数(在本例中为cx
)向右移动源操作数(在本例中为常量1
)。回想一下,右移相当于除以2,但速度更快。因此,这与cx = cx >> 1
或cx = cx / 2
相同。
INC
将其操作数增加1.它与bx = bx + 1
相同。
loop again
{x}程序集编程中LOOP
指令不再广泛使用,因为它相对较慢。关于你使用它的唯一时间是小代码比快速代码更重要。因此,我必须查看它的作用。您可以通过Google搜索助记符名称和“x86”来查找此信息,或者您可以在英特尔的手册中找到它,或者您可以在x86标签维基中的材料中找到它,或者您可以在任何地方找到它您用于学习汇编语言编程的教科书/课程资料。我查了一下here,这是一个网站,其中包含使用Google发现的英特尔手册的在线转录。
结果是,LOOP
指令递减计数寄存器(cx
),并且如果cx != 0
则执行循环的另一次迭代。否则,如果cx == 0
,则会停止循环播放。
有了这些知识,你就应该能够“执行”你头脑中的代码。 bx
发生的事情是无关紧要的。唯一有趣的操作是那些影响cx
的操作。令人感兴趣的是,由于cx
从0开始,而0 >> 1
为0,LOOP
指令将减1,使其为-1在循环的第一次迭代之后。
对有符号值使用按位右移有点不寻常(通常是一个错误),但它是x86程序集中定义明确的操作(与C或C ++不同)。基本上,发生的情况是移位的位(在这种情况下,最后一位)消失,空位插槽用零填充。因此,右移1只会在最重要的位置放置0。 (并且,从技术上讲,它会将进位标志中的移位位置放,但这在此代码中无关紧要,因为没有测试进位标志。)
例如,6 >> 1 == 3
(0000 0110 >> 1 == 0000 0011
)。
现在,您应该充分理解这种行为,以便能够回答第二个后续问题。但是如果你需要提示,look up the behavior of the SHL
instruction。它是一个按位左移,相当于乘以2。
在这种情况下,代码将无限循环,因为cx
永远不会为0,这是LOOP
指令正在检查的条件!为什么会这样?因为LOOP
首先递减cx
,然后然后进行测试以查看它是否为零。正如Peter Cordes指出的那样,或许更好的思考方式是cx
是否可以是1. SHL
指令确保永远不会出现这种情况,{{1在cx
为0之后(在这种情况下SHL
会将其递减为-1并因此继续循环),或者> = 2(在这种情况下LOOP
将减少它到> = 1然后继续循环)。