zoukankan      html  css  js  c++  java
  • Ubuntu x86-64汇编(5) 控制指令

    控制指令 Control Instructions

    汇编的控制指令主要包含标签, 无条件跳转和有条件跳转几种

    标签 Label

    标签用于标记跳转的目的, 必须以字母开头, 后面跟着字母, 数字和下划线, 最后以冒号:结束
    yasm里的标签是区分大小写的

    无条件跳转 Unconditional Control Instructions

    格式

    jmp   <label>
    jmp   startLoop
    jmp   ifDone
    jmp   last
    

    条件跳转 Conditional Control Instructions

    条件跳转一般发生在一个比较指令之后, 比较的结果决定跳转是否执行. 比较指令的结果会存储在rFlag寄存器. 条件跳转要紧接着比较指令进行, 以免结果被其他指令修改.
    比较指令的格式

    cmp   <op1>, <op2>
    

    <op1> 和 <op2> 必须是同一尺寸且不能修改. 不能同时为内存. <op1>不能为立即数. 跳转指令je和jne对无符号数和有符号数同样适用. 但是其他的跳转指令会有区别, 适用于有符号数的有 jl, jle, jg, jge; 适用于无符号数的有 jb, jbe, ja, jae. 列表如下

    je    <label>   ; if <op1> == <op2>
    jne   <label>   ; if <op1> != <op2>
    jl    <label>   ; signed, if <op1> < <op2>
    jle   <label>   ; signed, if <op1> <= <op2>
    jg    <label>   ; signed, if <op1> > <op2>
    jge   <label>   ; signed; if <op1> >= <op2>
    jb    <label>   ; unsigned, if <op1> < <op2>
    jbe   <label>   ; unsigned, if <op1> <= <op2>
    ja    <label>   ; unsigned, if <op1> > <op2>
    jae   <label>   ; unsigned, if <op1> >= <op2>
    

    举例对于下面的判断语句
    if (currNum > myMax)
      myMax = currNum;

    ;先定义变量
    currNum  dq  0
    myMax    dq  0
    ; 代码为
        mov   rax, qword [currNum]
        cmp   rax, qword [myMax]    ;if currNum <= myMax
        jle   notNewMax             ;   skip set new max
        mov   qword [myMax], rax
    notNewMax:
    

    另一个例子
    if (x != 0) {
        ans = x / y;
        errFlg = FALSE;
    } else {
        ans = 0;
        errFlg = TRUE;
    }

    代码

    TRUE   equ 1
    FALSE  equ 0
    x      dd  0
    y      dd  0
    ans    dd  0
    errFlg db  FALSE
    ;
    ;
        cmp    dword [x], 0   ; if statement
        je     doElse
        mov    eax, dword [x]
        cdq
        idiv   dword [y]
        mov    dword [ans], eax
        mov    byte [errFlg], FALSE
        jmp    skpElse
    doElse:
        mov    dword [ans], 0
        mov    byte [errFlg], TRUE
    skpElse:
    

    这个例子中因为是带符号数, 所以使用了idiv和cdq.

    超出跳转范围 Jump Out Of Range

    一般来讲, 条件跳转的目标标签要在128byte以内, 如果超出的话就会出现jump out-of-range错误. 但是无条件跳转是没有这个限制的. 可以用以下的方法解决这个问题

        cmp   rcx, 0
        je    endOfLoop
        jmp   startOfLoop
    endOfLoop:
    

    用je + jmp 代替 jne, 就避免了条件跳转的限制

    枚举 Iteration

    这个控制指令用于枚举或循环. 一个基本的循环由一个计数器和一个顶上或底下的判断和跳转组成. 例如

    maxN  dq   30
    sum   dq   0
    ; 下面的代码用于计算从1到maxN的奇数之和.
    mov   rcx, qword [maxN]   ; loop counter
    mov   rax, 1              ; odd integer counter
    sumLoop:
        add   qword [sum], rax    ; sum current odd integer
        add   rax, 2              ; set next odd integer
        dec   rcx                 ; decrement loop counter
        cmp   rcx, 0
        jne   sumLoop
    

    在这个例子中, rcx 用于循环的计数, rax用于存储当前循环的奇数, 用1初始化并每次加2.
    另外我们也可以用loop指令来实现, 其格式如下, 执行时会递减rcx寄存器的值, 与0比较, 当不等于0时跳转(到开始处再次循环)
    loop   <label>
    之前的代码可以用loop改写为:

    mov   rcx, qword [maxN]  ; loop counter
    mov   rax, 1             ; odd integer counter
    sumLoop:
    add   qword [sum], rax   ; sum current odd integer
    add   rax, 2             ; set next odd integer
    loop  sumLoop
    

    因为循环中会改写并检查rcx寄存器, 如果未初始化rcx寄存器, 将导致未知的循环次数. loop指令在编程中很有用, 但是受限于rcx寄存器. 如果需要多层的loop, 需要在循环内外进行rcx当前值的保存和恢复.

    代码例子 平方数求和 Sum of Squares

    ;  Simple example program to compute the
    ;  sum of squares from 1 to N.
    ; **********************************************
    ;  Data declarations
    section   .data
    ; ----
    ;  Define constants
    SUCCESS   equ  0       ; Successful operation
    SYS_exit  equ  60      ; call code for terminate
    
    ;  Define Data.
    n         dd   10
    sumOfSquares  dq  0
    
    ; *******************************************************
    section   .text
    global    _start
    _start:
    ; ----
    ;  Compute sum of squares from 1 to N.
    ;  Approach:
    ;    for (i=1; i<N; i++)
    ;      sumOfSqaures += i^2;
    mov   rbx, 1           ; i
    mov   ecx, dword [n]
    
    sumLoop:
    mov   rax, rbx         ; get i
    mul   rax              ; i^2
    add   qword [sumOfSquares], rax
    inc   rbx
    loop  sumLoop
    
    ; ----
    ;  Done, terminate program.
    last:
    mov   rax, SYS_exit   ; call code for exit
    mov   rdi, SUCCESS    ; exit with success
    syscall
    

    .

  • 相关阅读:
    4.2 省选模拟赛 流浪者 容斥dp
    4.2 省选模拟赛 旅行路线 广义SAM
    4.2 省选模拟赛 摆棋子 网络流 最大流/上下界最小流
    bzoj 4316 小C的独立集
    CF R630 div2 1332 E Height All the Same
    C++多线程の条件变量
    c++多线程のunique和lazy initation
    c++多线程の死锁与防止死锁
    c++多线程の数据竞争和互斥对象
    c++的多线程和多进程
  • 原文地址:https://www.cnblogs.com/milton/p/9106291.html
Copyright © 2011-2022 走看看