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,二元操作符,位与
    合法形式:

    1
    2
    3
    4
    5
    AND reg , reg
    AND reg , mem
    AND reg , imm
    AND mem , reg
    AND mem , imm

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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 运算后
    来个有用的函数,字符转换成大写:

    1
    2
    3
    4
    function UpcaseChar(a:AnsiChar):AnsiChar;
    asm
      and al,$DF
    end;

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

    1
    2
    3
    4
    5
    OR reg , reg
    OR reg , mem
    OR reg , imm
    OR mem , reg
    OR mem , imm

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

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

    image 运算前
    image 运算后

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

    1
    2
    3
    4
    5
    procedure TestXor;
    asm
      xor eax,eax
      mov eax,0
    end;

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

    1
    2
    NOT reg
    NOT mem

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

    1
    2
    3
    4
    5
    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

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

    2 SF

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

    3 CF

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

    4 OF

    1
    2
    3
    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个数中较小的一个数的函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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来在一个字符串中查找一个字符

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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..都是中国人哈哈.

    http://www.cnblogs.com/huangjacky/archive/2010/01/20/1652495.html

  • 相关阅读:
    void类型和void *指针类型(网上摘抄总结)【转】
    微信小程序中的canvas基础应用
    Google Interview University 一套完整的学习手册帮助自己准备 Google 的面试
    git使用教程(详细)
    Vue下载依赖遇到的一些bug
    原生Javascript客户端表单验证
    ASP MVC 后台控制器弹出框提示
    网页URLJs传值传值传值传值传值问题
    从零开始,搭建博客系统MVC5+EF6搭建框架(1),EF Code frist、实现泛型数据仓储以及业务逻辑
    弹出提示框,在跳转
  • 原文地址:https://www.cnblogs.com/findumars/p/5185276.html
Copyright © 2011-2022 走看看