第一部分.嵌入式汇编
第一章.基础知识
CPU执行机器指令,利用编译器将高级语言源程序转换成目标程序(代码),计算机系统最终运行目标程序。
CPU基本功能:执行机器指令,暂存少量数据、访问寄存器。
ASCII码:0~9
对应30H~39H
,A~Z
对应41H~5AH
,a~z
对应61H~7AH
,' '(空)对应20H
,'\0'对应0H
。
第二章.IA-32处理器基本功能
保护方式:32根地址线有效,寻址4GB
的物理空间。
实地址方式:处理器重新开始运行后的最初工作方式。仅能访问1MB
物理地址空间,范围00000H~FFFFFH
。支持存储器分段管理,每个存储段大小限于64KB
。
通用寄存器:
32位寄存器:EAX EBX ECX EDX EBP ESP EDI ESI
16位寄存器:AX BX CX DX BP SP DI SI
高8位寄存器:AH BH CH DH
低8位寄存器:AL BL CL DL
标志寄存器:EFLAGS
,32位,含有一组状态标志,系统标志,控制标志。
CF
:第0位,进位标志,运算结果最高位产生进位/借位时置1,否则清0。
ZF
:第6位,零标志,运算结果为0置1,否则清0。
SF
:第7位,符号标志,运算结果最高位为1(负数)时置1,否则清0。
OF
:第11位,溢出标志,有符号数加减结果溢出(127/-128,32767/-23768,231-1/-231)置1,否则清0。
PF:第2位,奇偶标志,结果最低字节(8位)中1的个数,偶数置1,奇数清0。 AF:第4位,辅助进位标志,反映算术运算第三位或最低四位是否有进位/借位,有则置1,无则清0。
段寄存器
代码段、数据段、堆栈段。
逻辑地址:段号:段内地址 或 段号:偏移
物理地址 = 段起始地址 + 偏移
段寄存器:代码段寄存器CS
、堆栈段寄存器SS
、数据段寄存器DS
、附加段寄存器ES
、FS
、GS
。
CS
指定当前代码段,SS
指定当前堆栈段,DS
指定当前数据段。
寻址方式
立即寻址:MOV EAX, 12345678H
,仅限源操作数。
寄存器寻址:ADD DI, BX
,执行速度快,源/目标操作数均可使用。
直接寻址:MOV ECX, [95480H]
,有效(物理)地址,源/目标操作数均可使用,但不可两个操作数均为存储单元。
寄存器寻址:SUB DX,[EBX]
,间接给出存储单元有效地址,要求和直接寻址类似。
通用表示:MOV EBX, [EDI+EAX*4+300H]
,基址寄存器(32位),变址寄存器(32位,无ESP),比例因子(1/2/4/8)
位移量(8位/16位/32位,自动扩展为32位)。
指令指针寄存器
EIP/IP
:指向下一条指令地址(有效地址),CS
+EIP
= 物理地址。
堆栈
对应高级语言的栈,后进先出,堆栈段寄存器SS存有栈号,ESP存放偏移(有效地址),指向栈顶。
用途:(1)保护寄存器内容或保护现场。(2)保存返回地址。(3)传递参数。(4)安排局部变量,临时变量。
传送指令(不影响标志位)
MOV DEST, SRC:
将数据从通用寄存器/存储单元/立即数传入通用寄存器/存储单元。
XCHG OPED1, OPRD2:
内容交换,通用寄存器/存储单元,尺寸一致,不能同时为存储单元。
简单加减指令(运算不受标志寄存器影响,但会改变标志寄存器)
ADD DEST, SRC
:加法,操作数尺寸一致,SRC
为通用寄存器/存储单元/立即数,DEST
为通用寄存器/存储单元。
SUB DEST, SRC
:前减后,尺寸一致,SRC
为通用寄存器/存储单元/立即数,DEST
为通用寄存器/存储单元。
INC DEST
:DEST++,操作数为通用寄存器/存储单元。(不影响CF
)
DEC DEST
:DEST--,操作数为通用寄存器/存储单元。(不影响CF
)
NEG
DEST
:取相反数,操作数为通用寄存器/存储单元。
状态标志操作指令
CLC
:清进位标志,将CF位清0。
STC
:置进位标志,将CF位置1。
CMC
:进位标志取反,CF位由0变为1/从1变为0。
LAHF
:获取状态标志,将标志寄存器低8位送到通用寄存器AH
中,EFLAGS
不变。
SAHF
:设置状态标志,将AH中第0、2、4、6、7位传入EFLAGS
中,保留位1、3、5不变。
带进位加法指令
ADC DEST, SRC
:带进位加法,DEST+=SRC+CF
,操作数要求与ADD
一致。
SBB DEST, SRC
:带借位减法,DEST-=SRC+CF
,操作数要求与SUB
一致。
条件转移指令(不影响标志位,改变EIP
,范围一个代码段64K
)
Jcc LABEL
:这里举几个重要例子,更多翻书P45
。
JZ LABEL
:ZF=1,运算结果等于0转移。
JNZ LABEL
:ZF=0,运算结果不等于0转移。
JB LABEL
:PF=1,无符号,比较结果<转移。(JNB
,不低于转移)
JL LABEL
:SF!=OF,带符号,比较结果<转移。(JNL
,不小于转移)
JA LABEL
:CF=0&&ZF=0
,无符号,比较结果>转移。(JNA
,不高于转移)
JG LABEL
:ZF=0&&SF=OF
,带符号,比较结果>转移。(JNG
,不大于转移)
JMP LABEL
:无条件段内直接转移,类似goto
语句。
比较指令
CMP DEST, SRC
:前减后,改变标志寄存器,不改变操作数,两操作数尺寸一致。
取有效地址指令
LEA REG, OPRD
:把OPRD
(存储器)有效地址送到REG
(通用寄存器16/32位),类似指针,不影响标志位
LEA EBX, [EDI + EAX * 4 + 300H]
,可用于取地址,也可用于计算(不影响标志位)。
堆栈操作指令
PUSH SRC
:源操作数(32/16位通用寄存器,段寄存器,双字/字存储单元,立即数)压栈,
ESP减存储大小,数据送到ESP位置。
POP DEST
:弹栈,将一个双字/字数据送到DEST
(32/16位通用寄存器,段寄存器,双字/字存储单元,立即数)
根据目标操作数大小弹栈,至少弹出一个字(16位)。
PUSHA
:将AX、CX、DX、BX、SP、BP、SI、DI
依次压栈,SP-=16
POPA
:从堆栈以与PUSHA
相反顺序送到通用寄存器,SP+=16
PUSHAD
:将EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI
依次压栈,SP-=32
POPAD
:从堆栈以与PUSHAD
相反顺序送到通用寄存器,SP+=32
第三章.程序设计初步
过程调用和返回指令
过程(procedure):子程序。调用子程序(过程,函数):控制转移,考虑返回。
过程调用指令:由主程序转移到子程序;过程返回指令:由子程序返回到主程序。
CALL LABEL
:过程调用,LABEL是程序中的标号或过程名。
段内调用:压返回地址EIP
入栈,再实现转移。段间调用:压CS(代码段)、返回地址EIP
入栈,再转移。
RET
:过程返回,堆栈弹出返回地址偏移,送到EIP
,转移到该地址。
参数传递
寄存器传递法:一般ECX
、EDX
传递入口参数,EAX
传递出口参数;
堆栈传递法:主程序在调用子程序之前,将需传递参数依次压栈,再从堆栈中取入口参数。(不占寄存器,复杂)
入口参数从右向左压栈。堆栈中可以存放动态局部变量。
算术逻辑运算指令
MUL OPRD
:无符号乘法,由操作数位数决定与AL/AX/EAX
相乘送入AX/DX:AX/EDX:EAX
中。
IMUL OPRD
:有符号乘法,与MUL
类似。
IMUL DEST, SRC
:双操作数有符号乘DEST=DEST*SRC
(DEST
16/32位通用寄存器,SRC
寄存器/存储单元/立即数)
IMUL DEST, SRC1, SRC2
:DEST
16/32位通用寄存器,SRC1
为通用寄存器/存储单元,SRC2
为立即数。
DIV OPRD
:无符号数除法,OPRD
为除数,8/16/32位对应被除数AX/DX:AX/EDX:EAX
,结果商在低位,余数高位
IDIV OPRD
:有符号数除法,被除数/除数均视为有符号数,不能整除时余数符号与被除数一致,绝对值小于除数
带符号扩展指令
CBW
:字节转换为字,将寄存器AL
中符号扩展到AH
。
CWD
:字转换为双字,将AX
中符号扩展到DX
。
CDQ
:双字转换为四字,将EAX
中符号扩展到EDX
。
CWDE
:字转换为双字,将AX
中符号扩展到EAX
高16位。
无符号数扩展:异或XOR指令把高8/16/32位直接清0。
扩展传送指令(不改变源操作数,不影响标志寄存器)
MOVSX DEST, SRC
:符号扩展传送,将SRC
符号扩展后送到DEST
,DEST
尺寸必须大于SRC
尺寸。 (SRC
为通用寄存器/存储单元,8/16位,DEST
为通用寄存器,16/32位)。
MOVZX DEST, SRC
:零(无符号)扩展传送,高位置0,要求与MOVSX
一致。
逻辑运算指令
NOT OPRD
:否运算,操作数按位取反,送回OPRD
。
AND DEST, SRC
:按位与运算,使CF=0,OF=0,PF/ZF/SF
反映运算结果。
OR DEST, SRC
:按位或运算,结果送DEST
。
XOR DEST, SRC
:按位异或运算,CF=0,OF=0,PF/ZF/SF
反映运算结果。
TEST DEST, SRC
:两个操作数按位与,结果不送到DEST
,仅改变标志位,改变同AND
。
移位指令(OPRD
通用寄存器/存储单元,CF
(进位标志)受影响、SF/ZF/PF
反映移位结果、OF
情况复杂)
SAL OPRD, count
:算术左移,count
为8位立即数或寄存器CL
(移位数0~31,截取低5位),用0补足,高位进CF
。
SHL OPRD, count
:逻辑左移,同SAL
。
SAR OPRD, count
:算术右移,符号位保存不变,最低位进入CF位,count同上。
SHR OPRD, count
:逻辑右移,高位用0补足,低位进入CF位,count同上。
循环移位指令(OPRD
通用寄存器/存储单元,CF
(进位标志)受影响、SF/ZF/PF
反映移位结果、OF
情况复杂)
ROL OPRD, count
:左循环移位,每左移一位,最高位移入最低位,且移入CF,
count要求同移位指令。
ROR OPRD, count
:右循环移位,每右移一位,最低位移入最高位,且移入CF
。
RCL OPRD, count
:带进位左循环移位,每左移一位,最高位移入CF
位,CF
位移入最低位。
RCR OPRD, count
:带进位右循环移位,每右移一位,最低位移入CF
位,CF
位移入最高位。
双精度移位指令(目的OPRD1
为通用寄存器/存储器单元,字/双字;源OPRD2
为寄存器,尺寸与OPRD1
一致,count同上
移动一位,符号位变化,置OF
(溢出位)为1,否则清0,同时影响SF/ZF/PF
,AF
无定义)
SHLD OPRD1,OPRD2,count
:双精度左移,OPRD1
左移count位,最后一位传CF
,低位用OPRD2
高count位补。
SHRD OPRD1,OPRD2,count
:双精度右移,OPRD1
右移count位,最后一位传CF
,高位用OPRD2
低count位补。
分支程序
编译优化:不优化,多与内存打交道;优化使速度最大化后,多与寄存器打交道,减少转移。
无条件和条件转移指令
段内转移(近转移):仅重新设置指令寄存器EIP
转移,未重置CS
。
段间转移(远转移):重置EIP
和CS
,转移后的指令在另一个代码段中。
JMP LABEL
:无条件段内直接转移,机器指令由操作码OP和地址差rel组成,EIP+rel
实现转移,相对转移。
JMP OPRD
:无条件段内间接转移,OPRD
是32位通用寄存器/双字存储单元,内容直接存入EIP
。
无条件段间转移在后面章节介绍。
条件转移指令:相对转移,EIP+rel
表示转移位置。
循环程序
LOOP LABEL
:计数循环,ECX-=1
(不影响标志位),结果不为0则转到LABEL
继续执行。最多进行232次。
LOOPE LABEL
:等于/全零循环,ECX-=1
(不影响标志位)若结果不为0,且ZF=1
(零标志),转到LABEL
处。
LOOPZ LABEL
:同上。
LOOPNE LABEL
:不等于/非零循环,ECX-=1
(不影响标志位),若结果不为0,且ZF=0
,转到LABEL
处。
LOOPNZ LABEL
:同上。
JECXZ LABEL
:计数器转移,当ECX=0
时转移到LABEL
处。循环开始前使用,保证n=0(while(i<n))时正常执行。
子程序设计
堆栈传递入口参数,寄存器(EAX
)传递出口参数。
寄存器作为局部变量效率高,堆栈安排局部变量数量多。
约定会保护寄存器EBX/ESI/EDI/EBP
,不保护EAX/ECX/EDX
,自己保护。
子程序说明:(1)子程序名(或入口标号);(2)子程序功能描述;(3)子程序入口参数和出口参数。
第四章.字符串操作和位操作
第五章.VC目标代码的阅读理解
第二部分.完整汇编
第六章.汇编语言
第七章.BIOS和虚拟机
第八章.输入输出和中断
第九章.保护方式程序设计
notes:主要面向NUAA学生所学《汇编语言》课程,课本为《新概念汇编语言》,鉴于该书知识较为繁杂,内容较多,做作业、实验、课设时不方便定位每章知识点,在此对每章知识点做出简单归纳,随缘更新,欢迎交流指正。