zoukankan      html  css  js  c++  java
  • ASM 条件判断

    技术交流,DH讲解.

    正式之前,我们看看寄存器和CPU的标志位:
    image

    OD中的截图,下方的CPAZSTDO就是标志位.
    image
    Delphi的FPU窗口,右边一列就是标志位.
    为什么要给大家看标志位呢?因为ASM中的跳转语句都是由相应的标志位控制的.
    而标志位又是由于以下的情况影响的:
    1.运算结果为0,Zero Flag(ZF)被设定
    2.运算结果太大或者太小,超容了,Carry Flag(CF)被设定
    3.Sign Flag(SF)是运算结果的最高位发生变化的时候,结果为正SF=1,为负SF=0
    4.指令无效时(al=+127, al+1爆 , al = -128 , al-1爆),Over Flag会被设定
    5.运算造成结果的地位中1的个数是偶数个的时候Parity Flag会被设定

    指令讲解:
    具体指令之前,先说一下:reg代表寄存器,mem代表内存上的数(变量),imm代表立即数(常量)
    AND,二元操作符,位与
    合法形式:

    AND reg , reg
    AND reg , mem
    AND reg , imm
    AND mem , reg
    AND mem , imm

    标志位:总是清除OF和CF,根据结果来设置SF,ZF,PF.
    来看个例子吧:

    function TestAnd(a,b:Integer):Integer ;
    asm
      and eax,edx
    end;
    
    procedure TForm4.FormCreate(Sender: TObject);
    var
      a:Integer;
    begin
      a:=$F;//00001111
      ShowMessage(IntToStr(TestAnd(a,1)));
    end;

    image 运算前
    image 运算后
    来个有用的函数,字符转换成大写:

    function UpcaseChar(a:AnsiChar):AnsiChar;
    asm
      and al,$DF
    end;

    OR,二元操作符,位或
    合法形式:

    OR reg , reg
    OR reg , mem
    OR reg , imm
    OR mem , reg
    OR mem , imm 

    标志位:和AND一样.
    例子将0~9的整数变成对应的Char形式:

    function _0_9ToChar(n:Byte):AnsiChar;
    asm
      or al,$30
    end;

    image 运算前
    image 运算后

    XOR,二元操作符,位异或(相同为0,不同为1)
    合法形式:同AND
    标志位:同AND
    我们有时候需要将某个寄存器清零,我们有2种方式:

    procedure TestXor;
    asm
      xor eax,eax
      mov eax,0
    end;

    反汇编看:
    image
    第一个指令:$31C0只用了2个字节.第二个指令就用了5个字节.
    NOT,一元操作符,位非(1变0,0变1)
    合法形式:

    NOT reg
    NOT mem

    标志位:不影响任何标志位
    TEST,二元操作符,和AND的一样,但是不改变2个操作数的值,只影响标志位.
    合法形式:同AND
    标志位:同AND
    我们经常需要判断一个string变量是否为nil

    function TestTest(const s:string):Integer;
    asm
      test eax,eax //if s=nil then
      jz @@nExit
    end;

    CMP,二元操作符,比较2个数大小
    合法形式:同SUB指令
    标志位:
                    CF ZF
    目的<來源 | 0 | 1
    目的>來源 | 0 | 0
    目的=來源 | 1 | 0
    带正负号的数比较:
    目的<來源 | SF≠OF
    目的>來源 | SF=OF
    目的=來源 | ZF=1

    常用的设置个别标志位的方法:
    1 ZF

    and al,0 //ZF=1,任何数和0进行与
    or al,1 //ZF=0,任何数和1进行或

    2 SF

    or al,$80 //SF=1,最高位与1进行或
    and al,$7F //SF=0,最高位与0进行与

    3 CF

    stc //CF=1
    clc //CF=0

    4 OF

    mov al,$7F
    inc al //OF=1
    or al,0 //OF=0

    跳转指令
    一般跳转根据:1 标志位 2 参与运算的2个数
    第一组:N代表Not,J就是Jump,然后其他字母对应相应的标志位
    JZ   | 若為零則跳     | ZF=1
    JNZ | 若為不零則跳 | ZF=0
    JC   | 若進位則跳     | CF=1
    JNC | 若不進位則跳 | CF=0
    JO   | 若溢位則跳     | OF=1
    JNO | 若不溢位則跳 | OF=0
    JS    | 若負號則跳    | SF=1
    JNS  | 若非負號則跳 | SF=0
    JP    | 同位(偶)則跳  | PF=1
    JNP | 非同位(奇)則跳 | PF=0
    第二组:根据参与运算的2个数的值
    JE     | 相等則跳(leftOp=rightOp)
    JNE   | 不相等則跳(leftOp≠rightOp)
    JCXZ | 若 CX = 0 則跳
    JECXZ | 若 ECX = 0 則跳
    无符号2个数比较时候:
    JA     | 較大則跳 大于
    JNBE | 不是較小或相等則跳(=JA) 大于
    JAE   | 較大或相等則跳 大于等于
    JNB   | 不是較小則跳(=JAE)大于等于
    JB     | 較小則跳 小于
    JNAE | 不是較大或相等則跳(=JB)小于
    JBE   | 較小或相等則跳 小于等于
    JNA   | 不是較大則跳(=JBE)小于等于
    有符号2个数比较时候:
    JG      | 較大則跳
    JNLE  | 非較小或相等則跳(=JG)
    JGE    | 較大或相等則跳
    JNL    | 不是較小則跳(=JGE)
    JL      | 較小則跳
    JNGE | 非較大或相等則跳(=JL)
    JLE    | 較小或相等則跳
    JNG   | 不是較大則跳(=JLE) | 不是較大則跳(=JBE)

    好我们来看下怎么写一个求2个数中较小的一个数的函数

    function IntegerMin(a,b:Integer):Integer;
    asm
      cmp eax,edx
      jg @@nBmin
      ret
    @@nBmin:
      mov eax,edx
    end;
    
    function CardinalMin(a,b:Cardinal):Cardinal ;
    asm
      cmp eax,edx
      ja @@nBmin
      ret
    @@nBmin:
      mov eax,edx
    end;

    关键处的跳转指令不一样的,因为数据类型不一样.

    最后来看一下循环指令
    LOOPELOOPZ,一元操作符,满足条件就跳转,条件是ZF=1 and ecx>0
    合法形式:LOOPE/LOOPZ 标签

    LOOPNELOOPNZ,一元操作符,条件ZF=0 AND ECX>0
    合法形式:和LOOPE
    我们用LoopE来在一个字符串中查找一个字符

    function FindChar(a:AnsiChar;const s:AnsiString):Integer ;
    asm
      test edx,edx   //s=nil
      jz @@nNotFound
      mov ecx,[edx - 4]
      //length(s)=0
      jz @@nNotFound
      push edx
      dec edx
    @@nLoop:
      inc edx
      cmp al,Byte ptr [edx]
      loopne @@nLoop
      pop edx
      test ecx,ecx
      jz @@nNotFound
      mov eax,[edx - 4]
      sub eax,ecx
      dec eax
      ret
    @@nNotFound:
      xor eax,eax
    end;

    好了今天能说的就这么多了.特别感谢http://evotalk.net..都是中国人哈哈.

  • 相关阅读:
    668. Kth Smallest Number in Multiplication Table
    658. Find K Closest Elements
    483. Smallest Good Base
    475. Heaters
    454. 4Sum II
    441. Arranging Coins
    436. Find Right Interval
    410. Split Array Largest Sum
    392. Is Subsequence
    378. Kth Smallest Element in a Sorted Matrix
  • 原文地址:https://www.cnblogs.com/huangjacky/p/1652495.html
Copyright © 2011-2022 走看看