[工学]汇编语言第二章 寻址方式.doc
第二章 寻址方式在8086微处理器中,一条指令通常由操作码加上操作数构成。指令形式为:操作码 操作数1, 操作数2; 注释其中,操作码指明执行的动作,操作数指明操作的对象。由于寄存器数量有限,操作数不可能都放在寄存器中,实际上,操作数既可以放在寄存器中,也可以放在主存贮器中,这样就涉及到操作数的寻址问题。我们将寻址操作数存放地址的方式称为寻址方式。本章的内容包括:主存储器和物理地址的形成寻址方式常量与变量的定义2.1 主存贮器和物理地址的形成一、 主存贮器计算机存贮系统分为:主存贮器(内存)、辅助存贮器(外存)。l 主存容量小、存取速度快、价格高;l 辅存容量大、存取速度慢、价格低。主存贮器的基本存贮单位是“位”(bit),每8位组合成一个“字节”;每相邻的两个字节称为“字”;相邻的四个字节称为“双字”。为了区别各个存贮单元,给每个单元编号,称为地址。地址:字节单元的编号,也称为物理地址。010FFFFFH低地址高地址从00FFFFFH,共有220个单元,20根地址线。低字节放低位,高字节放高位。例如:0004单元存放内容为1234H。012345表示:(0004)字=1234H34H12H二、 存储器物理地址的形成早期的8086微处理器,有20根地址线,寻址范围220 = 1M字节。但是,8086内部为16位结构,与地址相关的寄存器均为16位,从而导致可寻址范围为64K。因此,设计成为将主存分段使用,每段最大为64K字节。用CS、DS、SS、ES保存当前可用段的段首地址。规定:段首地址只能从任一“小段”的首地址开始,也就是必须最低4位为0,如果所有的段首地址都是这样,则可以忽略最低4位,而只将高16位放到段寄存器中。因此,计算物理地址时,应将段寄存器内容左移4位,恢复段首址原值,然后再与本段中待访问单元的偏移地址相加,得到访问单元的物理地址。因此,被访问单元物理地址 PA = 段首址*16+偏移地址。具体在不同的段中,物理地址为:1 代码段:待取指令PA=(CS)左移4位+(IP)2 数据段、附加数据段:PA=(DS或ES)左移4位+(EA)如:(DS)= 8765H,某变量Y的EA = 153H,则Y的物理地址:PA=(8765)左移4位 + 153H = 877A3H3 堆栈段:栈顶PA=(SS)左移4位+(SP)入栈、出栈指令SP自动变化,不需用户设置。如果需要访问堆栈段,将偏移地址放在BP中,计算堆栈单元物理地址。某堆栈单元PA=(SS)左移4位+(BP)注意:l DS、ES需要用户自行设计,CS由系统赋值l 各段可以完全重叠、部分重叠、不重叠l 各段最大为64KBl 上述物理地址的计算,皆由微处理器自动完成,编程时,着重考虑偏移地址的表示形式,也就是操作数所在位置。三、 保护模式下的内存管理1. 80x86的寻址范围l 80x86地址总线32位,寻址范围4Gl 80x86通用寄存器32位,寻址范围也是4G所以80x86的一个通用寄存器能够存放一个完整的32位地址2. 虚拟内存与分页机制在支持虚拟内存的32位操作系统(WIN32,Linux等)中,目标是要为每个进程提供一个独立的4G大小的虚拟地址空间。在80x86保护模式下,逻辑地址空间(多个进程的地址空间总和)大于物理地址空间,所以用实模式的地址直接映射不能满足此要求,需要通过虚拟内存管理器,采用分页机制来实现:l 将物理地址映射到进程的逻辑地址空间上;l 只有映射了物理内存的逻辑地址空间才能访问;l 每次映射的物理内存不大,且用完后可释放,再重新映射到新的逻辑地址空间上,因此能够让多个进程同时运行;l 分页由系统基于页目录和页表,自动完成进程1的逻辑地址空间进程2的逻辑地址空间物理内存3. 特权级与分段机制(1) 80x86有4个特权级:0,1,2,3(0级最高,3级最低),能够在虚拟内存的基础上实现进一步的内存保护机制如果程序有0级权限,它可以执行所有的指令,访问所有的数据。如果程序只有3级权限,则它只能执行有限的指令,访问有限的数据(它自己的数据)。(2) 80x86通过分段机制来实现特权级的访问控制。用“段选择符:EA”的形式表示逻辑地址,段选择符(16位)存放在段寄存器中,指向一个段描述符(64位)。段描述符索引 T1 特权级段选择符32位段基址 20位段界限 特权级段描述符153210用逻辑地址访问内存时,段选择符中的特权级需要高于段描述符中的特权级。(3) 由逻辑地址生成物理地址的过程:EA + 段基址线性地址物理地址分页32位32位32位32位EA要小于“段界限 * 4K”。一般应用程序中,段基址为0,段界限为0FFFFFH。所以对线性地址的形成不产生影响。所以32位保护模式下,在一般的应用程序中,是一个可通过EA访问的,平坦的,独立的4G内存空间。不用特别考虑分段和分页。2.2 寻址方式一、 立即寻址操作数直接存放在指令中,紧跟在操作码之后,它作为指令的一部分存放在代码段里,这种操作数称为立即数。汇编格式:n功能:指令的下一单元的内容为操作数n,即:指令nn也称为立即数。例如:MOV AX,3064H目的操作数采用寄存器寻址,地址为AX。源操作数采用立即寻址。即:64HMOV30H代码段该功能主要用来给寄存器赋值。注意:l 立即数只能作源操作数,不能作目的操作数。如:MOV 100H,AX。l 立即数作为源操作数时,注意溢出。如:MOV AH, -90H;这个语句是错误的。因为:-90H=-142-128。二、 寄存器寻址在这种寻址方式中,指令所指明的寄存器就是操作数的存放地址。汇编格式:R(R为8或16位寄存器)指令操作数1.1.1.1 R功能:寄存器R的内容就是操作数。表示:指令指明操作数在R中。INC指令12H1.1.1.2 AX例:INC AX; 操作数在AX中。执行前:(AX)=12H执行:(AX)+1AX。执行后:(AX)=13H例:ADD AX, BXAX为目的操作数地址,BX为源操作数地址。ADD指令1234H5620HBXAX执行前:(AX)=1234H,(BX)=5620H执行:(AX)+(BX)AX。执行后:(AX)=6854H,(BX)=5620H此例中,目的操作数、源操作数都是用寄存器寻址。注意:l 采用寄存器寻址方式,指令执行速度快。特别是加法指令,如果目的操作数为AX,指令执行快一些。l 采用寄存器寻址方式,目的、源操作数类型必须一致。如:MOV AH,BX就是错误的。三、 直接寻址直接寻址方式中,操作数的偏移地址就在指令操作码后面,而操作数则存放在数据段。汇编格式:地址表达式或段寄存器:EA功能:指令下一字单元的内容是操作数的偏移地址。指令段首址Å操作数PA左移4位段寄存器EAEA例如:MOV AX, 2000H执行前:(DS)=3000H,(32000H)=1234H源操作数寻址过程: 指令3000HÅ32000HDS2000AEA34H左移4位执行:(32000H) AX执行后:(AX)=1234H注意:8086汇编语言中,可以用含有变量的地址表达式代替数地址。如:MOV AX, VALUE+6其中VALUE定义在数据段:VALUEDB 12H, 13H, 14H, 15H, 16H此时,操作为(VALUE+6)的内容AX,也就是将15H送到AX中。四、 寄存器间接寻址操作数的有效地址(偏移地址)在基址寄存器BX、BP或变址寄存器SI、DI中,而操作数则在存贮器中。汇编格式:R功能:R的内容为操作数的偏移地址EA,即:指令EA段首址Å操作数PA左移4位R段寄存器R只能是BP、BX、DI、SI之一。注意BP所指的段为堆栈段。例:MOV AX, SIAX是目的操作数地址,采用寄存器寻址方式;SI指明源操作数采用寄存器间接寻址方式。假定执行前:(AX)=5,(DS)=2000H,(SI)=1000H,(21000H)=50A0H。源操作数寻址过程:MOV指令1000H2000HÅ21000H左移4位SIDS存储器50A0H执行:(21000H) AX执行后:(AX)=50A0H,(SI)、(DS)、(21000H)不变。例:MOV AX, BP假定执行前:(AX)=0,(BP)=30H,(SS)=2000H,(20030H)=1234H。源操作数寻址过程:BPSSMOV指令30H2000HÅ20030H左移4位存储器1234H执行:(20030H) AX执行后:(AX)=1234H,(BP)、(SS)、(20030H)不变。五、 变址寻址操作数的偏移地址EA是指令中指明的寄存器的内容与指令中给出的位移量之和。操作数在存贮器中。汇编格式:XR功能:R的内容与X相加,和为操作数的偏移地址EA。也就是:指令变址值段首址Å操作数PA左移4位R段寄存器XEAÅ关于段寄存器的选择同寄存器间接寻址一样,只能是BP、BX、DI、SI之一。注意BP所指的段为堆栈段。例:MOV AX, COUNTSI也可表示为:MOV AX, COUNT+SI目的操作数采用寄存器寻址方式,操作数地址为AX。源操作数采用变址寻址方式。操作数EA=SI+COUNT。假定执行前:(SI)=2000H,(DS)=3000H,COUNT=3000H,(AX)=0,(35000H)=1234H。源操作数的寻址过程如下:指令2000H3000HÅ35000H左移4位SIDS3000H5000HÅ1234H执行:(35000H) AX执行后:(AX)=1234H,(SI)、(DS)、(35000H)内容不变。例:ADD COUNTBP, BX目的操作数采用变址寻址方式,偏移地址EA=BP+COUNT。源操作数采用寄存器寻址方式。假定执行前:(BX)=40H,(BP)=2000H,(SS)=3000H,COUNT=3000H,(35000H)=50H。目的操作数的寻址过程如下:指令2000H3000HÅ35000H左移4位BPSS3000H5000HÅ50H执行:(35000H)+(BX) 35000H单元执行后:(35000H)=90H,(BX)、(BP)、(SS)内容不变。注意:采用变址寻址可以方便地访问数组中的任一元素,使得编程更加方便。例如:一唯数组a,其存放如图所示。定义:DATASEGMENTCOUNTDB a0, a1, anDATAENDSMOV BX, OFFSET COUNT; 若要将a8放到AH,可用:MOV AH, 8BX; 若要将第 i 个元素放到AH,可用:MOV AH, i BX(BX)=COUNTa0a1a8an六、 基址加变址寻址操作数的偏移地址EA是指令中指定的基址寄存器内容、变址寄存器内容及位移量X三者之和。操作数存放在主存之中。汇编格式:XBR + IR功能:BR的内容加上IR的内容,再加上X,得到操作数的偏移地址。也就是:EA =(BR)+(IR)+X。指令基址值Å操作数PA左移4位BR段寄存器XEAÅ变址值IR段首址其中:BR表示基址寄存器,只能是BX、BP之一。IR表示变址寄存器,只能是SI、DI之一。也就是:EA = BX + SI或DI + X;数据在当前DS中EA = BP + SI或DI + X;数据在当前SS中同前面一样,基址寄存器决定操作数所在的段。如果选用BX,则操作数在数据段内;如果选用BP,则操作数在堆栈段内。例1:MOV AX, MASKBXSI,也可以写成:MOV AX, MASKBX+SI或MOV AX, MASK+BX+SI目的操作数采用寄存器寻址,地址在AX。源操作数采用基址加变址寻址,EA = BX+SI+MASK。执行前:(DS)=3000H,(BX)=2000H,(SI)=1000H,MASK=250H,(33250H)=1234H。源操作数寻址过程:指令2000HÅ33250H左移4位BXDS250H3250HÅ1000HSI1234H3500H执行:(33250H) AX执行后:(AX)=1234H,(BX)、(SI)、(DS)、(33250H)不变。例2:ADD AX, MASKBP+DI目的操作数采用寄存器寻址,地址在AX。源操作数采用基址加变址寻址,EA = BP+DI+MASK。执行前:(SS)=3000H,(BP)=2000H,(DI)=1000H,MASK=8H,(33008H)=34H,(AX)=12H。源操作数寻址过程:指令2000HÅ33008H左移4位BPSS83008HÅ1000HDI34H3500H执行:(AX)+(33008H) AX执行后:(AX)=46H,(BP)、(DI)、(SS)、(33008H)不变。七、 寻址方式注意事项1. 某些指令的执行要涉及到缺省的操作数,其寻址方式也是隐含的。例: CBW隐含源和目的操作数。源操作数为AL,寄存器寻址;目的操作数为AX,寄存器寻址2. 双操作数指令中,源和目的操作数不能同为存储器寻址方式例:指令中操作数指定错误MOV BYTE PTRSI, DIADD EBX+EDI*4+10, COUNT3. 指令中至少有一个操作数的类型要明确,若为双操作数,则操作数的类型必须相同。例:判断指令中操作数指定是否正确INC DS:100H; 错DEC DI; 错ADD BX + SI, 12H; 错MOV BX, AL; 错MOV WORD PTRBX, C; 对DEC BYTE PTRSI; 对4. 跨度寻址如果选用BP或EBP作间址寄存器、变址寄存器或基址寄存器,则操作数在堆栈段内;如果选用BX、SI、DI作间址寄存器、变址寄存器或基址寄存器,则操作数在数据段内。上述两种寻址方法都是80x86微处理器所默认的状态。在实际编写程序时,可以利用段寄存器,指明所要寻址的段。汇编格式:段寄存器名:功能:冒号之前的段寄存器指明了操作数所在段。例如:MOV AX, DS: BPMOV BX, ES: BXMOV CX, SS: SIMOV DX, SS: DIDS、ES、SS指明了数据所在段,而原来的默认状态不起作用。第1条:操作数在DS段,PA =(DS)左移4位+BP第2条:操作数在ES段,PA =(ES)左移4位+BX第3条:操作数在SS段,PA =(SS)左移4位+SI第4条:操作数在SS段,PA =(SS)左移4位+DI八、 32位寻址方式1 寄存器间接寻址:R(1) 可使用8个32位通用寄存器:EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP(2) ESP和EBP默认为SS段,其他默认为DS段2. 变址寻址:XR(1) 可使用8个32位通用寄存器(2) ESP和EBP默认为SS段,其他默认为DS段3. 基址加变址寻址:XBRIR(1) 可使用8个32位通用寄存器(2) 32位通用寄存器可任意搭配,不受BR+IR限制(除了IR不能为SP)(2) 当BR为ESP和EBP时,默认为SS段,否则为DS段4. 16位-32位汇编程序,可分为三种情况:(1) 16位寄存器,16位寻址:普通的三段式程序(2) 32位寄存器,16位寻址:(1),加.386,加USE16(1) 32位寄存器,32位寻址:(1),加.386,加.MOEL FLAT,且不用DOS功能调用,而换用WIN32函数调用在情况(2)中,前面所讲的6中寻址方式仍然有效。在情况(2)中,计算得到的EA仍不能超过16位。在情况(3)中,不能使用16位寄存器寻址,计算得到的EA能超过16位,有32位的空间。5. 带有比例因子的寻址方式CPU提供的指令和寻址方式,需要能够将高级语言翻译成高效的机器代码。高级语言中除了简单变量,还有一维或多维数组、结构、结构组成的数组等数据结构,因此提供了更多的32位寻址方式。带有比例因子的寻址方式:R -> R * FVR -> VR * FVBRIR -> VBRIR * F(1) 只在变址寄存器上可以加比例因子F(2) 比例因子F可以为1,2,4,8例:MOV AX, BUFEBXESI * 2则EA = (EBX) + 2 * (SI) + BUF的偏移地址九、 寻址方式举例例:已知数据段定义和存储示意图如下:DATA SEGMENTBUF DB 10,20,40,80,30BUF1 DB 5 DUP(0)DATA ENDS(1) 分别利用直接寻址,寄存器间接寻址,变址寻址和基址加变址寻址,将该段中BUF+3单元中的内容送到AL中。l 直接寻址MOV AL, BUF+3l 寄存器间接寻址LEA BX, BUF+3; 将BUF+3相对于段首地址的偏移地址EA=3送入BX中。 MOV AL, BXl 寄存器变址寻址LEA BX, BUF; 取BUF的EA->BXMOV AL, BX+3; (BX)+3)->ALl 基址加变址寻址LEA BX, BUF;MOV SI, 3;MOV AL, BX+SI;(2) 利用寄存器间接寻址,变址寻址和基址加变址寻址,将BUF为首址的连续字节单元的内容分别送到以BUF1为首址的连续字节单元中。l 寄存器间接寻址LEA SI, BUFLEA DI, BUF1;MOV CX, 5;A:MOV AL, SI;MOV DI, AL;INC SI;INC DI;DEC CX;JNZ A;l 变址寻址MOV SI, 0;MOV CX, 5;A:MOV AL, BUFSI;MOV BUF1SI, AL;INC SI;DEC CX;JNZ A;l 基址加变址寻址LEA BX, BUFLEA BP, BUF1MOV SI, 0;MOV CX, 5;A:MOV AL, BXSI;MOV DS:BPSI, AL;INC SI;DEC CX;JNZ A;l 说明:(a) 寄存器间接寻址,变址寻址和基址加变址寻址都能用来传送一片连续存储区的内容。(b) 该例中,变址寻址方式最直观,可读性最好2.3 常量与变量的定义汇编程序的语句中具体的操作数,可以分为常量和变量两种:常量与数值表达式变量与地址表达式常量数值表达式变量地址表达式表达式:由常数、寄存器、标号、变量加上运算符构成的式子。一、 常量与数值表达式1. 常量常量:从源程序翻译成目标程序期间已经有确定数值的量。用途:赋值、作立即数、位移量。常量的分类:数值常量:二进制、十进制、十六进制、字符符号常量:有名字的数值常量2. 数值表达式由常量与运算符组成的式子。数值表达式在汇编期间进行运算,结果为常量。汇编期间允许对常量进行3种运算:l 算术运算包括:+、*、/、模除(MOD,取余数)、右移、左移。l 逻辑运算包括:逻辑乘:AND(与),逻辑加:OR(或),按位加:XOR(异或),逻辑非:NOT(非)l 关系运算包括:相等(EQ)、不等(NE)、小于(LT)、大于(GT)、小于等于(LE)、大于等于(GE)。运算结果:关系不成立,结果为0;关系成立,结果为1(0FFFFH)。如:N = 50M = (N EQ 50)该关系成立,M =1。二、 变量与地址表达式1. 变量数据段或附加数据段中一个数据存贮单元的名字,是这个存储单元的地址的符号表示。可代表一批存储单元的首址。(1) 变量的属性l 段属性定义变量所在段的段首址,当访问该变量时该段首址应在某一段寄存器中,即为CPU当前可访问段。l 偏移地址该变量所占存储单元到所在段的段首址的字节距离。l 类型类型是指存取该变量中的数据所需要的字节数,变量的类型由定义该变量时所使用的伪指令确定。(2) 变量的定义格式:变量名 数据定义伪指令 表达式,l 数据定义伪指令DB、DW、DD、DQ、DT等。l 表达式(a) 数值表达式(b) ASCII字符串(c)地址表达式(DW 地址表达式为变量时,DW内容为变量的EA;DD 地址表达式为变量时,DD的内容为EA+段首址)(d)?不确定(e) n DUP(表达式),重复子句上述(a)(e)组成的系列,中间用逗号隔开。(3) 示例:DATASEGMENT USE16ADW MBUFDB AB, 0DH, 0AHCONEQU 500HBDW 0FFAAHMARK = 100HDDD BUFMDB 2 DUP(1), 2 DUP(2, B)DB 123, 1DATAENDSl 请画出数据段中的数据在主存中的存储形式。l 在上例中分别执行语句后AL的结果。MOV AL,BUFMOV AL,BUF+2l 指令MOV EDX, M是否正确?l 注意伪指令EQU及“=”不分配存贮单元使用直接寻址方式时,变量的类型必须与指令的要求相符变量的段必须是当前段2. 地址表达式由变量、标号、常量、寄存器(名加方括号)及一些运算符(数值表达式的运算符和特殊运算符)所组成的有意义的式子。地址表达式也具有段、EA、类型等三个属性。简单的地址表达式:直接寻址、间接寻址、变址、基址加变址等。在地址表达式中,除运算符外、还可使用特殊算符。取偏移地址OFFSET取段地址SEG取类型TYPE类型运算符PTR跨段前缀符“:”定义类型算符THIS属性定义符属性分离符特殊算符:(1) 属性定义符l 类型运算符PTR功能:指明变量、标号或地址表达式的类型。格式:类型 PTR 地址表达式;类型包括:BYTE、WORD、DWORD、NEAR、FAR等。例:MOV BYTE PTR SI+4, 55HTWODW 055H; 定义一个字MOV AH, BYTE PTR TWO; 只读字节例:DATASEGMENTTWODW 1234H, 5678HONEEQU BYTE PTR TWODATAENDSl 跨段前缀符“:”功能:指定变量、标号、地址表达式的段属性。格式:段名:地址表达式。例:DS:BP。l 定义类型算符 THIS功能:与PTR类似,指定下一个存贮单元的类型。格式:THIS 类型例:DATASEGMENTBEQU THIS BYTE; 指下面将要定义的变量ADD ?; A双字WDW ?; W字CEQU WORD PTR A; C为字变量A、B、C有相同的段首址和EA,但是它们的类型不同。(2) 属性分离算符功能:分离出段、EA及类型等属性。分离对象为变量、标号。格式:属性分离算符 变量或标号;属性分离算符有:SEG、OFFSET、TYPE。l 取段地址算符SEG功能:分离出标号、变量的段首址。例:MOV AX, SEG BUFl 取偏移地址算符 OFFSET功能:分离出变量、标号的偏移地址。例:MOV SI, OFFSET BUFl 取类型算符 TYPE功能:取变量、标号的类型。类型值:变量类型类型值字节1字2双字44字8十字节10例:BUF2DW ?MOV DX, TYPE BUF2; 类型值(DX)=1(4) 汇编地址计数器功能:记录正被翻译的语句地址。格式:$例:DATASEGMENTBUFDB 12345CONEUQ $BUFADB BDATAENDSBUF当前12345B注意:CON = 5 0 = 5,就是BUF字符个数。又如:A DW 1, 2, $+4, 3, 4, $+4。0A124 此时$ = 4,所以$ + 4 = 8356798BA 此时$ = A,所以$ + 4 = E010002000800030004000E00本章作业一、p44:2.2, 2.3, 2.4二、p94:3.1, 3.437