汇编语言整理

汇编语言
第一章 基础知识

  1. 最早的计算机语言是机器语言,直接用二进制代码表示,程序执行快、占用空间小,缺点是语言难以掌握,程序调试困难,硬件要求高。
  2. 机器语言符号化产生了汇编语言,两者都是低级语言。
  3. 汇编程序中是ASCII码,该字符集有256个字符:每个字符占一个字节
    0-9:30H-39H 对应数字差30H
    A-B: 41H-5AH
    a-b:61H-7AH 对应大写字母差20H
  4. 寄存器相关,
    BP寄存器是不能分解的16位寄存器
    SI、DI也是不能分解的16位,与BP相似
    SP、IP寄存器为专用16位寄存器,不能挪作他用。
  5. FLAG标志
    条件标志:CAZSOP
    CF=0无进位或借位,CF=1有(八位结果超出256有进位)
    AF=0 第三位无进位或借位(一个字节八位数从右到左分别是第0-7位)
    ZF=0 运算结果不为0
    SF=0 结果符号位为0,正数
    OF=0 没有溢出(同符号相加得异号必定溢出)
    PF=0 结果低八位1的数目为奇数
    控制标志:DIT
    DF=0 串操作方向为正,左向右,CLD指令可以置DF=0,STD置1
    IF、TF为CPU工作指令
  6. 段寄存器及其指针
    CS:IP,代码段
    DS: SI, 数据段
    ES: DI, 附加段
    SS: SP, 堆栈段
  7. 逻辑地址表示成,段地址:偏移地址
    偏移地址=有效地址
    物理地址=短地址*10H+偏移地址
  8. 数据类型及强制转换方法
    字节: DB ,BYTE PTR 1字节
    字: DW ,WORD PTR 2字节
    双字: DD ,DWORD PTR 4字节
    四字: DQ 8字节
    十字: DT 10字节

第二章 语句结构

  1. 汇编程序采用分段结构,一个源程序包括:代码段、数据段、堆栈段(CS\DS\SS)。
  2. 8086CPU只提供4个段寄存器,最多同时操作四个段寄存器,如果引入其他段,先要把引入段的地址存入寄存器,原来的段会被覆盖。
  3. 汇编语句的格式:[名字项] 操作项 [操作数项] [注释项] ,其中操作项不可省去!
    名字项: 伪指令中:定义的段名、过程名(子程序proc名,类型NEAR/FAR、段地址、偏移地址为过程名的三大属性)、变量名(类型DW/DB/…、段地址、偏移地址为变量名的三大属性)、替代符(例如COUNT=$-变量名)、宏指令名(宏指令的助计符)
    指令中:指令标号(使用要后面加:,类型NEAR/FAR、段地址、偏移地址为指令标号的三大属性)
    操作项: 描述语句功能,是伪指令、指令、宏指令的操作助记符,在语句中必不可少。
    操作数项: 可以是常量、变量、寄存器、指令标号、过程名、段名、表达式,内容可以是数据或地址。
    注释项:分号;后面的
  4. 三大语句类型
    伪指令 SEGMENT 段定义伪指令,段名+SEGMENT开始,段名+ENDS结束。
    ASSUME 段联系伪指令,ASSUME+寄存器名+段名建立联系
    END 程序结束伪指令,END+START为常用格式
    EQU 替代伪指令,替代符+EUQ+表达式,替代符不占空间
    = 替代伪指令,与EQU相同用法,可重复替代
    $ 段内偏移地址指针,即为当前指的偏移地址
    ORG 设置 的 伪 指 令 , O R G + 常 量 表 达 式 , 将 常 量 表 达 式 赋 的伪指令,ORG+常量表达式,将常量表达式赋 ORG+
    PROC 过程定义,过程名+PROC+[类型:NEAR/FAR]
    ENDP 过程结束,过程名+ENDP
    MACRO 宏定义,宏指令名+MACRO+[形参表]
    ENDM 宏定义结束
    定义与结束之间叫宏体,调用宏指令称为宏调用
    这些是伪指令的操作项,也称伪指令的操作助记符,本质还是操作项。
    因此,操作项=操作助记符,是一个很大的概念,它可能是运算、操作、定义等等
    指令 格式为:
    【标号】+操作助记符(操作项)
    宏指令 即为MACRO中定义的指令。

