汇编杂记

一、操作指令类型

 操作数 说明
reg88 位通用寄存器:AH、AL、BH、BL、CH、CL、DH、DL
reg16 16 位通用寄存器:AX、BX、CX、DX、SI、DI、SP、BP
reg32  32 位通用寄存器:EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP
reg通用寄存器
sreg   16 位段寄存器:CS、DS、SS、ES、FS、GS
imm8 位、16 位或 32 位立即数
imm88 位立即数,字节型数值
imm1616 位立即数,字类型数值
imm3232 位立即数,双字型数值
reg/mem88 位操作数,可以是 8 位通用寄存器或内存字节
reg/mem1616 位立即数,可以是 16 位通用寄存器或内存字
reg/mem3232 位立即数,可以是 32 位通用寄存器或内存双字
mem8位、16 位或 32 位内存操作数
32位通用寄存器
EAX    EBP         
EBX    ESP         
ECX     ESI       
EDX     EDI       


    



二、指令操作


    1).硬件和软件;
        windwo系统计算机,安装Microsoft visual studio;


    2).段寄存器。基址寄存器、指针,分配地址,    


    3).DUP 初始化字段


    4). BYTE    8 位无符号整数,B 代表字节
        SBYTE    8 位有符号整数,S 代表有符号
        WORD    16 位无符号整数
        SWORD    16 位有符号整数
        DWORD    32 位无符号整数,D 代表双(字)
        SDWORD    32 位有符号整数,SD 代表有符号双(字)
        FWORD    48 位整数(保护模式中的远指针)
        QWORD    64 位整数,Q 代表四(字)
        TBYTE    80 位(10 字节)整数,T 代表 10 字节
        REAL4    32 位(4 字节)IEEE 短实数
        REAL8    64 位(8 字节)IEEE 长实数
        REAL10    80 位(10 字节)IEEE 扩展实数


    5).BSD编码转换压缩: 
        1.fld 加载实数到浮点寄存器堆栈;
        2.fbstp 将其转换压缩为BCD
        3.伪代码 = 号,声明常量,为代码通俗易懂,便于理解。
        4.$当前地址计数器
            list BYTE 10,20,30,40,50
            listSize = ($ - list)


    6).EQU伪指令:把一个符号名称与一个整数表达式或任意文本连接起来,在同一源文件中,用EQU 定义的
    符号不能给重新定义.


    7).TEXTEQU伪指令,类似EQU


    8).64位编程。取消环境说明,编译说明,栈的大小声明,取消不必要参数说明


    9).mnemonic 助记符-指令
       operands 操作数
       comment 说明
       [label:] mnemonic [operands][;comment]
       destination 目的地
       source 来源
       操作数有 3 种基本类型:
        (1).立即数——用数字文本表达式
        (2).寄存器操作数——使用 CPU 内已命名的寄存器
        (3).内存操作数——引用内存位置
       
    10).MOVZX 指令: 进行全0扩展并使用,支持无符号操作
        MOVSX 指令: 进行全1扩展,支持有符号的
        LAHF 指令: 加载状态标志位到AH,指令将 EFLAGS 寄存器的低字节复制到 AH
        SAHF 指令: 报错AH内容到标志位,指令奖AH内容复制到EFLAGS
        XCHG 指令: 交换两个操作数内容,


    11).   标志名称    溢岀    方向    中断    符号      零        辅助进位    奇偶    进位标志位
              符号        OF        DF        IF        SF        ZF        AF            PE            CF


    12). INC 加法指令;DEC 减法指令
        ADD 相加操作,SUB 相减操作;NEG 把操作数转换为二进制补码,将操作数取反


    13). OFFSET 运算符返回数据标号的偏移量
        ALING 对齐一个变量到边界,
        PRT 重写一个已经被声明过的操作数的大小类型,PTR 必须与一个标准汇编数据类型一起使用

            .data
            myDouble DWORD 12345678h
            .code
            mov ax,myDouble;不允许这个操作,使用下一句
            mov ax,WORD PTR myDouble


        TYPE 返回变量单个元素的大小,返回的是标识符存储类型(BYTE、WORD、DWORD 等)的字节数。
        LENGTHOF 计算组中元素的个数
        SIZEOF 运算符则为 LENGTHOF 与 TYPE 的乘积
        LABEL  为数据段中定义的下一个变量提供不同的名称和大小属性
        JMP 指令无条件跳转到目标地址,该地址用代码标号来标识,并被汇编器转换成偏移量
        LOOP 指令,正式称为按照 ECX 计数器循环,将程序块重复特定次数


    14). 堆栈由高到低生长的,PUSH 入栈, POP 出栈
        PUSHFD 指令把32位EFLAGS寄存器内容入栈
        POPFD 指令则把栈顶单元内容弹出到 EFLAGS 寄存器
        PUSHADPUSHAPOPAD POPA 指令按照 EAX、ECX、EDX、EBX、ESP(执行 PUSHAD 之前的值)、EBP、ESI 和 EDI 的顺序,将所有 32 位通用寄存器压入堆栈。


    15).定义一个过程,过程用 PROC ENDP 伪指令来定义
        子过程(subroutine)
        术语过程(procedure)来指代子程序
        命名为 Receives ( 接收 )
        过程的返回 Returns ( 返回 )
        先决条件 (preconditions)。
        列表命名为 Requires


    16).条件判断
        CMD 指令比较整数
        
        CMP结果                    ZF    CF        *|*      CMP结果                    标志位
        目的操作数 < 源操作数    0    1        *|*        目的操作数 < 源操作数    SF ≠ OF
        目的操作数 > 源操作数    0    0        *|*        目的操作数 > 源操作数    SF=OF
        目的操作数 = 源操作数    1    0        *|*        目的操作数 = 源操作数    ZF=1
        
        
        OR 或:
            X    Y    X∨Y
            0    0    0
            0    1    1
            1    0    1
            1    1    1
            
        AND 与:
            X    Y    X^Y
            0    0    0
            0    1    0
            1    0    0
            1    1    1
            
        无符号操作数: A (大于)、 B(小于)、E(等于)
        有符号操作数: G (大于)、 L(小于)、E(等于)
        
        JG  大于跳转
        JL  小于跳转
        JE  等于跳转
        
        *================================================*
        | JZ    为零跳转    ZF=1    JNO    无溢出跳转    OF=0 |
        | JNZ    非零跳转    ZF=0    JS    有符号跳转    SF=1 |
        | JC    进位跳转    CF=1    JNS    无符号跳转    SF=0 |
        | JNC    无进位跳转    CF=0    JP    偶校验跳转    PF=1 |
        | JO    溢出跳转    OF=1    JNP    奇校验跳转    PF=0 |
        *================================================*
         
        *=======================================*
        | 助记符    说明                        |
        | JE    相等跳转 (leftOp=rightOp)        |
        | JNE    不相等跳转 (leftOp M rightOp)    |
        | JCXZ    CX=0 跳转                        |
        | JECXZ    ECX=0 跳转                        |
        | JRCXZ    RCX=0 跳转(64 位模式)            |
        *=======================================*
        LOOPZ 为零控制转向目的标号,零标志位必须置 1


    17).表驱动选择
    18).有限状态机
    19).循环
            *===================*===================*
            |.REPEAT            |.IF conditionl        |
            |  staements        |    statements        |
            |.UNTIL condition    |[.ELSEIF condition2|
            *===================*    statements ]    |
            |.WHILE condition    |[.ELSE                |
            | statements        |    statements ]    |
            |.ENDW                |.ENDIF                |
            *===================*===================*



