按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
在循环体中也可以用 ntinue伪指令忽略以后的指令,遇到 ntinue伪指令时,不管下面还有没有其他循环体中的指令,都会直接回到循环头部开始执行。
同样,为了深入了解MASM编译器把循环伪指令变成了什么,下面对比一段源程序和反汇编后的代码。首先是源程序:
。while eax 》 1
mov esi;1
。break 。if ebx
ntinue
mov esi;2
。endw
。repeat
mov esi;1
。break 。if !ebx
ntinue
mov esi;2
。until eax 》 1
。repeat
mov esi;1
。break
。untilcxz
以下是反汇编后的代码:
; 。while 第一个循环开始
:00401000 EB10 jmp 00401012
:00401002 BE01000000 mov esi; 00000001
:00401007 0BDB or ebx; ebx
; 。break 。if ebx
:00401009 750C jne 00401017
; ntinue
:0040100B EB05 jmp 00401012
:0040100D BE02000000 mov esi; 00000002
; 。while eax 》 1
:00401012 83F801 cmp eax; 00000001
:00401015 77EB ja 00401002
; 。repeat 第二个循环开始
:00401017 BE01000000 mov esi; 00000001
; 。break 。if !ebx
:0040101C 0BDB or ebx; ebx
:0040101E 740C je 0040102C
; ntinue
:00401020 EB05 jmp 00401027
:00401022 BE02000000 mov esi; 00000002
; 。until eax 》 1
:00401027 83F801 cmp eax; 00000001
:0040102A 76EB jbe 00401017
; 。repeat 第三个循环开始
:0040102C BE01000000 mov esi; 00000001
; 。break
:00401031 EB02 jmp 00401035
; 。untilcxz
:00401033 E2F7 loop 0040102C ;注意这里是loop指令!
对比伪指令和翻译成的实际指令,可以对循环的伪指令有更好的理解:。break翻译成一个跳转指令跳到循环结束的地方,ntinue是一个无条件跳转指令跳到循环开始的地方,。while是先比较条件再执行循环体,而 。repeat是先执行循环体再比较条件的。
对指令的分析中可以发现,。while/。endw和 。repeat/。until循环没有使用loop指令的优势,因为loop指令可以自动递减ecx的值来控制循环,不使用loop将会在循环体内多设置一条参数递减的指令,但不用loop指令的好处是带来更多的灵活性。当然,为了弥补这个缺陷,使用 。repeat/。untilcxz伪指令,编译器将会指定用loop指令来完成循环,当然,在这种用法中,程序员必须在循环开始前正确设置ecx的值。
如果又想用loop指令来构成循环又要使用条件表达式怎么办,这时同样可以在 。untilcxz伪指令后加条件测试语句,只不过这时候有很大的限制,第一只能是单个条件表达式,不能用&&或||来构成多项表达式了;第二即使是单个表达式中,也只能用或!=操作符,不能用其他比较大小的操作符,因为这时编译器的翻译方式是在一个比较指令后使用loopz或loopnz来构成循环,这个指令不能测试其他标志位。
在分支和循环的伪指令反汇编后可以发现,在使用》、》=、