汇编语言JMP和LOOP(转移)指令

  • 内容
  • 评论
  • 相关

默认情况下,CPU 是顺序加载并执行程序。但是,当前指令有可能是有条件的,也就是说,它按照 CPU 状态标志(零标志、符号标志、进位标志等)的值,把控制转向程序中的新位置。

汇编语言程序使用条件指令来实现如 IF 语句的高级语句与循环。每条条件指令都包含了一个可能的转向不同内存地址的转移(跳转)。控制转移,或分支,是一种改变语句执行顺序的方法,它有两种基本类型:

  • 无条件转移:无论什么情况都会转移到新地址。新地址加载到指令指针寄存器,使得程序在新地址进行执行。JMP 指令实现这种转移。
  • 条件转移:满足某种条件,则程序出现分支。各种条件转移指令还可以组合起来,形成条件逻辑结构。CPU 基于 ECX 和标志寄存器的内容来解释真 / 假条件。

JMP 指令

JMP 指令无条件跳转到目标地址,该地址用代码标号来标识,并被汇编器转换为偏移 量。语法如下所示:

JMP destination

当 CPU 执行一个无条件转移时,目标地址的偏移量被送入指令指针寄存器,从而导致迈从新地址开始继续执行。

JMP 指令提供了一种简单的方法来创建循环,即跳转到循环开始时的标号:

top:
    .
    .
    jmp top     ;不断地循环

JMP 是无条件的,因此循环会无休止地进行下去,除非找到其他方法退岀循环。

LOOP 指令

LOOP 指令,正式称为按照 ECX 计数器循环,将程序块重复特定次数。ECX 自动成为计数器,每循环一次计数值减 1。语法如下所示:

LOOP destination

循环目标必须距离当前地址计数器 -128 到 +127 字节范围内。LOOP 指令的执行有两个步骤:

  • 第一步,ECX 减 1。
  • 第二步,将 ECX 与 0 比较。

如果 ECX 不等于 0,则跳转到由目标给岀的标号。否则,如果 ECX 等于 0,则不发生跳转,并将控制传递到循环后面的指令。

实地址模式中,CX 是 LOOP 指令的默认循环计数器。同时,LOOPD 指令使用 ECX 为循环计数器,LOOPW 指令使用 CX 为循环计数器。

下面的例子中,每次循环是将 AX 加 1。当循环结束时,AX=5, ECX=0:

    mov ax,0
    mov ecx,5
L1:
    inc ax
    loop L1

一个常见的编程错误是,在循环开始之前,无意间将 ECX 初始化为 0。如果执行了这个操作,LOOP 指令将 ECX 减 1 后,其值就为 FFFFFFFFh,那么循环次数就变成了 4 294 967 296!如果计数器是 CX (实地址模式下),那么循环次数就为 65 536。

有时,可能会创建一个太大的循环,以至于超过了 LOOP 指令允许的相对跳转范围。下面给出是 MASM 产生的一条错误信息,其原因就是 LOOP 指令的跳转目标太远了:

error A2075: jump destination too far : by 14 byte(s)

基本上,在一个循环中不用显式的修改 ECX,否则,LOOP 指令可能无法正常工作。下例中,每次循环 ECX 加 1。这样 ECX 的值永远不能到 0,因此循环也永远不会停止:

top:
    .
    .
    inc ecx
    loop top

如果需要在循环中修改 ECX,可以在循环开始时,将 ECX 的值保存在变量中,再在 LOOP 指令之前恢复被保存的计数值:

.data
count DWORD ?
.code
    mov ecx, 100        ;设置循环计数值
top:
    mov count, ecx      ;保存计数值
    .
    mov ecx, 20         ;修改 ECX
    .
    mov ecx, count      ;恢复计数值
    loop top

循环嵌套

当在一个循环中再创建一个循环时,就必须特别考虑外层循环的计数器 ECX,可以将它保存在一个变量中:

.data
count DWORD ?
.code
    mov ecx, 100    ;设置外层循环计数值
L1:
    mov count, ecx  ;保存外层循环计数值
    mov ecx, 20     ;设置内层循环计数值
L2 :
    loop L2         ;重复内层循环
    mov ecx, count  ;恢复外层循环计数值
    loop L1         ;重复外层循环

提示:作为一般规则,多于两重的循环嵌套难以编写。如果使用的算法需要多重循环,则将一些内层循环用子程序来实现。

在 Visual Studio 调试器中显示数组

在调试期间,如果想要显示数组的内容,步骤如下:选择 Debug 菜单 -> 选择 Windows -> 选择 Memory -> 选择Memory 1。则出现内存窗口,可以用鼠标拖动并停靠在 Visual Studio 工作区的任何一边。还可以右键点击该窗口的标题栏,表明要这个窗口浮动在编辑窗口之上。

在内存窗口上端的 Address 栏里, 键入 & 符号和数组名称,然后点击 Enter。比如,&myArray 就是一个有效的地址表达式。内存窗口将显示从这个数组地址开始的内存块,如下图所示。

使用调试内存窗口显示数组

本文标题:汇编语言JMP和LOOP(转移)指令

本文地址:https://www.hosteonscn.com/5330.html

评论

0条评论

发表评论

邮箱地址不会被公开。 必填项已用*标注