x86汇编语言期末复习
本人对于易错点的整理,欢迎食用。(临近期末、格式没有调整)
一、Intel中央处理器
32位的CPU按其主要功能通常可分为6大部件:总线接口部件、执行部件、指令预取部件、指令译码部件、分段部件、分页部件。
标志寄存器中CF可以指进位,也可以指借位。
标志寄存器的理解:根据每次执行设置新的标志寄存器,会把相应的所有位都赋值,至于取哪一位用,要看程序员使用的指令。
x86的三种工作方式:实地址方式(1MB物理存储空间)、保护方式(4GB物理存储空间)、虚拟8086方式
二、主存储器
x86以字节作为最小寻址单位。
x86采用的是小端存储。
一个数和它的反码之和为0FFH。
符号常量不是变量,不会为其分配空间。
ASCII字符串一般只跟在db后面,当字符串长度小于等于2时,可以跟在dw后面,当字符串长度小于等于4时,可以跟在dd后面。
以下两种表达含义不同,s1符合小端存储。
s1 dw '12'
s2 db '12'
内存管理有两种模型:扁平内存模型和分段内存模型。
实方式下物理地址的形成(掌握):
-
16根地址线,为了能够表示20位物理地址,8086的设计人员提出了地址由段寄存器和段内偏移地址组成的方案。
-
指令物理地址 PA = (CS)左移四位 + (IP)
-
栈顶物理地址 PA = (SS)左移四位 + (IP)
-
数据物理地址 PA = (DS或ES、FS、GS)左移四位 + 16位偏移地址
保护方式下物理地址的形成(了解):
-
保护方式下采用描述符来记录一个分段的信息。
-
特权级:应用程序<系统扩展程序<操作系统服务程序<操作系统内核
-
描述符表是描述符的集合
三、寻址方式
x86寻址方式共有6种:立即寻址、寄存器寻址、直接寻址、寄存器间接寻址、变址寻址、基址加变址寻址。
(后四种为存储器寻址)
立即寻址:
-
立即数可写成仅有常量组成的数值表达式。
-
要注意数值的大小是否在另一个操作数类型所限定的范围内。
寄存器寻址:
- 寄存器本质就是一个符号地址
- 对于经常存取的操作数,采用寄存器寻址方式能提高工作效率。
- 寄存器R中的内容作为操作数
直接寻址:
- 变量、[变量]、变量±一个数值表达式、[变量±一个数值表达式]、变量[±一个数值表达式]
- 两个变量相减,实际上是两个变量的地址相减
寄存器间接寻址:
- 使用格式[R]
- 本质上就是,R中存放了一个地址,通过[R]访问R中存放的地址对应的存储的内容。
mov byte ptr[ebx],32H
- byte ptr 不可以省略
变址寻址:
-
寄存器中的内容成一个比例因子再和给定的位移量相加。
-
V[R*F]、[R*F+V]、[R*F]+V
-
F只能是1,2,4,8
-
R为esp时,F只能是1
-
若V是变量,则操作数类型为V的类型,若V是常量,则类型不明确
当数组变量是全局变量时,变址寻址;为局部变量时,为基址加变址寻址。
基址加变址寻址:
- V[BR+IR*F]、[BR+IR*F+V]、V[BR][IR*F]
- 变址寄存器IR乘比例因子,加上基址寄存器BR内容,再加上位移量V
- F只能是1,2,4,8
- 若V是变量,则操作数类型为V的类型,若V是常量,则类型不明确
变址寻址和基址加变址寻址中都有寄存器,据此来记忆,可以通过书上的例题来加深理解。
四、常用机器指令
movsx、movzx、xchg
push、pop:将立即数、寄存器、段寄存器、存储器中的一个字、双字压入栈中(不能只操作一个字节)
pushad、popad
lea:当x是子程序中定义的局部变量时,则只能用lea。lea eax,[eax+ebx],可以实现eax和ebx的加法
inc、add、adc
dec、sub、sbb
neg :求补
cmp
imul opd,ops ; imul opd,ops,n ; imul ops
opd只能是寄存器、n只能是立即数,单操作数时,ops不能是立即数(不能确定类型)
mul
div ops、idiv ops
(ah,al)、(dx,ax)、(edx,eax)
如果被除数太大,而除数太小,可能产生溢出异常
cbw、cwd、cwde、cdq
not、and、test、or、xor(其中test执行与但是结果不赋给opd)
sal、shl、shr、sar、rol、ror(不带进位循环)、rcl、rcr(带进位循环)、shld、shrd
五、一些细节
.686P 处理器选择伪指令
.model 存储模型 [,语言类型]
Windows提供API函数 语言类型都是stdcall:采用堆栈法传参数、由被调用者在返回时释放参数占用的空间(在子程序内释放堆栈)
而c语言类型:堆栈法传参数、由调用者释放参数占用空间。
.data
.code
.stack
.const
end [表达式]
如果end后面带有表达式,其值必须是一个存储器地址,该地址为程序的启动地址,一般情况下表达式是一个标号或者一个子程序的名字。(也就是通过end指定启动函数、或者通过VS配置程序执行的入口点)
条件转移指令(根据名字很容易记忆)
jg、jl是有符号条件转移、ja、jb是无符号条件转移
循环控制指令
loop 标号:看ecx的值,若ecx、cx不为0,则转移到标号处执行。
子程序相关内容
子程序名 proc
子程序名 endp
call 过程名
;比jmp多了 将eip进栈的过程
ret n
;esp出栈到eip
;n 为原参数字节数的和(不包括eip!)
子程序间传递参数:寄存器法、约定单元法、堆栈法
local u:dword,w:dword
定义局部变量必须紧跟在proc后面
函数名 proto [函数类型][语言类型][ [参数名]:[参数类型] ,...]
汇编语言默认采用紧凑对其模式
extern 符号:类型,[符号:类型]
public 符号
C语言中的int类型和汇编中的sdword类型对应。
宏指令名 macro 形式参数(例如: myadd macro v1,v2,v3)
endm
中断
实方式下的中断矢量表:大小为1KB,起始位置固定地从物理地址0开始
按照IP、CS先后存放
INT n
EFLAGS进栈、CS扩展成32位进栈、EIP进栈
IRET EIP出栈,出栈32位、低16位到CX,EFLAGS出栈
0:[n*4] ->IP
0:[n*4+2] -> CS
CLI 关中断、STI、开中断
(iii) 用系统功能调用装入
可使用25H号DOS功能调用设置中断向量。
功能:设置中断向量,建立由(AL)指定类型号的软中断指令。
参数:DS:中断处理程序段首址, DX:中断处理程序偏移地址
AL:中断号n
调用格式:
MOV AX,中断处理程序段首址
MOV DS, AX
LEA DX,中断处理程序名
或者:MOV DX, OFFSET 中断处理程序名
MOV AH,25H
MOV AL,n (n为中断号)
INT 21H
(iv) 取得中断号是n的中断处理程序入口地址的方法
使用35号DOS功能调用取中断号是n的中断向量入口地址
调用格式:
MOV AL,n
MOV AH, 35H
INT 21H
返回结果: (BX) = 中断号是n的中断处理程序偏移地址
(ES) = 中断号是n的中断处理程序段地址