第三章 指令系统

  1. 操作数的寻址方式:(关注SRC的寻址)
    ① 寄存器寻址 ADD AL,BL
    ② 立即寻址 MOV AL,68 描述常量而非地址,不能用于DST
    ③ 存储器寻址 操作数在存储器中,操作数项要描述其存放地址。
    i. 直接寻址 MOV AL,DS:[0010H] ;用段名+【常数】直接表示
    MOV AX,WORD PTR VAR1 ;用变量名直接表示(段名隐含)
    ii. 寄存器间接寻址 以寄存器内容做偏移地址,可用16位寄存器:SI、DI、BX、BP,使用时必须在中括号里面,其中SI、DI、BX默认DS,BP默认SS。
    偏移地址=(16位寄存器) ;括号表示是寄存器的内容,即里面的值
    MOV AX,[SI]
    MOV AL,ES:[DI] ;访问非默认的DS,需要标注段名
    MOV BYTE PTR [BX],98H ;间接寻址不描述类型,需要PTR指定访问类型。
    iii. 寄存器相对寻址 位移量D+间接寻址里的16位寄存器
    D可以是变量名(定义的数组名)也可以是常数
    偏移地址=(16位寄存器)+D ;物理地址是偏移地址再加上相应段寄存器的地址即可
    MOV AL,[SI+06H]
    MOV AL,06H[SI]
    MOV AL,[DI+VAR]
    MOV AL,VAR[BX]
    iv. 基址变址寻址 BX,BP称基址寄存器(BX默认DS,BP默认SS)
    SI,DI称变址寄存器(SI源变址寄存器,DI目标变址寄存器)
    偏移地址=(基址寄存器)+(变址寄存器)
    MOV AL,[BX]+[SI]
    MOV AL,[BX+SI] ;两种形式一样
    与间接寻址类似,基址变址寻址也要注意访问类型问题和段前缀是否默认!
    v. 相对基址变址寻址
    偏移地址=(基址寄存器)+(变址寄存器)+ 位移量D
    D可以是变量名(定义的数组名)也可以是常数
    MOV AL,[BX+SI+06H]
    MOV AL,06H[BX][SI]
    MOV AL,[BP+DI+VAR]
    MOV AL,VAR[BX][DI]
    ④ 隐含寻址 例如乘法,默认对AX/AL操作
    MUL BX

  2. 转移地址的寻址:
    ① 段内直接寻址 转移指令+目标指令标号
    转移指令与目标指令在同一个代码段,不改CS,根据目标指令标号改IP即可。
    段内直接转移有短近之分,默认为近(16位),短距离转移要加SHORT(8位),短距离转移的指令代码比近距离转移少一个字节。
    ② 段内间接寻址 转移指令+寄存器/字存储单元
    JMP BX ;BX寄存器内容作为转移目标地址
    JMP WORD PTR [SI] ;寄存器间接寻址读取数据短一个字作为转移目标地址
    ③ 段间直接寻址 转移指令+FAR+PTR+目标指令标号
    转移指令与目标指令不在同一个代码段,CS和IP都改
    ④ 段间间接寻址 转移指令+双字类型变量
    从主存两个连续字存储单元中获取转移目标地址,低地址的字修改IP,高地址的字修改CS,从而实现段间转移
    JMP DWORD PTR [BX]
    JMP ADDR ;ADDR定义成双字变量(DD)
    3.助记符汇总
    操作项:(操作助记符)
    DUP:重复分配空间: 重复次数+DUP(?)
    数据传送类指令:
    MOV数据传送 MOV AX,BX 1.要注意DST和SRC类型一致
    2.不能同时采用存储器寻址,可事先转换成寄存器寻址
    3.DST不能是CS(IP也不行)
    4.段寄存器DS、ES不能MOV进立即数
    XCHG互换 XCHG AX,BX 两个通用寄存器可以这样用其他形式需要具体分析
    LEA 取偏移地址 LEA SI,ARR1 把偏移地址送DST,
    SRC为变量或者标号等同于 MOV SI,OFFSET ARR1
    但是未设定BX值时形如MOV SI,OFFSET [BX+6] 是错误的!!
    XLAT查表存 XLAT 把BX+AL的值做偏移地址访问数据段,读一个字节数据存入AL,隐含操作数,BX存表首偏移地址,AL存序号

    PUSH入栈 PUSH OPR 不能入栈立即数,步骤为1. SP=SP-2 2.(SP)=OPR
    OPR必须是字类型,不明确类型的默认为字,可以是CS
    POP出栈 POP OPR 步骤为1.OPR=(SP) 2.SP=SP+2
    OPR必须是字类型,不能是CS
    I/O指令
    IN输入 IN AL/AX PORT/DX 直接寻址PORT为8位
    间接寻址DX为16位
    当PORT超过8位,需要放在DX里面
    OUT输出 OUT PORT/DX AL/AX 与IN相同
    完整地址传送指令
    LDS 段地址送DS,偏移地址送指定的16位寄存器
    LES 段地址送ES,偏移地址送指定的16位寄存器
    标志传送指令
    LAHF 标志寄存器低八位存AH
    SAHF AH存标志寄存器低八位
    PUSHF 标志寄存器内容入栈
    POPF 栈顶出栈并存标志寄存器