三、汇编语言整数运算


    1).位移动 (bit shifting) ,这些操作都会影响溢出标志位和进位标志位。
        SH(移动),SA(算术移动),
        RO(循环移动),RC(带进位循环移动)
        SH_D(双精度移动)


    2).多个字移动
        10011001 CF=1 10011001 CF =0
        CF 10011001 CF=1
        EAX、EBX、ECX、EDX、ESI、EDI、ESP、EBP
        (EAX*32)+(EXA*4)


    3).存储空间,字段提取
        MUL 无符号乘法
        IMUL 有符号乘法
        
        2000H * 0100H=00200000H,CF=1
        10000000000000   *    100000000= 1000000000000000000000
        8192    *    256 = 2097152
        
        进制位高半部分不是低半部分的符号扩展
        IMUL reg16/mem16,imm8
        IMUL reg16/mem16
        IMUL reg/mem32,imm32
        .data
        startTime DWORD ?
        procTime1 DWORD ?
        procTime2 DWORD ?
        .code
        call GetMesconds ;获取开始时间
        mov startTime,eax
        .
        call First ProcedureToTest
        .
        call getMsecounds
        sub eax,startTime
        mov procTime1,eax


    4)DIV 无符号除法
    
    5)操作数,是输入输出的数值,每个指令后跟操作数为0~3个,操作数可以是寄存器、内存操作数、整数表达式和输入输出端口
    生成内存操作数有不同的方法,使用变量名、带方括号的寄存器等。变量名代表变量地址,并指示计算机使用给定地址的内存内容
        
    6)IDIV 有符号数除法,操作数与DIV指令相同。
    执行8位除法之前,被除数(AX)必须完成符号扩展。余数的符号总是与被除数相同
    示例:
    .data
    byteVal SBYTE -48;
    
    使用之前进行符号扩展:
    符号扩展指将一个数的最高位复制到包含该数的变量或寄存器的所有高位中
    符号扩展指令(CBW、CWD、CDQ)


    CBW(字节转字)指令将AL的符号位扩展到AH,保留了数据的符号,
    CBW 指令将AL的符号扩展到AH
    
    CWD(字转双字)将AX的符号位扩展到DX  ;DX:AX
    
    CDQ(双字转四字) 指令将EAX 的符号位扩展到EDX ;EDX:EAX
    
    7).MUL 乘法执行指令 (忽略成绩的高32位)
        如果MUL指令产生的乘积大于32位,则跳转到jc 指令处


    8).ADC 带进位加法,要求操作数大小必须一致,
    当两个8位整数相加是,产生16位和数是,将进位标志位置1,然后和进位标志位与DL寄存器相加


    9).SBB 接位减法 指令从目的操作数中减去源操作数和进位标志位的值。


    10).ASCLL 数学十进制加、减、乘、除运算。
    第二种方法需要在执行每对 ASCII 数字相加后,用特殊指令来调整和数。有四类指令用于处理 ASCII 加法、减法、乘法和除法,如下所示:


    AAA    (执行加法后进行 ASCII 调整)    AAM    (执行乘法后进行 ASCII 调整)
    AAS    (执行减法后进行 ASCII 调整)    AAD    (执行除法前进行 ASCII 调整


    两个ASCll 数字相加,其二进制结果存放在AL中。


    11).DAA (加法后的十进制调整)指令将和数转换为压缩十进制格式
        DAS (减法后的十进制调整)指令将其转换为压缩十进制格式。



