zoukankan      html  css  js  c++  java
  • win32汇编问题指令

    一、关于REP/REPE/REPZ/REPNE/REPNZ

         按计数寄存器 ((E)CX) 中指定的次数重复执行字符串指令,或是重复到 ZF 标志不再满足指定的条件。REP(重复)、REPE(相等时重复)、REPNE(不相等时重复)、REPZ(为零时重复)及 REPNZ(不为零时重复)助记符都是可以添加到一些字符串指令中的前缀。REP 前缀可以添加到 INS、OUTS、MOVS、LODS 及 STOS 指令,REPE、REPNE、REPZ 及 REPNZ 前缀可以添加到 CMPS 与 SCAS 指令。(REPZ 与 REPNZ 前缀分别是 REPE 与 REPNE 前缀的同义形式)。同非字符串指令一起使用时,REP 前缀的行为未定义。

    REP 前缀一次只能应用于一条字符串指令。要重复指令块,请使用 LOOP 指令或其它循环结构。

    所有这些重复前缀都会使关联的指令重复执行,直到寄存器 (E)CX 中的计数递减到 0(请参阅下表)。(如果当前地址大小属性为 32,则将寄存器 ECX 用作计数器;如果大小属性为 16,则将 CX 寄存器用作计数器)。在每次迭代之后,REPE、REPNE、REPZ 及 REPNZ 前缀还会检查 ZF 标志的状态,如果 ZF 标志未处于指定的状态,则终止重复循环。同时测试两个终止条件时,终止重复的原因可以通过使用 JECXZ 指令来测试 (E)CX 寄存器进行确定,也可以通过使用 JZ、JNZ 及 JNE 指令来测试 ZF 标志进行确定。

    重复前缀 终止条件1 终止条件2

    REP

    ECX=0

    REPE/REPZ

    ECX=0

    ZF=0

    REPNE/REPNZ

    ECX=0

    ZF=1

    使用 REPE/REPZ 与 REPNE/REPNZ 前缀时,由于 CMPS 与 SCAS 指令都会根据它们的比较结果设置 ZF 标志,因此 ZF 标志不需要初始化。

    正在重复的字符串操作可以因异常或中断而暂停。发生这种情况时,将保存寄存器的状态,以便从异常或中断处理程序返回时,字符串操作能够恢复。源寄存器与目标寄存器指向下一个要操作的字符串元素,EIP 寄存器指向字符串指令,ECX 寄存器保存的是上一次成功迭代指令之后的值。通过此种机制,就可以执行很长的字符串操作,而不会影响系统的中断响应时间。

    在执行以 REPE 或 REPNE 为前缀的 CMPS 或 SCAS 指令期间,如果发生错误,EFLAGS 值还原为指令执行之前的状态。由于 SCAS 与 CMPS 指令不会将 EFLAGS 用作输入,因此,处理器可以在页错误处理程序完成之后恢复执行指令。

    谨慎使用 REP INS 与 REP OUTS 指令。并非所有的 I/O 端口都可以处理这些指令的执行速率。

    初始化大块内存最快的方法是使用 REP STOS 指令。

     示例一:在字符串中查找字符

    cld //从低地址到高地址方向 
    lea edi, lpszName //edi指向目标字符串首地址 (00402068)="*.exe"
    mov al,'x' //要查找值放入al中 
    mov ecx,5 //重复查找次数
    repne scasb //在edi所指字符串中查找al值,若不等将继续查找,直到(ecx)=0

    REPNE执行的操作:
    1)如(ecx)=0时退出,否则往下执行
    2)(ecx)=(ecx)-1
    3)执行其后的串指令
    4)重复1)~3)
    上述程序段执行结果:(edi)=0040206c   (ecx)=1

     示例二:两个字符串比较

    cld //从低地址到高地址方向 
    lea edi, lpszSrc //edi指向目标字符串首地址 (00402060)="c:\windows"
    lea esi, lpszDes //edi指向目标字符串首地址 (00402090)="c:\windows" 
    mov ecx,11 //重复查找次数
    repz cmpsb //如果相等则继续比较,直到源目字符不等或(ecx)=0才结束 
    .if ZERO? //如果条件满足,表示两个字符串完全相等
    ...          
    .endif//重复查找次数 
    上述程序段执行结果:(edi)=0040206B   (edi)=0040209B  (ecx)=0  ZF=1

    二、关于mul div imul idiv

    MUL: 无符号乘


    ;影响 OF、CF 标志位
    ;指令格式:
    ;MUL r/m  ;参数是乘数
    
    ;如果参数是 r8/m8,   将把  AL 做乘数, 结果放在 AX
    ;如果参数是 r16/m16, 将把  AX 做乘数, 结果放在 EAX
    ;如果参数是 r32/m32, 将把 EAX 做乘数, 结果放在 EDX:EAX
    
    示例一: 8 位
    mov al, 0FFh mov cl, 8 mul cl 执行结果:(ax)=07F8h   示例二: 16 位 mov ax, 0FFFFh
    mov cx, 8
    mul cx
    执行结果:(dx)=0007h (ax)=0FFF8h   示例三: 32 位   mov eax, 0FFFFFFFFh
      mov ecx, 8   mul ecx   执行结果: (edx)=00000007h (eax)=0FFFFFFF8h

    IMUL: 有符号乘
    ;影响 OF、CF 标志位
    ;第一种指令格式:
    ;IMUL r/m  ;单操作数
    
    ;如果参数是 r8/m8,   将把  AL 做乘数, 结果放在 AX
    ;如果参数是 r16/m16, 将把  AX 做乘数, 结果放在 EAX
    ;如果参数是 r32/m32, 将把 EAX 做乘数, 结果放在 EDX:EAX
    
    ;以上这些都是和 MUL 一样的, 只是运算结果有时一样、有时不一样.
    
    ;IMUL 还有另外两种指令格式:
    ;IMUL r16/r32, r16/r32/m16/m32/i  ;双操作数, (1)*(2) -> (1)
    ;IMUL r16/r32, r16/r32/m16/m32, i ;三操作数, (2)*(3) -> (1)
    
    ;其中常数 i 的位数可以 <= 但不能 > 其他操作数
    

        示例一:8 位   
    mov al, 0FFh
    mov cl, 8 imul cl
    执行结果:(ax)=0FFF8h   示例二:16 位   mov ax, 0FFFFh
    mov cx, 8
      imul cx
      执行结果:(dx)=0FFFFh (ax)=0FFF8h   示例三:32 位   mov eax, 0FFFFFFFFh
    mov ecx, 8
      imul ecx   执行结果:(edx)=0FFFFFFFFh (eax)=0FFFFFFF8h 示例四:;IMUL 两个操作数   mov eax, 7
    mov ecx, 8   imul eax, 8   执行结果:(eax)=56   示例五:IMUL 三个操作数   mov ecx, 8
    imul eax, val, 9   执行结果:(eax)=72

    MUL 与 IMUL 结果的一致和不一致:

    示例六:如果操作数都没有符号位, 结果一致   mov al, 7Fh
    mov cl, 7fh
      mul cl   执行结果: (ax)=3F01h     mov al, 7Fh
    mov cl, 7fh   imul cl   执行结果: (ax)=3F01h   示例七:如果操作数的其中之一有符号位, 结果不一致   mov al, 80h
    mov cl, 7fh   mul cl   执行结果: (ax)=3F80     mov al, 80h
    mov cl, 7fh   imul cl   执行结果: (ax)=0C080h   示例八:如果操作数都有符号位, 结果也一致   mov cl, 80h   mov al, 80h   mul cl   执行结果: (ax)=4000h     mov al, 80h
    mov cl, 80h
      imul cl   执行结果: (ax)=4000h


    DIV、IDIV: 无符号除、有符号除


    ;它们没有定义对 EFLAGS 的影响
    ;它们的指令格式:
    ;DIV r/m  ;参数是除数
    
    ;如果参数是 r8/m8,   将把 AX      做被除数; 商 -> AL,  余数 -> AH
    ;如果参数是 r16/m16, 将把 DX:AX   做被除数; 商 -> AX,  余数 -> DX
    ;如果参数是 r32/m32, 将把 EDX:EAX 做被除数; 商 -> EAX, 余数 -> EDX
    
        示例一:除数是 8 位
         mov ax, 17   ;被除数
         mov cl, 3    ;除数
         div cl
         执行结果: (al)=5 --商    (ah)=2 --余数
        
         示例二:除数是 16 位
         mov dx, 0    ;
         mov ax, 17   ;dx:ax 是被除数
         mov cx, 3    ;cx    是除数
         div cx
         执行结果: (ax)=5 --商  (dx)=2 --余数
        
          示例三:除数是 32 位
          mov edx, 0   ;
          mov eax, 17  ;edx:eax 是被除数
          mov ecx, 3   ;ecx     是除数
          div ecx
          执行结果: (eax)=5 --商 (edx0=2 --余数
    
    ;IDIV 测试
    
         示例一:除数是 8 位
         mov al, -17   
         cbw          ;ax 是被除数
         mov cl, 3    ;除数
         idiv cl
         执行结果: (al)=-5 --商    (ah)=-2 --余数
        
         示例二:除数是 16 位
         mov ax, -17   
         cwd          ;dx:ax 是被除数
         mov cx, 3    ;cx    是除数
         idiv cx
         执行结果: (ax)=-5 --商 (dx)=-2 --余数
        
         示例三:除数是 32 位
         mov eax, -17  
         cdq          ;edx:eax 是被除数
         mov ecx, 3   ;ecx     是除数
         idiv ecx
         执行结果: (eax)=-5 --商   (edx)=-2 --余数
    
  • 相关阅读:
    DFS(深度优先搜索)
    dp动态规划 之 背包问题
    python选择排序的实现
    python冒泡排序实现
    python 数据类型
    SyntaxError: Missing parentheses in call to 'print'
    MFC位图传送错误之一
    SyntaxError :invalid syntax
    Python之命令行参数
    Python之print
  • 原文地址:https://www.cnblogs.com/guanlaiy/p/2507267.html
Copyright © 2011-2022 走看看