运算符:
OFFSET 取偏移地址: OFFSET+变量/标号
SEG 取段地址: SEG+变量/标号
PTR 重新定义类型: 只能用在地址表达式里
新类型(BYTE、WORD、DWORD/NEAR、FAR)+PTR+变量/标号/地址表达式

ADD加法		ADD AX,BX	对所有标志位都有影响,CF记录最高位进位
ADC带进位加法	ADC DX,CX	加的时候同时加上CF
INC 加一		INC AX		不影响CF但是影响其他的状态标志符

SUB减法			SUB AX,BX	对所有标志位都有影响,CF记录最高位的借位
SBB带进位减法	SBB DX,CX	减的时候同时减去CF
DEC减一		DEC AX		不影响CF但是影响其他的状态标志符
CMP比较		CMP AX,BX	进行减法操作,影响全部状态,但是不保存运算结果。
							CF=1则AX

逻辑运算符:按位进行
AND 按位与 影响ZF,PF,SF,CF,OF,并对CF和OF清零
OR 按位或 影响ZF,PF,SF,CF,OF,并对CF和OF清零
XOR 按位异或 影响ZF,PF,SF,CF,OF,并对CF和OF清零
NOT 非 不影响FLAGS
TEST 测试 进行AND操作,但是不保存结果
移位操作指令:P61 指令+DST+CNT
逻辑: SHL 补零,移出的进CF 影响CF,OF,ZF,SF,PF
SHR
算术: SAL 补零,移出的进CF(保符号) 影响CF,OF,ZF,SF,PF
SAR 补符号,移出的进CF
循环: ROL 移出的补,同时赋给CF
ROR
带进位:RCL 补CF,移出的进CF
RCR
循环位移只影响CF和OF,对OF影响只在位移次数CNT=1时有效,否则无定义。
CNT=1时若位移前后符号不变,则OF=0,否则OF=1
算术移位作用于有符号数有乘除效果,左移一位等于该数乘上2(前提是OF=0,表示符号位未变,未溢出),右移一位等于该数除以2(移位所得数为商,余数在CF),无符号逻辑运算也有此效果。

