zoukankan      html  css  js  c++  java
  • 各寄存器的作用

    各寄存器的作用

    ============
     
    通用寄存器
    EAX 累加(Accumulator)寄存器 AX(AH、AL) 常用于乘、除法和函数返回值
    EBX 基址(Base)寄存器 BX(BH、BL) 常做内存数据的指针, 或者说常以它为基址来访问内存.
    ECX 计数器(Counter)寄存器 CX(CH、CL) 常做字符串和循环操作中的计数器
    EDX 数据(Data)寄存器 DX(DH、DL) 常用于乘、除法和 I/O 指针
    ESI 来源索引(Source Index)寄存器 SI 常做内存数据指针和源字符串指针
    EDI 目的索引(Destination Index)寄存器 DI 常做内存数据指针和目的字符串指针
    ESP 堆栈指针(Stack Point)寄存器 SP 只做堆栈的栈顶指针; 不能用于算术运算与数据传送
    EBP 基址指针(Base Point)寄存器 BP 只做堆栈指针, 可以访问堆栈内任意地址, 经常用于中转 ESP 中的数据, 也常以它为基址来访问堆栈; 不能用于算术运算与数据传送
    指令指针寄存器
    EIP 指令指针(Instruction Pointer)寄存器 总是指向下一条指令的地址; 所有已执行的指令都被它指向过.
    标志寄存器
    EFLAGS

    标志(Flag)寄存器:
    EFLAGS 中的 32 位被分成 0-31 个二进制位分别使用;
    第 0、2、4、6、7、11 位是状态标志位;
    第 10 位是字符串操作控制标志位;
    其他标志位一般不用或无权使用
     

    0 CF 进位(Carry)标志 目标无法容纳无符号算术运算的结果, 需要进位或借位时被设置; 可用 STC 指令设置, CLC 指令取消.
    1      
    2 PF 奇偶(Parity)标志 低 8 位中有偶数个 1 时被设置
    3      
    4 AF 辅助(Auxiliary)标志 使用 BCD 码运算导致 3 位到 4 位产生进位时被设置
    5      
    6 ZF 零(Zero)标志 运算结果为 0 时被设置
    7 SF 符号(Sign)标志 运算结果为负数时被设置
    8      
    9      
    10 DF 方向(Direction)标志 字符串操作是从高位到低位时被设置; 可用 STD 指令设置, CLD 指令取消.
    11 OF 溢出(Overflow)标志 因有符号运算的结果太宽而导致数据丢失时被设置
    ...      
    31      
    ...          


    其中的 EAX、ECX、EDX 三个寄存器相对自由些, 所以练习时用它们较多.

    没理会段寄存器: CS、DS、SS、ES、FS、GS, 是因在 Win32 保护模式下编程它们不再重要了.

    还有 FPU、MMX 系列寄存器, 等用到再说吧.
     
     
    4个数据寄存器(EAX、EBX、ECX、EDX)
    2个变址和指针寄存器(ESI、EDI)
    2个指针寄存器(ESP、EBP)
    6个段寄存器(ES、CS、SS、DS、FS、GS)
    1个指令指针寄存器(EIP)
    1个标志寄存器(EFL)
     
    1、数据寄存器
    数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间。32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。对低16位数据的存取,不会影响高16位的数据。这些低16位寄存器分别命名为:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。
    4个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取。程序员可利用数据寄存器的这种“可分可合”的特性,灵活地处理字/字节的信息。
    寄存器AX和AL通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。累加器可用于乘、 除、输入/输出等操作,它们的使用频率很高; 寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用; 寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次数;在位操作 中,当移多位时,要用CL来指明移位的位数;
    寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也 可用于存放I/O的端口地址。在16位CPU中,AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址,但在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果,而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。
     
    2、变址寄存器
    32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据。
    寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。变址寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。
     
    3、指针寄存器
    32位CPU有2个32位通用寄存器EBP和ESP。其低16位对应先前CPU中的SBP和SP,对低16位数据的存取,不影响高16位的数据。
    寄存器EBP、ESP、BP和SP称为指针寄存器(Pointer Register),主要用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。指针寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。
    它们主要用于访问堆栈内的存储单元,并且规定:
    BP为基指针(Base Pointer)寄存器,通过它减去一定的偏移值,来访问栈中的元素;
    SP为堆栈指针(Stack Pointer)寄存器,它始终指向栈顶。
    说明:因栈的生长方向是从高地址向低地址生长,所以,进栈时,sp自减;出栈时,sp自增;
     
    4、段寄存器
    段寄存器是根据内存分段的管理模式而设置的。内存单元的物理地址由段寄存器的值和一个偏移量组合而成
    的,这样可用两个较少位数的值组合成一个可访问较大物理空间的内存地址。
    CPU内部的段寄存器:
    CS——代码段寄存器(Code Segment Register),其值为代码段的段值;
    DS——数据段寄存器(Data Segment Register),其值为数据段的段值;
    ES——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
    SS——堆栈段寄存器(Stack Segment Register),其值为堆栈段的段值;
    FS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
    GS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值。
    在16位CPU系统中,它只有4个段寄存器,所以,程序在任何时刻至多有4个正在使用的段可直接访问;在32位微机系统中,它有6个段寄存器,所以,在此环境下开发的程序最多可同时访问6个段。32位CPU有两个不同的工作方式:实方式和保护方式。在每种方式下,段寄存器的作用是不同的。有关规定简单描述如下:
    实方式: 前4个段寄存器CS、DS、ES和SS与先前CPU中的所对应的段寄存器的含义完全一致,内存单元的逻辑地址仍为”段值:偏移量”的形式。为访问某内存段内的数据,必须使用该段寄存器和存储单元的偏移量。
    保护方式: 在此方式下,情况要复杂得多,装入段寄存器的不再是段值,而是称为”选择子”(Selector)的某个值。
     
    5、指令指针寄存器
    32位CPU把指令指针扩展到32位,并记作EIP,EIP的低16位与先前CPU中的IP作用相同。
    指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。在具有预取指令功能的系统中,下次要执行的指令通常已被预取到指令队列中,除非发生转移情况。所以,在理解它们的功能时,不考虑存在指令队列的情况。
    在实方式下,由于每个段的最大范围为64K,所以,EIP中的高16位肯定都为0,此时,相当于只用其低16位的IP来反映程序中指令的执行次序。
     
    6、标志寄存器
    asm
    一、运算结果标志位
    1、进位标志CF(Carry Flag)
    进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位,那么,其值为1,否则其值为0。使用该标志位的情况有:多字(字节)数的加减运算,无符号数的大小比较运算,移位操作,字(字节)之间移位,专门改变CF值的指令等。
    2、奇偶标志PF(Parity Flag)
    奇偶标志PF用于反映运算结果中”1″的个数的奇偶性。如果”1″的个数为偶数,则PF的值为1,否则其值为0。
    利用PF可进行奇偶校验检查,或产生奇偶校验位。在数据传送过程中,为了提供传送的可靠性,如果采用奇偶校验的方法,就可使用该标志位。
    3、辅助进位标志AF(Auxiliary Carry Flag)
    在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0:
    (1)、在字操作时,发生低字节向高字节进位或借位时;
    (2)、在字节操作时,发生低4位向高4位进位或借位时。
    对以上6个运算结果标志位,在一般编程情况下,标志位CF、ZF、SF和OF的使用频率较高,而标志位PF和AF的使用频率较低。
    4、零标志ZF(Zero Flag)
    零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。
    5、符号标志SF(Sign Flag)
    符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用补码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1。
    6、溢出标志OF(Overflow Flag)
    溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。”溢出”和”进位”是两个不同含义的概念,不要混淆。如果不太清楚的话,请查阅《计算机组成原理》课程中的有关章节。
    二、状态控制标志位
    状态控制标志位是用来控制CPU操作的,它们要通过专门的指令才能使之发生改变。
    1、追踪标志TF(Trap Flag)
    当追踪标志TF被置为1时,CPU进入单步执行方式,即每执行一条指令,产生一个单步中断请求。这种方式主要用于程序的调试。指令系统中没有专门的指令来改变标志位TF的值,但程序员可用其它办法来改变其值。
    2、中断允许标志IF(Interrupt-enable Flag)
    中断允许标志IF是用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求。但不管该标志为何值,CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求,以及CPU内部产生的中断请求。具体规定如下:
    (1)、当IF=1时,CPU可以响应CPU外部的可屏蔽中断发出的中断请求;
    (2)、当IF=0时,CPU不响应CPU外部的可屏蔽中断发出的中断请求。
    CPU的指令系统中也有专门的指令来改变标志位IF的值。
    3、方向标志DF(Direction Flag)
    方向标志DF用来决定在串操作指令执行时有关指针寄存器发生调整的方向。具体规定在第5.2.11节——字符串操作指令——中给出。在微机的指令系统中,还提供了专门的指令来改变标志位DF的值。
    三、32位标志寄存器增加的标志位
    1、I/O特权标志IOPL(I/O Privilege Level)
    I/O特权标志用两位二进制位来表示,也称为I/O特权级字段。该字段指定了要求执行I/O指令的特权级。如果当前的特权级别在数值上小于等于IOPL的值,那么,该I/O指令可执行,否则将发生一个保护异常。
    2、嵌套任务标志NT(Nested Task)
    嵌套任务标志NT用来控制中断返回指令IRET的执行。具体规定如下:
    (1)、当NT=0,用堆栈中保存的值恢复EFLAGS、CS和EIP,执行常规的中断返回操作;
    (2)、当NT=1,通过任务转换实现中断返回。
    3、重启动标志RF(Restart Flag)
    重启动标志RF用来控制是否接受调试故障。规定:RF=0时,表示”接受”调试故障,否则拒绝之。在成功执行完一条指令后,处理机把RF置为0,当接受到一个非调试故障时,处理机就把它置为1。
    4、虚拟8086方式标志VM(Virtual 8086 Mode)
    如果该标志的值为1,则表示处理机处于虚拟的8086方式下的工作状态,否则,处理机处于一般保护方式下的工作状态。
     
     

    eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。

    比方说:add eax,-2 ;   //可以认为是给变量eax加上-2这样的一个值。

    这些32位寄存器有多种用途,但每一个都有“专长”,有各自的特别之处。

    EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。

    EBX 是"基地址"(base)寄存器, 在内存寻址时存放基地址。

    ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。

    EDX 则总是被用来放整数除法产生的余数。

    ESI/EDI分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.

    EBP是"基址指针"(BASE POINTER), 它最经常被用作高级语言函数调用的"框架指针"(frame pointer). 在破解的时候,经常可以看见一个标准的函数起始代码:

    push ebp ;保存当前ebp
    mov ebp,esp ;EBP设为当前堆栈指针
    sub esp, xxx ;预留xxx字节给函数临时变量.
    ...

    这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数. EBP下方则是临时变量. 函数返回时作 mov esp,ebp/pop ebp/ret 即可.

    ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。

    esp:寄存器存放当前线程的栈顶指针
    ebp:寄存器存放当前线程的栈底指针
    eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。

    一般寄存器:AX、BX、CX、DX
    AX:累積暫存器,BX:基底暫存器,CX:計數暫存器,DX:資料暫存器

    索引暫存器:SI、DI 
    SI:來源索引暫存器,DI:目的索引暫存器 

    堆疊、基底暫存器:SP、BP 
    SP:堆疊指標暫存器,BP:基底指標暫存器 

    EAX、ECX、EDX、EBX:為ax,bx,cx,dx的延伸,各為32位元 
    ESI、EDI、ESP、EBP:為si,di,sp,bp的延伸,32位元

    栈的基本模型

    参数N

    ↓高地址

    参数…

    函数参数入栈的顺序与具体的调用方式有关

    参数 3

    参数 2

    参数 1

    EIP

    返回本次调用后,下一条指令的地址

    EBP

    保存调用者的EBP,然后EBP指向此时的栈顶。

    临时变量1

    临时变量2

    临时变量3

    临时变量…

    临时变量5

    ↓低地址

     
     
     
     
     
     
    指令功能
    AAA 调整加
    AAD 调整除
    AAM 调整乘
    AAS 调整减
    ADC 进位加
    ADD
    AND
    ARPL 调整优先级
    BOUND 检查数组
    BSF 位右扫描
    BSR 位左扫描
    BSWAP 交换字节
    BT 位测试
    BTC 位测试求反
    BTR 位测试清零
    BTS 位测试置一
    CALL 过程调用
    CBW 转换字节
    CDQ 转换双字
    CLC 进位清零
    CLD 方向清零
    CLI 中断清零
    CLTS 任务清除
    CMC 进位求反
    CMOVA 高于传送
    CMOVB 低于传送
    CMOVE 相等传送
    CMOVG 大于传送
    CMOVL 小于传送
    CMOVNA 不高于传送
    CMOVNB 不低于传送
    CMOVNE 不等传送
    CMOVNG 不大于传送
    CMOVNL 不小于传送
    CMOVNO 不溢出传送
    CMOVNP 非奇偶传送
    CMOVNS 非负传送
    CMOVO 溢出传送
    CMOVP 奇偶传送
    CMOVS 负号传送
    CMP 比较
    CMPSB 比较字节串
    CMPSD 比较双字串
    CMPSW 比较字串
    CMPXCHG 比较交换
    CMPXCHG486 比较交换486
    CMPXCHG8B 比较交换8字节
    CPUID CPU标识
    CWD 转换字
    CWDE 扩展字
    DAA 调整加十
    DAS 调整减十
    DEC 减一
    DIV
    ENTER 建立堆栈帧
    HLT
    IDIV 符号整除
    IMUL 符号乘法
    IN 端口输入
    INC 加一
    INSB 端口输入字节串
    INSD 端口输入双字串
    INSW 端口输入字串
    JA 高于跳转
    JB 低于跳转
    JBE 不高于跳转
    JCXZ 计数一六零跳转
    JE 相等跳转
    JECXZ 计数三二零跳转
    JG 大于跳转
    JL 小于跳转
    JMP 跳转
    JMPE 跳转扩展
    JNB 不低于跳转
    JNE 不等跳转
    JNG 不大于跳转
    JNL 不小于跳转
    JNO 不溢出跳转
    JNP 非奇偶跳转
    JNS 非负跳转
    JO 溢出跳转
    JP 奇偶跳转
    JS 负号跳转
    LAHF 加载标志低八
    LAR 加载访问权限
    LDS 加载数据段
    LEA 加载有效地址
    LEAVE 清除过程堆栈
    LES 加载附加段
    LFS 加载标志段
    LGDT 加载全局描述符
    LGS 加载全局段
    LIDT 加载中断描述符
    LMSW 加载状态字
    LOADALL 加载所有
    LOADALL286 加载所有286
    LOCK
    LODSB 加载源变址字节串
    LODSD 加载源变址双字串
    LODSW 加载源变址字串
    LOOP 计数循环
    LOOPE 相等循环
    LOOPNE 不等循环
    LOOPNZ 非零循环
    LOOPZ 为零循环
    LSL 加载段界限
    LSS 加载堆栈段
    LTR 加载任务
    MONITOR 监视
    MOV 传送
    MOVSB 传送字节串
    MOVSD 传送双字串
    MOVSW 传送字串
    MOVSX 符号传送
    MOVZX 零传送
    MUL
    MWAIT  
    NEG 求补
    NOP
    NOT
    OR
    OUT 端口输出
    OUTSB 端口输出字节串
    OUTSD 端口输出双字串
    OUTSW 端口输出字串
    POP 出栈
    POPA 全部出栈
    POPF 标志出栈
    PUSH 压栈
    PUSHA 全部压栈
    PUSHF 标志压栈
    RCL 进位循环左移
    RCR 进位循环右移
    RDMSR 读专用模式
    RDPMC 读执行监视计数
    RDSHR  
    RDTSC 读时间戳计数
    REP 重复
    REPE 相等重复
    REPNE 不等重复
    RET 过程返回
    RETF 远过程返回
    RETN 近过程返回
    ROL 循环左移
    ROR 循环右移
    RSM 恢复系统管理
    SAHF 恢复标志低八
    SAL 算术左移
    SALC  
    SAR 算术右移
    SBB 借位减
    SCASB 扫描字节串
    SCASD 扫描双字串
    SCASW 扫描字串
    SETA 高于置位
    SETB 低于置位
    SETE 相等置位
    SETG 大于置位
    SETL 小于置位
    SETNA 不高于置位
    SETNB 不低于置位
    SETNE 不等置位
    SETNG 不大于置位
    SETNL 不小于置位
    SETNO 不溢出置位
    SETNP 非奇偶置位
    SETNS 非负置位
    SETO 溢出置位
    SETP 奇偶置位
    SETS 负号置位
    SGDT 保存全局描述符
    SHL 逻辑左移
    SHLD 双精度左移
    SHR 逻辑右移
    SHRD 双精度右移
    SIDT 保存中断描述符
    SLDT 保存局部描述符
    SMI  
    SMINT  
    SMINTOLD  
    SMSW 保存状态字
    STC 进位设置
    STD 方向设置
    STI 中断设置
    STOSB 保存字节串
    STOSD 保存双字串
    STOSW 保存字串
    STR 保存任务
    SUB
    SYSCALL 系统调用
    SYSENTER 系统进入
    SYSEXIT 系统退出
    SYSRET 系统返回
    TEST 数测试
    UD0 未定义指令0
    UD1 未定义指令1
    UD2 未定义指令2
    UMOV  
    VERW 校验写
    WAIT
    WBINVD 回写无效高速缓存
    WRMSR 写专用模式
    WRSHR  
    XADD 交换加
    XBTS  
    XCHG 交换
    XLAT 换码
    XOR 异或
    XSTORE  



    指令功能
    EMMS 媒体空MMX状态
    F2XM1 浮点栈顶绝对值
    FADD 浮点加
    FADDP 浮点加出栈
    FBLD 浮点加载十数
    FBSTP 浮点保存十数出栈
    FCHS 浮点正负求反
    FCLEX 浮点检查错误清除
    FCMOVB 浮点低于传送
    FCMOVBE 浮点不高于传送
    FCMOVE 浮点相等传送
    FCMOVNB 浮点不低于传送
    FCMOVNBE 浮点高于传送
    FCMOVNE 浮点不等传送
    FCMOVNU 浮点有序传送
    FCMOVU 浮点无序传送
    FCOM 浮点比较
    FCOMI 浮点比较加载标志
    FCOMIP 浮点比较加载标志出栈
    FCOMP 浮点比较出栈
    FCOMPP 浮点比较出栈二
    FCOS 浮点余弦
    FDECSTP 浮点栈针减一
    FDISI 浮点检查禁止中断
    FDIV 浮点除
    FDIVP 浮点除出栈
    FDIVR 浮点反除
    FDIVRP 浮点反除出栈
    FENI 浮点检查禁止中断二
    FFREE 浮点释放
    FFREEP 浮点释放出栈
    FIADD 浮点加整数
    FICOM 浮点比较整数
    FICOMP 浮点比较整数出栈
    FIDIV 浮点除整数
    FIDIVR 浮点反除
    FILD 浮点加载整数
    FIMUL 浮点乘整数
    FINCSTP 浮点栈针加一
    FINIT 浮点检查初始化
    FIST 浮点保存整数
    FISTP 浮点保存整数出栈
    FISTTP  
    FISUB 浮点减整数
    FISUBR 浮点反减整数
    FLD 浮点加载数
    FLD1 浮点加载一
    FLDCW 浮点加载控制器
    FLDENV 浮点加载环境
    FLDL2E 浮点加载L2E
    FLDL2T 浮点加载L2T
    FLDLG2 浮点加载LG2
    FLDLN2 浮点加载LN2
    FLDPI 浮点加载PI
    FLDZ 浮点加载零
    FMUL 浮点乘
    FMULP 浮点乘出栈
    FNCLEX 浮点不检查错误清除
    FNDISI 浮点不检查禁止中断
    FNENI 浮点不检查禁止中断二
    FNINIT 浮点不检查初始化
    FNOP 浮点空
    FNSAVE 浮点不检查保存状态
    FNSTCW 浮点不检查保存控制器
    FNSTENV 浮点不检查保存环境
    FNSTSW 浮点不检查保存状态器
    FPATAN 浮点部分反正切
    FPREM 浮点部分余数
    FPREM1 浮点部分余数二
    FPTAN 浮点部分正切
    FRNDINT 浮点舍入求整
    FRSTOR 浮点恢复状态
    FSAVE 浮点检查保存状态
    FSCALE 浮点比例运算
    FSETPM 浮点设置保护
    FSIN 浮点正弦
    FSINCOS 浮点正余弦
    FSQRT 浮点平方根
    FST 浮点保存
    FSTCW 浮点检查保存控制器
    FSTENV 浮点检查保存环境
    FSTP 浮点保存出栈
    FSTSW 浮点检查保存状态器
    FSUB 浮点减
    FSUBP 浮点减出栈
    FSUBR 浮点反减
    FSUBRP 浮点反减出栈
    FTST 浮点比零
    FUCOM 浮点无序比较
    FUCOMI 浮点反比加载标志
    FUCOMIP 浮点反比加载标志出栈
    FUCOMP 浮点无序比较出栈
    FUCOMPP 浮点无序比较出栈二
    FWAIT 浮点等
    FXAM 浮点检查
    FXCH 浮点交换
    FXTRACT 浮点分解
    FYL2X 浮点求L2X
    FYL2XP1 浮点求L2XP1
    MOVED 媒体双字传送
    MOVEQ 媒体四字传送
    PACKSSDW 媒体符号双字压缩
    PACKSSWB 媒体符号字压缩
    PACKUSWB 媒体无符号字压缩
    PADDB 媒体截断字节加
    PADDD 媒体截断双字加
    PADDSB 媒体符号饱和字节加
    PADDSIW  
    PADDSW 媒体符号饱和字加
    PADDUSB 媒体无符号饱和字节加
    PADDUSW 媒体无符号饱和字加
    PADDW 媒体截断字加
    PAND 媒体与
    PANDN 媒体与非
    PAVEB  
    PCMPEQB 媒体字节比等
    PCMPEQD 媒体双字比等
    PCMPEQW 媒体字比等
    PCMPGTB 媒体字节比大
    PCMPGTD 媒体双字比大
    PCMPGTW 媒体字比大
    PDISTIB  
    PMACHRIW  
    PMADDWD  
    PMAGW  
    PMULHRIW  
    PMULHRWC  
    PMULHW  
    PMVGEZB  
    PMVLZB  
    PMVNZB  
    PMVZB  
    POR 媒体或
    PSLLD 媒体双字左移
    PSLLQ 媒体四字左移
    PSLLW 媒体字左移
    PSRAD 媒体双字算术右移
    PSRAW 媒体字算术右移
    PSRLD 媒体双字右移
    PSRLQ 媒体四字右移
    PSRLW 媒体字右移
    PSUBB 媒体截断字节减
    PSUBSB 媒体符号饱和字节减
    PSUBSIW  
    PSUBSW 媒体符号饱和字减
    PSUBUSB 媒体无符号饱和字节减
    PSUBUSW 媒体无符号饱和字减
    PSUBW 媒体截断字减
    PUNPCKHBW 媒体字节高位解压
    PUNPCKHDQ 媒体双字高位解压
    PUNPCKHWD 媒体字高位解压
    PUNPCKLBW 媒体字节低位解压
    PUNPCKLDQ 媒体双字低位解压
    PUNPCKLWD 媒体字低位解压



    Delphi 2010 VCL、JCL 源码中用到的汇编指令(只是粗略统计):

    按名称排序使用次数按使用频率排序使用次数
    ADC 15 MOV 4053
    ADD 659 PUSH 1505
    AND 162 CMP 1372
    BSF 8 POP 1187
    BSR 7 JE 952
    BSWAP 12 CALL 847
    BT 13 JMP 771
    BTC 9 ADD 659
    BTR 10 JNE 503
    BTS 10 TEST 452
    CALL 847 SUB 400
    CDQ 6 DEC 332
    CLD 10 LEA 288
    CMP 1372 RET 280
    CPUID 3 INC 261
    CWD 1 JZ 252
    DB 241 OR 248
    DD 189 DB 241
    DEC 332 DD 189
    DIV 40 JNZ 167
    DW 63 MOVZX 166
    ELSE 2 AND 162
    END 2 FLD 154
    F2XM1 6 SHR 131
    FABS 7 JB 101
    FADD 9 JG 92
    FADDP 15 JA 86
    FBSTP 3 REP 83
    FCHS 5 JBE 81
    FCLEX 5 XCHG 79
    FCOM 7 JLE 79
    FCOMP 7 FSTP 76
    FCOMPP 3 LODSB 74
    FCOS 4 JL 72
    FDIV 11 FWAIT 72
    FDIVP 5 NEG 70
    FDIVRP 11 DW 63
    FFREE 13 LOCK 61
    FIADD 6 STOSB 58
    FIDIV 2 STOSW 54
    FILD 32 MOVSX 53
    FIMUL 4 FLDCW 52
    FINCSTP 1 FLD1 52
    FISTP 30 SHL 48
    FLD 154 JAE 48
    FLD1 52 DIV 40
    FLDCW 52 JGE 35
    FLDL2E 6 REPNE 33
    FLDLG2 2 LODSW 33
    FLDLN2 9 IMUL 32
    FLDZ 8 FMUL 32
    FMUL 32 FILD 32
    FMULP 26 JNS 31
    FNCLEX 11 FISTP 30
    FNINIT 2 FXCH 28
    FNSTCW 20 FMULP 26
    FNSTSW 6 JS 24
    FPATAN 15 SBB 22
    FPREM 3 FSTSW 22
    FPTAN 4 LOOP 20
    FRNDINT 14 FNSTCW 20
    FSCALE 8 FSTCW 18
    FSIN 3 NOT 17
    FSINCOS 7 JECXZ 17
    FSQRT 15 FYL2X 17
    FST 5 MUL 16
    FSTCW 18 JNC 16
    FSTP 76 SAHF 15
    FSTSW 22 ROR 15
    FSUB 11 FSQRT 15
    FSUBP 5 FPATAN 15
    FSUBR 2 FADDP 15
    FSUBRP 4 ADC 15
    FTST 4 FRNDINT 14
    FWAIT 72 FFREE 13
    FXAM 1 BT 13
    FXCH 28 SAR 12
    FXTRACT 1 ROL 12
    FYL2X 17 RCL 12
    FYL2XP1 1 JO 12
    HLT 1 BSWAP 12
    IMUL 32 REPE 11
    INC 261 FSUB 11
    INT 8 FNCLEX 11
    JA 86 FDIVRP 11
    JAE 48 FDIV 11
    JB 101 WAIT 10
    JBE 81 CLD 10
    JC 6 BTS 10
    JE 952 BTR 10
    JECXZ 17 SETC 9
    JG 92 FLDLN2 9
    JGE 35 FADD 9
    JL 72 BTC 9
    JLE 79 INT 8
    JMP 771 FSCALE 8
    JNA 1 FLDZ 8
    JNC 16 BSF 8
    JNE 503 PUSHFD 7
    JNG 2 FSINCOS 7
    JNL 1 FCOMP 7
    JNS 31 FCOM 7
    JNZ 167 FABS 7
    JO 12 BSR 7
    JRCXZ 2 NOP 6
    JS 24 JC 6
    JZ 252 FNSTSW 6
    LEA 288 FLDL2E 6
    LEAVE 1 FIADD 6
    LOCK 61 F2XM1 6
    LODSB 74 CDQ 6
    LODSW 33 STOSD 5
    LOOP 20 POPFD 5
    MOV 4053 FSUBP 5
    MOVSB 1 FST 5
    MOVSX 53 FDIVP 5
    MOVZX 166 FCLEX 5
    MUL 16 FCHS 5
    NEG 70 SHRD 4
    NOP 6 PUSHF 4
    NOT 17 POPF 4
    OR 248 FTST 4
    PAUSE 3 FSUBRP 4
    POP 1187 FPTAN 4
    POPF 4 FIMUL 4
    POPFD 5 FCOS 4
    PUSH 1505 RCR 3
    PUSHF 4 PAUSE 3
    PUSHFD 7 FSIN 3
    RCL 12 FPREM 3
    RCR 3 FCOMPP 3
    REP 83 FBSTP 3
    REPE 11 CPUID 3
    REPNE 33 STD 2
    RET 280 SETNZ 2
    ROL 12 SETE 2
    ROR 15 JRCXZ 2
    SAHF 15 JNG 2
    SAL 1 FSUBR 2
    SAR 12 FNINIT 2
    SBB 22 FLDLG2 2
    SETC 9 FIDIV 2
    SETE 2 END 2
    SETNC 1 ELSE 2
    SETNZ 2 STC 1
    SHL 48 SHLD 1
    SHLD 1 SETNC 1
    SHR 131 SAL 1
    SHRD 4 MOVSB 1
    STC 1 LEAVE 1
    STD 2 JNL 1
    STOSB 58 JNA 1
    STOSD 5 HLT 1
    STOSW 54 FYL2XP1 1
    SUB 400 FXTRACT 1
    TEST 452 FXAM 1
    WAIT 10 FINCSTP 1
    XCHG 79 CWD 1
     
     
    名称  功能 操作数操作码模数寄存器1寄存器2
    或内存
    位移量立即数符号方向芯片
    型号
    16位32位
    MOV 传送 累加08<=8[位移16] $A0 8086 $67
    MOV 传送 累加08<=8[位移32] $A0 386 $67
    MOV 传送 累加16<=16[位移16] $A1 8086 $6667
    MOV 传送 累加16<=16[位移32] $A1 386 $67 $66
    MOV 传送 累加32<=32[位移16] $A1 386 $66 $67
    MOV 传送 累加32<=32[位移32] $A1 386 $6667
    MOV 传送 累加8=>8[位移16] $A2 8086 $67
    MOV 传送 累加8=>8[位移32] $A2 386 $67
    MOV 传送 累加16=>16[位移16] $A3 8086 $6667
    MOV 传送 累加16=>16[位移32] $A3 386 $67 $66
    MOV 传送 累加32=>32[位移16] $A3 386 $66 $67
    MOV 传送 累加32=>32[位移32] $A3 386 $6667
    MOV 传送 寄:段=>寄16 $8C 11 3 0 8086 $66
    MOV 传送 寄:段=>寄32 $8C 11 3 0 386 $66
    MOV 传送 寄:段<=寄16 $8E 11 3 1 8086
    MOV 传送 寄:段<=寄32 $8E 11 3 1 386
    MOV 传送 寄:控制器=>寄32 $0F20 11 3 0 386
    MOV 传送 寄:调试器=>寄32 $0F21 11 3 0 386
    MOV 传送 寄:任务器=>寄32 $0F24 11 3 0 386
    MOV 传送 寄:控制器<=寄32 $0F22 11 3 1 386
    MOV 传送 寄:调试器<=寄32 $0F23 11 3 1 386
    MOV 传送 寄:任务器<=寄32 $0F26 11 3 1 386
    MOV 传送 寄8=>寄8 $88 11 1 3 0 8086
    MOV 传送 寄16=>寄16 $89 11 1 3 0 8086 $66
    MOV 传送 寄32=>寄32 $89 11 1 3 0 386 $66
    MOV 传送 寄8<=寄8 $8A 11 1 3 1 8086
    MOV 传送 寄16<=寄16 $8B 11 1 3 1 8086 $66
    MOV 传送 寄32<=寄32 $8B 11 1 3 1 386 $66
    MOV 传送 寄:段<=[寄16] $8E 00 5 1 8086 $67
    MOV 传送 寄:段<=[寄32] $8E 00 5 1 386 $67
    MOV 传送 寄8<=[寄16] $8A 00 1 5 1 8086 $67
    MOV 传送 寄8<=[寄32] $8A 00 1 5 1 386 $67
    MOV 传送 寄16<=[寄16] $8B 00 1 5 1 8086 $6667
    MOV 传送 寄16<=[寄32] $8B 00 1 5 1 386 $67 $66
    MOV 传送 寄32<=[寄16] $8B 00 1 5 1 386 $66 $67
    MOV 传送 寄32<=[寄32] $8B 00 1 5 1 386 $6667
    MOV 传送 寄:段<=[寄16+位移8] $8E 01 5 9 1 8086 $67
    MOV 传送 寄:段<=[寄32+位移8] $8E 01 5 9 1 386 $67
    MOV 传送 寄8<=[寄16+位移8] $8A 01 1 5 9 1 8086 $67
    MOV 传送 寄8<=[寄32+位移8] $8A 01 1 5 9 1 386 $67
    MOV 传送 寄16<=[寄16+位移8] $8B 01 1 5 9 1 8086 $6667
    MOV 传送 寄16<=[寄32+位移8] $8B 01 1 5 9 1 386 $67 $66
    MOV 传送 寄32<=[寄16+位移8] $8B 01 1 5 9 1 386 $66 $67
    MOV 传送 寄32<=[寄32+位移8] $8B 01 1 5 9 1 386 $6667
    MOV 传送 寄:段<=[寄16+位移16] $8E 10 5 9 1 8086 $67
    MOV 传送 寄:段<=[寄32+位移32] $8E 10 5 9 1 386 $67
    MOV 传送 寄8<=[寄16+位移16] $8A 10 1 5 9 1 8086 $67
    MOV 传送 寄8<=[寄32+位移32] $8A 10 1 5 9 1 386 $67
    MOV 传送 寄16<=[寄16+位移16] $8B 10 1 5 9 1 8086 $6667
    MOV 传送 寄16<=[寄32+位移32] $8B 10 1 5 9 1 386 $67 $66
    MOV 传送 寄32<=[寄16+位移16] $8B 10 1 5 9 1 386 $66 $67
    MOV 传送 寄32<=[寄32+位移32] $8B 10 1 5 9 1 386 $6667
    MOV 传送 寄8<=数8 $C6 11 000 3 10 8086
    MOV 传送 寄16<=数16 $C7 11 000 3 10 8086 $66
    MOV 传送 寄32<=数32 $C7 11 000 3 10 386 $66
    MOV 传送 寄8<=数8 $B0 90 10 8086
    MOV 传送 寄16<=数16 $B8 90 10 8086 $66
    MOV 传送 寄32<=数32 $B8 90 10 386 $66
    MOV 传送 寄:段=>[寄16] $8C 00 5 0 8086 $67
    MOV 传送 寄:段=>[寄32] $8C 00 5 0 386 $67
    MOV 传送 寄8=>[寄16] $88 00 1 5 0 8086 $67
    MOV 传送 寄8=>[寄32] $88 00 1 5 0 386 $67
    MOV 传送 寄16=>[寄16] $89 00 1 5 0 8086 $6667
    MOV 传送 寄16=>[寄32] $89 00 1 5 0 386 $67 $66
    MOV 传送 寄32=>[寄16] $89 00 1 5 0 386 $66 $67
    MOV 传送 寄32=>[寄32] $89 00 1 5 0 386 $6667
    MOV 传送 寄:段=>[寄16+位移8] $8C 01 5 9 0 8086 $67
    MOV 传送 寄:段=>[寄32+位移8] $8C 01 5 9 0 386 $67
    MOV 传送 寄8=>[寄16+位移8] $88 01 1 5 9 0 8086 $67
    MOV 传送 寄8=>[寄32+位移8] $88 01 1 5 9 0 386 $67
    MOV 传送 寄16=>[寄16+位移8] $89 01 1 5 9 0 8086 $6667
    MOV 传送 寄16=>[寄32+位移8] $89 01 1 5 9 0 386 $67 $66
    MOV 传送 寄32=>[寄16+位移8] $89 01 1 5 9 0 386 $66 $67
    MOV 传送 寄32=>[寄32+位移8] $89 01 1 5 9 0 386 $6667
    MOV 传送 寄:段=>[寄16+位移16] $8C 10 5 9 0 8086 $67
    MOV 传送 寄:段=>[寄32+位移32] $8C 10 5 9 0 386 $67
    MOV 传送 寄8=>[寄16+位移16] $88 10 1 5 9 0 8086 $67
    MOV 传送 寄8=>[寄32+位移32] $88 10 1 5 9 0 386 $67
    MOV 传送 寄16=>[寄16+位移16] $89 10 1 5 9 0 8086 $6667
    MOV 传送 寄16=>[寄32+位移32] $89 10 1 5 9 0 386 $67 $66
    MOV 传送 寄32=>[寄16+位移16] $89 10 1 5 9 0 386 $66 $67
    MOV 传送 寄32=>[寄32+位移32] $89 10 1 5 9 0 386 $6667
    MOV 传送 8[寄16]<=数8 $C6 00 000 5 10 8086 $67
    MOV 传送 8[寄32]<=数8 $C6 00 000 5 10 386 $67
    MOV 传送 16[寄16]<=数16 $C7 00 000 5 10 8086 $6766
    MOV 传送 16[寄32]<=数16 $C7 00 000 5 10 386 $67 $66
    MOV 传送 32[寄16]<=数32 $C7 00 000 5 10 386 $66 $67
    MOV 传送 32[寄32]<=数32 $C7 00 000 5 10 386 $6766
    MOV 传送 8[寄16+位移8]<=数8 $C6 01 000 5 9 10 8086 $67
    MOV 传送 8[寄32+位移8]<=数8 $C6 01 000 5 9 10 386 $67
    MOV 传送 16[寄16+位移8]<=数16 $C7 01 000 5 9 10 8086 $6766
    MOV 传送 16[寄32+位移8]<=数16 $C7 01 000 5 9 10 386 $67 $66
    MOV 传送 32[寄16+位移8]<=数32 $C7 01 000 5 9 10 386 $66 $67
    MOV 传送 32[寄32+位移8]<=数32 $C7 01 000 5 9 10 386 $6766
    MOV 传送 8[寄16+位移16]<=数8 $C6 10 000 5 9 10 8086 $67
    MOV 传送 8[寄32+位移32]<=数8 $C6 10 000 5 9 10 386 $67
    MOV 传送 16[寄16+位移16]<=数16 $C7 10 000 5 9 10 8086 $6766
    MOV 传送 16[寄32+位移32]<=数16 $C7 10 000 5 9 10 386 $67 $66
    MOV 传送 32[寄16+位移16]<=数32 $C7 10 000 5 9 10 386 $66 $67
    MOV 传送 32[寄32+位移32]<=数32 $C7 10 000 5 9 10 386 $6766
    MOVSB 传送字节串 $A4 8086
    MOVSW 传送字串 $A5 8086 $66
    MOVSD 传送双字串 $A5 386 $66
    MOVSX 符号传送 寄16<=寄8 $0FBE 11 1 3 386 $66
    MOVSX 符号传送 寄32<=寄8 $0FBE 11 1 3 386 $66
    MOVSX 符号传送 寄32<=寄16 $0FBF 11 1 3 386 $66
    MOVSX 符号传送 寄16<=8[寄16] $0FBE 00 1 5 386 $6667
    MOVSX 符号传送 寄16<=8[寄32] $0FBE 00 1 5 386 $67 $66
    MOVSX 符号传送 寄32<=8[寄16] $0FBE 00 1 5 386 $66 $67
    MOVSX 符号传送 寄32<=8[寄32] $0FBE 00 1 5 386 $6667
    MOVSX 符号传送 寄32<=16[寄16] $0FBF 00 1 5 386 $66 $67
    MOVSX 符号传送 寄32<=16[寄32] $0FBF 00 1 5 386 $6667
    MOVSX 符号传送 寄16<=8[寄16+位移8] $0FBE 01 1 5 9 386 $6667
    MOVSX 符号传送 寄16<=8[寄32+位移8] $0FBE 01 1 5 9 386 $67 $66
    MOVSX 符号传送 寄32<=8[寄16+位移8] $0FBE 01 1 5 9 386 $66 $67
    MOVSX 符号传送 寄32<=8[寄32+位移8] $0FBE 01 1 5 9 386 $6667
    MOVSX 符号传送 寄32<=16[寄16+位移8] $0FBF 01 1 5 9 386 $66 $67
    MOVSX 符号传送 寄32<=16[寄32+位移8] $0FBF 01 1 5 9 386 $6667
    MOVSX 符号传送 寄16<=8[寄16+位移16] $0FBE 10 1 5 9 386 $6667
    MOVSX 符号传送 寄16<=8[寄32+位移32] $0FBE 10 1 5 9 386 $67 $66
    MOVSX 符号传送 寄32<=8[寄16+位移16] $0FBE 10 1 5 9 386 $66 $67
    MOVSX 符号传送 寄32<=8[寄32+位移32] $0FBE 10 1 5 9 386 $6667
    MOVSX 符号传送 寄32<=16[寄16+位移16] $0FBF 10 1 5 9 386 $66 $67
    MOVSX 符号传送 寄32<=16[寄32+位移32] $0FBF 10 1 5 9 386 $6667
    MOVZX 零传送 寄16<=寄8 $0FB6 11 1 3 386 $66
    MOVZX 零传送 寄32<=寄8 $0FB6 11 1 3 386 $66
    MOVZX 零传送 寄32<=寄16 $0FB7 11 1 3 386 $66
    MOVZX 零传送 寄16<=8[寄16] $0FB6 00 1 5 386 $6667
    MOVZX 零传送 寄16<=8[寄32] $0FB6 00 1 5 386 $67 $66
    MOVZX 零传送 寄32<=8[寄16] $0FB6 00 1 5 386 $66 $67
    MOVZX 零传送 寄32<=8[寄32] $0FB6 00 1 5 386 $6667
    MOVZX 零传送 寄32<=16[寄16] $0FB7 00 1 5 386 $66 $67
    MOVZX 零传送 寄32<=16[寄32] $0FB7 00 1 5 386 $6667
    MOVZX 零传送 寄16<=8[寄16+位移8] $0FB6 01 1 5 9 386 $6667
    MOVZX 零传送 寄16<=8[寄32+位移8] $0FB6 01 1 5 9 386 $67 $66
    MOVZX 零传送 寄32<=8[寄16+位移8] $0FB6 01 1 5 9 386 $66 $67
    MOVZX 零传送 寄32<=8[寄32+位移8] $0FB6 01 1 5 9 386 $6667
    MOVZX 零传送 寄32<=16[寄16+位移8] $0FB7 01 1 5 9 386 $66 $67
    MOVZX 零传送 寄32<=16[寄32+位移8] $0FB7 01 1 5 9 386 $6667
    MOVZX 零传送 寄16<=8[寄16+位移16] $0FB6 10 1 5 9 386 $6667
    MOVZX 零传送 寄16<=8[寄32+位移32] $0FB6 10 1 5 9 386 $67 $66
    MOVZX 零传送 寄32<=8[寄16+位移16] $0FB6 10 1 5 9 386 $66 $67
    MOVZX 零传送 寄32<=8[寄32+位移32] $0FB6 10 1 5 9 386 $6667
    MOVZX 零传送 寄32<=16[寄16+位移16] $0FB7 10 1 5 9 386 $66 $67
    MOVZX 零传送 寄32<=16[寄32+位移32] $0FB7 10 1 5 9 386 $6667  
     
     
     
    相比高级语言中的栈结构,在汇编指令层面栈的任务更加复杂—生命周期必须与汇编指令行的切换正确对应。
     
    这里写图片描述

    图片说明:内存地址,汇编指令都为简写,用的十进制,栈空间1个格子大小是4*8=32位(对应32位操作系统),指令行长度都简化为1字节。为了突出建栈与撤栈的过程示意,函数都没有参数。栈空间也简化了,局部变量和参数都没有在其中。 实际执行顺序一列中对汇编指令行作用的进一步解释,左边为寄存器或栈空间地址,右边为其中的值。

    寄存器%esp既是栈指针,总是指向最下方第一个空着的栈空间地址。当栈栈指针向上移动后,下方的栈空间就相当于被释放掉了。 
    %ebp寄存器在此机制中相当重要,它存储着当前函数在栈中所被分配的局部空间的起始地址。在释放栈的过程中,leave指令将会移动栈指针至%ebp存储的内存地址的位置,再反过来将此起始位置中存储的值,既上一层调用函数的起始地址,存到%ebp中,为下一次进一步释放做准备,并进一步向上移动栈指针,为ret命令做准备。在此机制中,当前函数在栈中所被分配的局部空间的起始地址的前一格内存(既是+32bit)中存储的是上一层调用函数指令call的下一行指令的内存位置,leave之后的ret指令将会控制指令行流水线跳到此处。

    一些指令的简单说明: 
    push为入栈命令。 
    pop为出栈命令。 
    栈命令都跟伴随栈指针的移动。 
    mov在此过程中将一个寄存器中的值移到另一个寄存器。 
    call可以理解为goto。并将它的下一行指令地址存到栈中。 
    leave为mov+pop。为退出栈机制的重要一环。 
    ret也可以理解为goto。并移动栈指针。

    汇编指令行对应的源码应为:

    void main(){
        //一些计算
        f1();
        //继续计算
    }
    void f1(){
        //一些计算
        f2();
        //继续计算return;
    }
    void f2(){
        //一些计算return;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    感觉这东西有点烧脑,花了一下午时间终于整个捋顺了整个流程。 
    想理解好此过程,理解每个指令的作用,必须结合指令行地址,栈地址和寄存器一起来分析,否则很容易被绕晕。

     
     
    汇编代码: rep stos dword ptr es:[edi]

    在网上查了相关资料显示:
    /************************************************************/
    lea     edi,[ebp-0C0h] 
    mov     ecx,30h 
    mov     eax,0CCCCCCCCh 
    rep stos dword ptr es:[edi]
    rep指令的目的是重复其上面的指令.ECX的值是重复的次数.
    STOS指令的作用是将eax中的值拷贝到ES:EDI指向的地址.


    如果设置了direction flag, 那么edi会在该指令执行后减小, 
    如果没有设置direction flag, 那么edi的值会增加.

    REP可以是任何字符传指令(CMPS, LODS, MOVS, SCAS, STOS)的前缀. 
    REP能够引发其后的字符串指令被重复, 只要ecx的值不为0, 重复就会继续. 
    每一次字符串指令执行后, ecx的值都会减小.

    stos((store into String),意思是把eax的内容拷贝到目的地址。
    用法:stos dst,dst是一个目的地址,例如:stos dword ptr es:[edi]。dword ptr前缀告诉stos,一次拷贝双字(4个字节)的数据到目的地址。为什么一次非要拷贝双字呢?这和eax寄存器有关,到底神马关系,慢慢道来。。
    执行stos之前必须往eax(32为寄存器)放入要拷贝的数据。上图中,eax的内容是cccccccc,不用说都明白int3中断。
    这段代码是初始化堆栈和分配局部变量用的,往分配好的局部变量空间放入int3中断的原因是:防止该空间里的东东被意外执行。


    /************************************************************/

    想了想,没怎么明白,于是直接写了个函数,来加深一下印象:
    /************************************************************/
    #include <stdio.h>
    int main()
    {
     int i;
     int result=0;

     _asm{
      mov edi,edi
      mov edi,edi
     }

     for (i=0;i<20;++i)
      result+=2;
     return result;
    }
    /************************************************************/
    其中,
     _asm{
      mov edi,edi
      mov edi,edi
     }
    是没有任何作用的,只是为了让我们在反汇编时好定位代码的位置。

    然后用OD打开,找到我们的代码处:
    /************************************************************/


    /************************************************************/

    LEA: 目标地址传送指令: 将一个近地址指针写入到指定的寄存器。
    区别MOV传送指令:MOV传送的是地址所指的内容,而LEA只是地址。

    另外,在二进制中,0xCC 对应的就是汇编的:int 3指令(中断).

     
     
     
    ptr -- pointer (既指针)得缩写。
         汇编里面 ptr 是规定 的 字 (既保留字),是用来临时指定类型的。

      (可以理解为,ptr是临时的类型转换,相当于C语言中的强制类型转换)

    如 mov ax,bx ;  是把BX寄存器“里”的值赋予AX,由于二者都是寄存器,长度已定(word型),所以没有必要加“WORD”   
    mov ax,word ptr [bx];   是把内存地址等于“BX寄存器的值”的地方所存放的数据,赋予ax。由于只是给出一个内存地址,不知道希望赋予ax的,是byte还是word,所以可以用word明确指出;如果不用,既(mov ax, [bx];   )则在8086中是默认传递一个字,既两个字节给ax。

    总结,既有寄存器时可以,且一般不用ptr;没有时一定要用(防止当两个操作数的宽度不一样)。

    分类如下:


    (1)通过寄存器名指明要处理的数据的尺寸。(既有寄存器,可以不用ptr来限制了,系统会自动分析的)
    例如:
    下面的指令中,寄存器指明了指令进行的是字操作:
    mov ax,1
    mov bx,ds:[0]       这个的意思是段内的偏移地址是0,段地址是DS。详情请看本人其他日记
    mov ds,ax
    mov ds:[0],ax
    inc ax
    add ax,1000
    下面的指令中,寄存器指明了指令进行的是字节操作(因为是al):
    mov al,1
    mov al,bl
    mov al,ds:[0]
    mov ds:[0],al
    inc al
    add al,100
    (2)在没有寄存器名存在的情况下,既都是在内存,得用操作符 X ptr 指明内存单元的长度,X在汇编指令中可以为byte,word或者DWORD。要不然内存是片连续的区域,操作就乱了。
    例如:
    下面的指令中,用word ptr 指明了指令访问的内存单元是一个字单元:
    mov word ptr ds:[0],1
    inc word ptr [bx]
    inc word ptr ds:[0]
    add word ptr [bx],2
    下面的指令中,用byte ptr 指明了指令访问的内存单元是一个字节单元:
    mov byte ptr ds:[0],1
    inc byte ptr [bx]
    inc byte ptr ds:[0]
    add byte ptr [bx],2
       在没有寄存器参与的内存单元访问指令中,用word prt 或byte ptr 显性地指明所要访问的内存单元的长度是很必要的。否则,CPU无法得知所要访问的单元,还是字节单元。假如我们用Debug查看内存的结果如下:
    2000:1000 FF FF FF FF FF FF ......
    那么指令:
    mov ax,2000H
    mov ds,ax
    mov byte ptr [1000H],1
    将使内存中的内容变为:
    2000: 1000 01 FF FF FF FF FF ......
    而指令:
    mov ax,2000H
    mov ds,ax
    mov word ptr [1000H],1
    将使内存中的内容变为:
    2000:1000 01 00 FF FF FF FF ......
       这是因为 mov byte ptr [1000H],1访问的是地址为 ds:1000H 的字节单元,修改的是ds:1000H 单元的内容;而mov word ptr [1000H],1 访问的是地址为 ds:1000H 的字单元,修改的是 ds:1000H 和 ds:1001H 两个单元的内容。
    (3) 其他方法
       有些指令默认了访问的是字单元还是字节单元,比如:push [1000H] 就不用指明访问的是字单元还是字节单元,因为push指令只进行字操作。

    补充

    ptr也可以是是临时的类型转换,

    cmp word ptr[si],'#'
    是用si所指向的内存的连续两个字节与#比较
    要是改成
    cmp byte ptr[si],'#'
    那就是用si指向的那个存储单元的内容(一个字节)与#比较了

    jmp near ptr opd
    是无条件转移指令,转移到段内的标号opd所标识的位置(临时说明成近类型)
    若是
    jmp far ptr opd
    那就是转移到另外一个代码段的opd所标识的位置了(远类型)


        总结:

    不管用在什么位置,ptr的作用就是临时指定类型
    可以放在ptr前面的类型有byte(字节)、word(字)、dword(双字)、qword(四字)、tbyte(十字节)、far(远类型)和near(近类型)

  • 相关阅读:
    Mechanism of Loading Resources
    Dashboards (Android)
    Tips: compilation and creating new projects on Android 4.0
    设备方向
    【转】字符串分割(C++)
    Moving From Objective-C to C++
    Simulate android behaviors on win32
    【ybtoj高效进阶 21265】排队问题(fhq-Treap)(构造)
    【ybtoj高效进阶 21262】头文字 D(线段树)(数学)
    【ybtoj高效进阶 21261】头文字 C(单调队列优化DP)
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/7639392.html
Copyright © 2011-2022 走看看