四、汇编高级过程


    1).堆栈帧简介,堆栈帧是一块堆栈保留区域,用于存放被传递得实际参数、子程序得返回值、局部变量以及被保存的寄存器
        ①.被传递的实际参数。如果有,则压入堆栈
        ②.当子程序被调用时,使该子程序的返回值压入堆栈。
        ③.子程序开始执行时,EEP被压入堆栈。
        ④.设置EBP等于ESP。从这个是开始,EBP就变成了该子程序所有参数的引用基址。
        ⑤.如果有局部变量,修改ESP以便在堆栈中为这些变量预留空间。
        ⑥.如果需要保存寄存器,就将他们压入堆栈。


    2).堆栈传参的缺点;
        ①.性能下降
        ②.访问时先进行参数入栈,先从最后一个参数开始入栈,依次递减


    3).堆空间调用规范:C 规范 、STDCALL 调用规范


    4).LEA 指令返回间接操作数的地址。由于间接操作数中包含一个或多个寄存器,因此会在运行时计算这个操作数的偏移量。


    5).ENTER指令被调用过程自动创建堆栈帧,他为局部变量保留堆栈空间,把EBP 入栈。
        EBP 入栈;把EBP 设置为堆栈帧的基址;为局部变量保留空间。


    6).LOCAL 声明一个或多个变量名,并定义其大小。ENTER则只为局部变量保留一块未命名的堆栈空间,如果要使用LOCAL伪指令,它必须紧跟在PRIC伪指令的后面


    7).无限递归子程序对自身的调用是递归中最显而易见的类型。

        INCLUDE Irvine32.inc
        .data
        endlessStr BYTE "This recursion never stops",0
        .code
        main PROC
            call Endless
            exit
        main ENDP
        
        Endless PROC
            mov edx,OFFSET endlessStr
            call WriteString
            call Endless
            ret                ;从不执行
        Endless ENDP
        END main


    8).INVOKE 伪指令,只用于32位模式,将参数入栈(安装MODEL伪指令的语言说明符所指定的顺序)并调用过程. 


    9).ADDR运算符只能与INVOKE 一起使用仪汇编直接操作数进行


    10).PROC伪指令允许在声明过程时,添加上用逗号分隔的参数名列表
        [distance] [langtype] [visibility] [prologuearg]
        代表实现可以用名称来引用参数,而不是计算堆栈偏移量,
        distance NEAR 或FAR。指定汇编器生成的RET 指定在声明过程时定义参数,使用逗号分隔
        langtype 指令调用规范(参数的传递规范)。
        visibility 指定过程对其他模块的可见性。
        prologuearg 指定会影响开始和结尾代码生成的参数
        
    11).一个程序可以调用lrvme32链接库过程,反之,也可以包含被C++程序调用的过程。为了提供这样的灵活性,PROC伪指令的属性域允许程序指定传递参数的语言规范,并能覆盖.MODEL 伪指令的指定的默认语言规范。


    12).汇编语言PROTO伪指令:指定程序的外部过程


    13).ExitProcess PROTO
        .code
        mov ecx,0
        call ExitProcess
        
        MySub PROTO
        .INVOKE MySub
        MySub PROC        ;过程实现
        MySub ENDP
        
    14). PROTO 伪指令可以覆盖.MODEL 伪指令中的参数传递协议。但它必须与过程的PROC声明一致:
    Examle1 PROTO C,
        parm1:DWORD,parm2:DWORD
    PROTO 伪指令帮助汇编器比较过程调用和过程定义的参数列表


    15).MASM 会检测的错误


    16).WriteStackFrame 用于显示当前过程堆栈帧的内容,其中包括过程参数的堆栈参数、返回地址、局部变量和被保存的寄存器。


    17).EXTERN 现在当前模块之外的过程的过程名,和堆栈帧大小。
    EXTERNDEF 可以代替PUBLIC 和EXTERN
    INCLUDE 复制参数到模块 


    18).java 虚拟机工作原理
    *===================================*=======================================*
    |数据类型    所占字节    格式         |数据类型    所占字节    格式            |
    |char        2            Unicode 字符|long         8            有符号整数        |
    |byte        1            有符号整数    |float        4            IEEE 单精度实数    |
    |short        2            有符号整数    |double        8            IEEE 双精度实数    |
    |int        4            有符号整数     |
    *===================================*=======================================*
    dcmp 指令比较双字,fcmp指令比较浮点数。
    goto 指令无条件跳转到一个标号
    jsr 指令调用用标号定义的子程序。
    ifle 指令当弹出数值小于等于0时跳转到标号。
    ifgt 指令当弹出数值大于等于0时跳转到标号。
    