串操作:
源串地址:DS:SI 目的串地址:ES:DI
串操作方向由DF状态决定,默认DF=0正向,然后字节/字串指针相应加减1/2。
CLD置正向 串首到串尾,设置DF=0,SI/DI加
STD置反向 串尾到串首,设置DF=1,SI/DI减
串单次的操作:
1.MOVS串传送 源串和目的串地址隐含在SI,DI(以默认的CLD为例)
MOVSB字节串传送 步骤:1. (ES:DI)(DS:SI) 2. SISI+1, DIDI+1
MOVSW字串传送 步骤:1. (ES:DI)(DS:SI) 2. SISI+2, DIDI+2
串传送不影响各种条件标志。
2.CMPS串比较 源串和目的串地址隐含在SI,DI(以默认的CLD为例)
CMPSB字节串比较 步骤:1. (ES:DI)-(DS:SI) 2. SISI+1, DIDI+1
CMPSW字串比较 步骤:1. (ES:DI)-(DS:SI) 2. SISI+2, DIDI+2
串比较会根据减法结果设置各种条件标志。
3.SCAS串搜索 目的串地址隐含在DI(以默认的CLD为例),还隐含AL/AX
SCASB字节串搜索 步骤:1. AL-(ES:DI),若ZF=1搜索成功 2. DIDI+1
SCASW字串搜索 步骤:1. AX-(ES:DI),若ZF=1搜索成功 2. DIDI+2
串搜索会根据减法结果设置各种条件标志。
4.STOS串存数 目的串地址隐含在DI(以默认的CLD为例),还隐含AL/AX
STOSB字节串存数 步骤:1. (ES:DI)AL 2. DIDI+1
STOSW字串存数 步骤:1. (ES:DI)AX 2. DIDI+2
5.LODS串取数 目的串地址隐含在DI(以默认的CLD为例),还隐含AL/AX
LODSB字节串存数 步骤:1. AL(ES:DI) 2. DIDI+1
LODSW字串存数 步骤:1. AX(ES:DI) 2. DIDI+2
串重复前缀:(以CX为计数器,放在单次操作前作为重复前缀)

  1. REP前缀 (for)
    REP MOVS/STOS/LODS CX=0停止
  2. REPE/REPZ前缀(for+break) 比较两个串是否完全相同
    REPE/REPZ CMPS/SCAS CX!=0且ZF=1重复,否则停止
  3. REPNE/REPNZ 前缀 比较两个串是否完全不同
    REPNE/REPNZ CMPS/SCAS CX!=0且ZF=0重复,否则停止

程序控制,跳转指令:
1.无条件跳转 JMP 这部分跟第三章的2.转移地址寻址相互联系
2.条件跳转 条件标志状态作为检测条件
单个条件标志状态作为检测条件:
JC LABEL CF=1跳LEBEL,否则顺序执行
JNC LABEL CF=0跳LEBEL,否则顺序执行
JZ/JE LABEL ZF=1跳LEBEL,否则顺序执行
JNZ/JNE LABEL ZF=0跳LEBEL,否则顺序执行
JS LABEL SF=1跳LEBEL,否则顺序执行
JNS LABEL SF=0跳LEBEL,否则顺序执行
JO LABEL OF=1跳LEBEL,否则顺序执行
JNO LABEL OF=0跳LEBEL,否则顺序执行
JP/JPE LABEL PF=1跳LEBEL,否则顺序执行
JNP/JPO LABEL PF=0跳LEBEL,否则顺序执行
多个条件标志状态作为检测条件:
无符号数比较:
JA/JNBE LABEL CF=ZF=0 即 >
JAE/JNB LABEL CF=0 即 ≥
JB/JNAE LABEL CF=1 即 <
JBE/JNA LABEL CF=1或ZF=1 即 ≤
有符号数比较:
JG/JNLE LABEL SF=OF且ZF=0 即 >
JG/JNLE LABEL SF=OF 即 ≥
JG/JNLE LABEL SF !=OF 即 <
JG/JNLE LABEL SF!=OF或ZF=1 即 ≤
注意!带条件的跳转只能是段内短距离转移,范围为-128~+127字节,超过了此范围需要改用JMP来跳转!
3.循环指令 LOOP LABEL
等效于:1. DEC CX 2. JNZ LABEL
由此可见,LOOP也是段内短距离转移

补充:
TYPE求类型 TYPE ARRY ARRY是DB类型则为1,DW类型则为2,以此类推
LENGTH 求长度 LENGTH ARRY 实际是求ARRY中最外层DUP的循环次数,默认为1
SIZE 求存储空间 SIZE ARRY SIZE=LENGTHTYPE
举个例子,ARRY DW 5 DUP(?) 则SIZE ARRY求得为5
2=10
这三个操作项跟OFFSET用法类似。

祝愿期末考试得高分!!
作者按

2021年12月20日星期一初稿

你可能感兴趣的:(经验分享)