汇编教程3-升级的准备
经过了前面2篇教程的学习,我向大家应该对汇编程序有了比较深刻的影响了吧?所以不能教扫盲帖了,可以升级了,不过,在升级前,不免的对一些基础的东西要了解一下。
一、 CPU的内部寄存器:
4个16位的通用寄存器:
_____________________________
|__ah________|____al_________| ax
|__bh________|____bl_________| bx
|__ch________|____cl_________| cx
|__dh________|____dl_________| dx
其中:一般来说,ax用作乘除法中的累加器,bx可存放地址,也可作指针寄存器。
cx可存放循环次数,dx可存放I/O号。
ah为两个4位,al为两个4位,所以,ax为16位,其余的以此类推
4个16位的指针寄存器
______________________________
|bp基址指针
|_____________________________
|sp堆栈指针 用于做堆栈顶端指针
|_____________________________
|si源变址寄存器
|________________这两个有时用来做变址器,存放数据以及运算结果
|di目标寄存器
|_____________________________
4个16位的内部寄存器:
______________________________
|cs:代码段寄存器
|_____________________________
|ds:数据段寄存器
|_____________________________
|es:附加段寄存器
|_____________________________
|ss:堆栈段寄存器
|_____________________________
标志寄存器:
____________________________
ip指令指针 |
___________________________|
flagsh | flagsl |
_____________|_____________|状态标志
16位的标志寄存器,只用了其中的9个标志位,6各状态标志位,3个控制标志位。
fh:
________________
|of|df|if|tf|
___|__|__|__|__|
fl:
___________________________
|sf|zf|空 |af|空 |pf|空|cf|
|__|__|_ |__|_ |__|__|__|
具体的每个标志位的意思我简单的讲一下,如果要编程还要自己看一下书
cf:进位标志,进位/借位的时候cf=1
pf:奇偶标志,当指令执行结果的低8位中含有偶数个1时,pf=1,f否则为0
af:辅助进位标志,加减法的结果的低字节向高4位有进/借位时af=1.
zf:0标志。运算结果为0时,zf=1
sf:符号标志,他和运算结果的最高位相同。负数为1,正数为1
of:溢出标志,补码运算有溢出时为1
上面是状态标志,下面是控制标志:
df:方向标志,控制数据串操作指令的步进方向
if:中断允许标志
tf:跟踪标志,为调试程序而设置的,喜欢破解的人要特别注意这个
二、寻址方式:
这个东西非讲不可,没办法,理解起来有困难,我尽量说清楚把!
1、固定寻址
这种方式,操作数隐藏在指令中,例如,daa,操作数隐含在al中
2、立即寻址
用来表示常数,例如:
mov ax,9 ;9为立即数
mov ax 1234h ;1234h为立即数,
3、寄存器寻址
例如:mov ax,cx
执行前ax=9602h,cx=2081h
执行后ax=2081h.
4、存储器寻址
这种方式下,操作数一般是代码段之外的数据段、堆栈段,附加段中的存储单元,指令给出的存储单元的地址或表达式。一般而言,一条指令的目的操作数和原操作数不能同为存储器操作数。存储器寻址又分为5种:
直接寻址:操作数的有效地址由指令直接给出,是带有方括号的常量或变量。 物理地址pa=16*(ds)+偏移地址nn
例如:
mov al,[1000h] 将ds段的1000h单元的内容传到al,注意方括号和不加方括号的区别。
mov ax,[1000h]
将ds段的1000h内容传到ax,注意ah,al的内容。另外,不要忽视物理地址,这是很总要的信息,破解还是编程,都必须考虑到这个东西。
mov al,es:[2000h] 表示将es段的2000h内容传到al,这叫段超越前缀。
寄存器间接寻址:
格式:[bx,bp,si或di].地址由基址寄存器或变址寄存器给出
如果指令中使用的是bx,si,di则用ds作为段地址
pa=16*(ds)+(bx/si/di)
例如:mov al,[bx] 设bx的内容为1000h,则把ds段的1000h的内容传到al
如果用bp,则用ss做段地址
pa=16*(ss)+(bp)
这种寻址方式一般用来对一维数组操作,改变bx等寄存器的值就可以对连续的存储器单元操作。
以后的就有点复杂了,注意看了,
基址寻址:
格式:偏移量[bx或bp]
例如:mov al,80h[bp] 设bp内容=2040h,则将堆栈段的20c0单元的内容传到al
为什么?因为在16进制下2040h+80h=20c0h不信可以到windows计算器中试一试。其实这条语句等同于mov al,[80h+bp]
操作数的有效地址ea=(bx)/(bp)+偏移量
变址寻址
格式:偏移量[si或di]
操作数的有效地址ea=(si)/(di)+偏移量
是不是和上面差不多?
我们来看一个操作数组的例子:
mov ax,array1[si]
mov array2[di],ax
懂了么? 为什么不能mov array2[di] array1[si]? 因为两个操作数不能同为变量。
别急,这里我没有给出这两种方式的物理地址,算是给大家的一个题目,很容易的,想想看!
基址变址寻址
其实就是上面两个结合起来
格式:偏移量[bx/bp + si/di]
pa=16*ds+(bx/bp + si/di +偏移量)
或者16*ss+(bx/bp + si/di +偏移量)
注意bx和bp选择的不同,段地址会不同,前者用ds,后者用ss
好了,就这么多,看着是有些头痛,有什么不懂就回帖问我吧,本来是要画图的,我偷了懒。
初学者慢慢看,多看几次,别想一次看懂,有信心就可以了!下一章我们讲循环语句,好了,睡觉去了,说不定明天要点名了。