五、字符串基本指令


    1).传送字符串:MOVSBMOVSWMOVSD 指令将数据从ESI指向的内存位置复制到EDI指向的内存位置。
    (根据方向标志位的值) ECX用于计数(传送的位数)ESI 内存增加,EDI减少


    2).比较字符串:CMPSBCMPSWCMPSD、分别由ESI和EDI寻址的内存数据
        REPE 前缀重置比较, 重复比较知道ECX=0,或者找到两个不相等的双字。


    3).扫描字符串:SCASBSCASWSCASD、比较累加器(AL、AX或EAX)与EDI寻址的内存数据
        在字符串组中寻找一个数值,结合REPE(或REPZ)前缀,当ECX>0且AL\AX\EAX的值等于内存中每个联系的值


    4).保存字符串数据:STOSBSTOSWSTOSB 将累加器内容保存到EDI寻址的内存位置
        
    5).从字符串加载到累加器:LODSBLODSWLODSD 将ESI 寻址的内存数据加载到累加器
        LODS很少与REP前缀一起使用,
        将ESI指向的内存的值加载一个字节或者一个字到AL/AX/EAX的。ESI按照方向标志位的状态递增或递减。
    
    CLD:方向标志位清零
    STD:方向标志位置1
    6).lrvine32 字符串过程详解。


    7).数组操作
        ①.2维数组,行偏移量放在基址寄存器中,列偏移量放在变址寄存器中。
        汇编器计数的常量Rowsize 是表中每一行的字节数。
        计算数组行之和,EBX=表偏移量,EAX=行索引
        ECX=按字节计的行大小
        ②.比例因子
        如果是为字数组编写代码,则需要将变址操作数乘以比例因子2,
        如果数组类型为双字,则比例因子为4.


    8).java字符串处理
    *store_x 指令从运行时堆栈弹出改字符串的引用
    *load_x 指令把引用压入操作数栈。



