目录
0,复习一下cpu中的寄存器:
1)数据寄存器
2)变址寄存器
3)指针寄存器
4)段寄存器(s结尾 segment)
5)指令指针寄存器
6)实模式和保护模式:
1,操作数的寻址方式
1)立即寻址方式
2)寄存器寻址方式
3)直接寻址方式
4)寄存器间接寻址方式
5)寄存器相对寻址方式
6)基址加变址寻址方式
7)相对基址加变址寻址方式
8)32位cpu比16位cpu多一种寻址方式
32位cpu有4个32位的通用寄存器eax, ebx, ecx, dex和16位的cpu中AX, BX, CX, DX作为区分,同时增加了2个fs, gs段寄存器。
其中32位cpu的通用寄存器,对低16位的存取,不影响高16位的数据。在16位的cpu中,ax, bx, cx, dx不可以作为基址和变址
寄存器来存放存储单元的地址。但在32位cpu中,通用寄存器不仅可以传送数据、暂存数据保存逻辑运算结果,而且还可以
作为指针寄存器,所以32位的通用寄存器更具有通用性。
寄存器功能:
ax: 称为累加器(Accumulator),累加器可用于乘,除,输入/输出等操作,他们的实用频率很高。
bx: 称为基地址寄存器(Base register),它可作为存储器指针来使用。
cx: 称为计数寄存器(Count register),在循环和字符串操作时,要用它来控制循环次数;在位操作时,当移多位时,
用CL来指明移位的位数。(循环中实用,移位时实用,CX)
dx:称为数据寄存器(Data register),在进行乘,除运算时。它可作为默认的操作数参与运算,也可以用于存放I/O的端口地址
si 和 di: 称为变址寄存器(Index register),它们主要用于存放存储单元在段内的偏移量。
用它们可以实现多种寄存器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。
变址寄存器不可分割成8位寄存器(ax,bx,cx,dx都可以分为高8位和低8位的如AH+AL)。作为通用寄存器,也可存储
算术逻辑运算的操作数和运算结果。
它们可作为一般的存储器指针使用,但在字符串操作指令中,有特定要求。
主要用于存放堆栈内存单元的偏移量,用它们可以实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元
提供方便。
bp:称为基指针寄存器(Base pointer),用它可直接存取堆栈中的数据。
sp:称为堆栈指针寄存器(stack pointer),用它只可访问栈顶。
根据内存分段的管理模式而设置的,内存单元的物理地址由段寄存器的值和一个偏移量组合而成的,这样可以用两个较少位数
的值访问一个较大物理空间的内存地址。
cs:代码段寄存器(code segment register)
ds:数据段寄存器(data segment register)
es:附加段寄存器(extra segment register)
ss:堆栈段寄存器(stack segment register)
fs: 附加段寄存器(extra segment register)
gs:附加段寄存器(extra segment register)
ip:称为指令指针寄存器(instructional pointer)是存放下次将要执行的指令在代码段的偏移量。
(在具有预取指令功能的系统中,下次执行的指令通常已被预取到指令队列中。不考虑这种情况)
是32位cpu的,实模式和16位相同,另外一个模式有一个新的概念叫“选择子(selector)”。
在指令中,指定操作数或操作数存放位置的方法称为寻址方式。在16位cpu中总共有7个方式:
立即寻址、寄存器寻址、直接寻址、寄存器间接寻址、
寄存器相对寻址、基址加变址寻址、相对基址加变址寻址。
后面用“(x)”表示x的值, 如: (AX)表示寄存器AX的值。
概念:操作数作为指令的一部分而直接写在指令中,这种操作数叫做立即数,这种方式叫立即寻址方式。
在指令中,立即数不能作为指令中的第一操作数,这和“赋值语句的左边不能是常量”规定一致。
(ps,原文中写的是立即数不能作为第二操作数,但是都知道mov ah, 80h第二个就是立即数,而且第一操作数是目的,
第二操作数是源,也就是把源赋值给目的,就和c语言常量不能做左值一样,所以这里应该是个错误,遂改为第一操作数)
方法: mov oprd1, oprd2 注意长度一致,如AH是8位后面的立即数也要是8位,不能是16位。
例子: mov ah, 80h 没有分号,记住高高低低原则
add ax, 1234h
mov ecx, 123456h
概念:指令所要的操作数,已经存储在某寄存器中,或把目标操作数存入寄存器。把在指令中指出所使用寄存器的
寻址方式称为寄存器寻址。 源和目的操作数都是寄存器。
1.源操作数是寄存器寻址方式 add varw, ax mov varb, bh (w 半字, b, 字节)
2.目的操作数是寄存器寻址方式 add ax, 1234h mov bh, 78h
3.源和目的操作数都是寄存器寻址 mov ax, bx mov bh, bl
因为都在寄存器中,执行过程会减少读/写存储单元的次数,所以具有较快的执行速度。
概念:指令所要的操作数存放在内存中,在指令中直接给出该操作数的有效地址,叫做直接寻址方式。
注意:立即寻址方式和直接寻址方式的书写格式的不同,直接寻址的地址要写在括号“[”,“]”内。在程序中,
直接地址通常用内 存变量名来表示,如:MOV BX, VARW,其中,VARW是内存字变量。
这中寻址方式要考虑段寄存器!!! 物理地址 = 段地址x16 + 偏移地址。 那么直接寻址就要计算物理地址,会和
段寄存器有相关的操作。默认段寄存器是ds, 如果指定是其他的寄存器则需要在第一个操作数加段前缀如
mov es:[1000h], ax
有代表性又醒目。
概念:操作数在存储器中,操作数的有效地址用si, di(变址寄存器), BX(基址寄存器), BP(基指针寄存器)之一来指定,称为寄存器间接寻址。
寻址方式的计算方法: PA(物理地址) = 段地址x16 + (si / di / bx / bp) # “ / ” 或的意思
若有效地址用si, di, bx之一来指定, 缺省的段寄存器是ds,
若有效地址用bp来指定,缺省的段寄存器是ss(堆栈段)。
概念:操作数在存储器中,其有效地址是一个基址寄存器(bx, bp)或变址寄存器(si, di)的内容 和 指令中8位/16位偏移量之和。
若有效地址用si, di, bx之一来指定, 缺省的段寄存器是ds,
若有效地址用bp来指定,缺省的段寄存器是ss(堆栈段)。
寻址方式的计算方法:PA = 段地址 x 16 + ( EA(偏移地址) = (bx / bp/ si/ di) + (8bit / 16bit)偏移量)
这个图很好理解了, 这种方式算出的是偏移地址,然后要加上段地址x16才是真正的物理地址。
指令中给出的8位/16位偏移量用补码表示。在计算有效地址时,如果偏移量是8位,则进行符号扩展成16位。当所得的有效地址超过0FFFFH,则取其64K的模。
概念:操作数在存储器中,其有效地址是一个基址寄存器(bx, bp)和一个变址寄存器(si, di)的内容之和。
寻址方式的计算方法:PA = 段地址X16 + (EA = (bx / bp) + (si / di))
在不使用段超越前缀的情况下,规定:如果有效地址中含有BP,则缺省的段寄存器为SS;否则,缺省的段寄存器为DS。
概念:操作数在存储器中,其有效地址是一个基址寄存器(bx, bp)的值,一个变址寄存器(si, di)的值和指令中
的8位/16位偏移量之和。
寻址方式计算方法: EA = (bx / bp) + (si / di) + (8 bit / 16bit) 偏移量
用D1[i]来访问一维数组D1的第i个元素,它的寻址有一个自由度,用D2[i][j]来访问二维数组D2的第i行、第j列的元素,
其寻址 有二个自由度。多一个可变的量,其寻址方式的灵活度也就相应提高了。
相对基址加变址寻址方式有多种等价的书写方式,下面的书写格式都是正确的,并且其寻址含义也是一致的。
MOV AX, [BX+SI+1000H] MOV AX, 1000H[BX+SI]
MOV AX, 1000H[BX][SI] MOV AX, 1000H[SI][BX]
但书写格式BX [1000+SI]和SI[1000H+BX]等是错误的,即所用寄存器不能在“[“,”]”之外,该限制对寄存器相对寻址方式
的书写也同样起作用。
指令中给出的8位/16位偏移量用补码表示。在计算有效地址时,如果偏移量是8位,则进行符号扩展成16位。
当所得的有效地址超过0FFFFH,则取其64K的模。
当用32位地址偏移量进行寻址时,内存地址的偏移量可分为三部分:
一个32位基址寄存器,
一个可乘1、2、4或8的32位变址寄存器,
一个8位/32位的偏移常量,并且这三部分还可进行任意组合,省去其中之一或之二。
总结: 首先明白这7种寻址方式各自的操作数存在哪里,指令中, 寄存器中,内存中。
然后记住默认的段,以及较为复杂的几种寻址方式要先算EA, 以及书写规范在“[ ]”内,
如果有指定的段,则在前面加“:” 如 es:[1000h]。