曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4751|回复: 2
打印 上一主题 下一主题

循环及循环指令

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-12-13 15:48:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在 IA-32 平台上提供了在汇编语言程序中实现循环的简单的机制:循环指令

循环指令使用 ECX 寄存器作为计数器并且随着循环指令的执行自动递减它的值。下表为循环指令说明:
指令
描述
LOOP
循环直到ECX寄存器为零
LOOPE/LOOPZ
循环直到 ECX 寄存器为零,或者没有设置ZF标志
LOOPNE/LOOPNZ
循环知道ECX寄存器为零,或者设置了ZF标志

LOOPE/LOOPZ 和 LOOPNE/LOOPNZ 提供了监视零标志的附加功能。
这些指令的格式是:
loop  address
上面,address 是要跳转到的程序代码位置的标签名称。不幸的是,循环指令只支持 8 位偏移量,所以只能进行短跳转。

循环开始之前,必须在 ECX 寄存器中设置执行迭代的次数值。通常会像下面这样的代码:
   < code before the loop >
movl $100, %ecx
loop1:
   < code to loop through >
    loop loop1
   < code after the loop >
需要注意的是,循环内部的代码要小心对待,要防止 ECX 寄存器被修改了,这样就会影响循环的操作。
循环的额外好处在于它们递减 ECX 寄存器的值,而不影响 ELFAGS 寄存器的标志位。当 ECX 寄存器值到达零时,零标志不会被设置。

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
沙发
 楼主| 发表于 2009-12-13 17:18:08 | 只看该作者

循环范例

测试程序
.section .data
output:
    .asciz "The value is: %d\\n"

.section .text
.globl _start
_start:
    movl $100, %ecx
    movl $0, %eax
loop1:
    addl %ecx, %eax
    loop loop1
    pushl %eax
    pushl $output
    call printf
    add $8, %esp
    movl $1, %eax
    movl $0, %ebx
    int $0x80
运行输出
$ ./loop
The value is: 5050
说明
LOOP 指令用于持续地循环调用 ADD 指令,直到 ECX 的值为零。

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
板凳
 楼主| 发表于 2009-12-13 19:05:18 | 只看该作者

防止 LOOP 灾难

在上面的程序中,将 ECX 寄存器设置为零会怎么样呢?实际的运行结果是:
$ ./loop
The value is: -2147483648
这不是正确答案。问题的原因在于 LOOP 指令的行为方式。当执行 LOOP 指令之前 ECX 的值已经为零,LOOP 指令会把它递减 1,使它成为 -1 。因为这个值非零,所以 LOOP 指令继续执行下去,循环回到低能给的标签。循环最终会在寄存器溢出时退出,并且显示错误的值。解决这个问题的一个方便方法是,使用 JCXZ 指令; JCXZ 指令为应用程序提供某种初步的错误检查:
.section .data
output:
    .asciz "The value is: %d\\n"

.section .text
.globl _start
_start:
    movl $0, %ecx
    movl $8, %eax
    jcxz done
loop1:
    addl %ecx, %eax
    loop loop1
done:
    pushl %eax
    pushl $output
    call printf
    movl $1, %eax
    movl $0, %ebx
    int $0x80
运行输出
$ ./loop
The value is: 8
在循环开始前添加了单一指令 --- JCXZ 。并且使用单一标签引用指令码的结尾。现在,如果 ECX 寄存器包含零值,JCXZ 就会捕获到它,并且立即输到输出段。运行程序结果显示这样确实解决了问题。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-3 12:44 , Processed in 0.098641 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表