六、汇编语言结构和宏:


    定义结构 identifier structureType<initializer-list>
    identifier 为命名规则
    initializer-list 可选项,该选项就是一个用逗号分隔的汇编时常数列表,
    空括号<> 使结构包含的是结构定义的默认字段值
    引用结构并初始化,在设置默认值时,用<>,多个字段声明默认数值,用逗号隔开
    1).定义结构STRUCTENDS伪指令。


    2).对齐结构字段,ALIGN datatype.


    3).使用 TYPE 和SIZEOF 运算符可以引用结构函数和结构名称.
    例如:

Employee STRUCT
     IdNum BYTE "0000000"
     LastName BYTE 30 DUP(0)
     ALIGN WORD 
     Years WORD 0
     ALIGN DWORD
     SalaryHistory DWORD 0,0,0,0
Employee ENDS


    给定数据定义:

        .data
        worker Employee<>
        TYPE Employee    ;60
        SIZEOF Employee    ;60
        SIZEOF worker    ;60


    结论:type 运算符返回的标识符存储类型的字节数。
    LENGTHOF 运算符返回的时数组元素的个数,
    SIZEOF 返回的则是LENGTHOF 与TYPE的乘积。
    使用OFFSET 运算符能获取到结构变量中的一个字段的地址


    4).间接操作数寻址,使用ESI ,引用间接操作数时需要PTR运算符
    MOV esi,OFFSET worker
    MOV ax,(Employee PTR [esi]).Years


    5).结构嵌套
        每个结构中的每个字段都有相对于结构第一个字节的偏移量。联合中所有的字段则都是起始于同一个偏移量。
        一个联合的存储大小即为其最大字段的长度
        不是结构的组成部分需要用UNION 和ENDS 伪指令来定义
        unionname UNION
            union-fields
        unionname ENDS


    6)宏过程是一个命名的汇编语言块。一旦定义好了,他就老爷在程序中被调用。在调用宏过程时,其代码副本被直接插入到程序中该宏被调用的位置
        这种种自动插入代码也被称为内联展开,尽管从技术上来说没有CALl,但按照惯例仍然说调用宏过程
        使用INCLUDE伪指令复制到程序里
        宏在汇编器预处理阶段进行扩展,在这个阶段中。
        宏在汇编预处理阶段进行扩展,

        PrintX MACRO char
            mov al,'x'
            call WriteChar
        ENDM
        
        .code
        PrintX


        
        Macroname 必须是源代码中在此之前被定义宏的名称。每个实参都是文本值,用以替换宏的一个形参 实参的顺序要与形参一致,但是两种数量不须相同。
        
        mPutchar 'A'


        push eax
        mov al,'A'
        1 call WriteChar
        1 pop eax,20
        L1:
        mPutchar al ;宏调用
        inc al,'A'
        1 call WriteChar
        1 pop eax
        mov al,'A‘
        使用REQ限定符,可以指令必须得宏形参。齐国被调用得宏灭有实参与规定得形参相匹配,那么汇编器将显示出错误
        mPutchar MACRO char:REQ
            push eax
            mov al,char
            call WriteChar
            pop  eax
        ENDM
        忽略宏展开的时的注释,使用双分号;;


    7).汇编语言条件汇编伪指令
        *======================*====================================================================================*
        |伪指令                    |说明                                                                                |
        |IF expression            |若 expression 为真(非零)则允许汇编。可能的关系运算符为 LT、GT、EQ、NE、LE 和 GE    |
        |IFB<argument>            |若 argument 为空则允许汇编。实参名必须用尖括号(<>)括起来                        |
        |IFNB<argument>            |若 argument 为非空则允许汇编。实参名必须用尖括号(<>)括起来                        |
        |IFIDN<arg1>,<arg2>        |若两个实参相等(相同)则允许汇编。采用区分大小写的比较                                |
        |IFIDNI<arg1 >,<arg2>    |若两个实参相等(相同)则允许汇编。采用不区分大小写的比较                            |
        |IFDIF<arg1 >,<arg2>    |若两个实参不相等则允许汇编。采用区分大小写的比较                                    |
        |IFDIFI<arg1>,<arg2>    |若两个实参不相等则允许汇编。采用不区分大小写的比较                                    |
        |IFDIF name                |若 name 已定义则允许汇编                                                            |
        |IFNDEF name            |若 name 还未定义则允许汇编                                                            |
        |ENDIF                    |结束用一个条件汇编伪指令开始的代码块                                                |
        |ELSE                    |若条件为真,则终止汇编之前的语句。若条件为假,ELSE 汇编语句直到遇到下一个 ENDIF    |
        |ELSEIF expression        |若之前条件伪指令指定的条件为假,而当前表达式为真,则汇编全部语句直到出现 ENDIF        |
        |EXITM                     |立即退出宏,阻止所有后续宏语句的展开                                                |
        *===========================================================================================================*


    8).IFIDN和IFIDNI伪指令,对两个参数进行比较
        IFIDNI 不进行区分大小写,如果相等则返回真.
        IFIDN 如果不想等,咋返回假
        矩阵相乘运行


    9).& 替换运算符 ; <> 文字文本运算符 ; !文字字符运算符 ; %展开运算符
        !强制预处理程序八预先定义的运算符当作普通的字符处理
        < > 把一个或多个字符组合成一个文字文本,以防止预处理程序把列表中的成员解释为独立的参数。
        % 展开文本宏并将常量表达式转换为文本形式。
        若使用的是 TEXTEQU,%运算符就是计算常量表达式,再把结果转换为整数。


    10).宏函数,与宏过程不同的地方是,宏函数总会通过EXITM伪指令返回一个常量(整数或字符串)。
    调用宏函数时它的参数列表必须用括号括起来.


    11).while 、repeat、for、forc。
        while 伪指令根据一个布尔表达式来重复语句块
        REPEAT 伪指令根据计数器的只来重复语句块
        FOR 伪指令通过遍历字符列表来重复语句块
        FORC 伪指令通过遍历字符串来重复语句块



七、汇编语言MS-Windows


    1). 未完待续....


八、浮点数处理与指令编码


    1).IEEE二进制浮点小数表示
        浮点E科学表示法,规范化操作的逆操作说将二进制浮点数反规格化,移动二进制小数点,直到阶码为0
    2). 0.5表示1/2 



九、高级语言调用汇编语言的规范


    1).一种语言使用的规范
        调用过程需要保存哪些寄存器
        传递参数的方法:用寄存器、用堆栈、共享内存,或者其他方法
        主调程序调用过程时,参数传递的顺序。
        参数传递方法时传值还是传引用
        过程调用后,如何回复堆栈指针
        函数如何向主调用程序返回结果


    2).MASM 使用.MODEL 伪指令确定若干重要的程序特性:内存模式类型、过程命名模式以及参数传递规则。
        其他所有模式都可以用于16位实地
    
        
    
    
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值