目录

跳转的分类

cmp指令

尝试:使用CMP指令写一个简单的循环

条件跳转


现在我们终于向更加复杂的程序迈出更加坚实的一步,下面我们来系统的聊聊跳转这个事情!

跳转的分类

汇编语言中的条件执行是通过几个循环和分支指令来完成的。这些指令可以更改程序中的控制流。在两种情况下观察到条件执行

  • 无条件跳转 - 这是通过JMP指令执行的。条件执行通常涉及将控制权转移到不遵循当前执行指令的指令的地址。控制权的转移可以是前进的(执行新的指令集),也可以是后退的(重新执行相同的步骤)。

  • 有条件跳转 - 这取决于条件由一组跳转指令j <condition>执行。条件指令通过中断顺序流程来转移控制,而它们通过更改IP中的偏移值来进行控制。

换而言之,一个是来了就跳转,看到jmp就三七二十一直接跑到label所在的地方继续执行。另一方面则是需要一定的条件——比如说必须小于7了才能跳转,等等!

cmp指令

cmp指令比较两个操作数。它通常用于条件执行中。该指令基本上从另一个操作数中减去一个操作数,以比较操作数是否相等。它不会干扰目标或源操作数。它与条件跳转指令一起用于决策。

cmp destination, source

cmp比较两个数字数据字段。目标操作数可以在寄存器中或在内存中。源操作数可以是常量(立即数)数据,寄存器或内存。

cmp DX, 00  ; 将DX值与0进行比较
je  L7      ; 如果等于,则跳转到标签L7
...
L7: ...  

cmp 通常用于比较计数器值是否已达到需要运行循环的次数。考虑以下典型条件-

INC     EDX
CMP     EDX, 10 ; 比较计数器是否达到10
JLE     LP1     ; 如果它小于或等于10,则跳转到LP1

换而言之,现在我们可以写循环了

尝试:使用CMP指令写一个简单的循环

程序需要循环9次打印一个字符串:I am looping lol,当然,前面需要加上当前打印剩余的次数:

charliechen@Charliechen:~/demo/demo10$ ./result 
9: I am looping lol
8: I am looping lol
7: I am looping lol
6: I am looping lol
5: I am looping lol
4: I am looping lol
3: I am looping lol
2: I am looping lol
1: I am looping lol

提示:哈?这个简单,不需要提示 :),非得要提示的话,那就是好好看看上面的阐述

答案如下:

​
​
​
; help announce a typical string
%macro ANNOUNCE_STRING 2
    %1 db %2
    %1_LEN equ $ - %1
%endmacro
​
; fast use of common value
%define MY_STDOUT       1
%define MY_SYS_WRITE    4
%define MY_STDIN        0
%define MY_SYS_READ     3
​
; print string in a simple way
%macro PRINT_STRING 2
    mov edx, %2
    mov ecx, %1
    mov ebx, MY_STDOUT
    mov eax, MY_SYS_WRITE
    int 0x80
%endmacro
​
%macro EASY_PRINT_STRING 1
    PRINT_STRING %1, %1_LEN 
%endmacro
​
%macro EXIT 0
    mov ebx, 0
    mov eax, 1
    int 0x80
%endmacro
​
section .data 
    PR_TIMES equ 9
    ANNOUNCE_STRING TELL_TIMES, {": "}
    ANNOUNCE_STRING BUFFER, {"I am looping lol", 0xA}
​
section .bss
    current_times resb 1
    current_times_for_print resb 1
​
section .text
    global _start
​
_start:
    mov ax, PR_TIMES
    mov [current_times], ax
​
_do_loop:
    mov ax, [current_times]
    add ax, '0'
    mov [current_times_for_print], ax
    PRINT_STRING current_times_for_print, 1
    EASY_PRINT_STRING TELL_TIMES
    EASY_PRINT_STRING BUFFER
    dec byte [current_times]
    cmp byte [current_times], 0
    jne _do_loop                ; jmp out! if the counter goes 0
    EXIT

Bonus: 你可以试试看让用户控制循环次数?

条件跳转

如果在条件跳转中满足某些指定条件,则控制流将转移到目标指令。根据条件和数据,有许多条件跳转指令。以下是用于算术运算的有符号数据的条件跳转指令-

指令描述标志测试
JE/JZ跳转等于或跳转零ZF
JNE/JNZ跳转不等于或跳转不为零ZF
JG/JNLE跳转大于或跳转不小于/等于OF,SF,ZF
JGE/JNL跳转大于/等于或不小于跳转OF,SF
JL/JNGE跳转小于或不大于/等于OF,SF
JLE/JNG跳少/等于或跳不大于OF,SF,ZF

以下是对用于逻辑运算的无符号数据使用的条件跳转指令-

指令描述标志测试
JE/JZ跳转等于或跳转零ZF
JNE/JNZ跳转不等于或跳转不为零ZF
JA/JNBE跳转向上或不低于/等于CF,ZF
JAE/JNB高于/等于或不低于CF
JB/JNAE跳到以下或跳到不高于/等于CF
JBE/JNA跳到下面/等于或不跳到上方AF,CF

以下条件跳转指令有特殊用途,并检查标志的值-

指令描述标志测试
JXCZ如果CX为零则跳转没有
JC如果携带则跳CF
JNC如果不携带则跳转CF
JO溢出时跳转OF
JNO如果没有溢出则跳转OF
JP/JPE跳校验或偶校验PF
JNP/JPO跳转无奇偶校验或跳转奇偶校验PF
JS跳跃符号(负值)SF
JNS跳转无符号(正值)SF

笔者目前建议是:如果不是在优化阶段或者是确实需要,可以不理睬上面的绝大多指令!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部