810 likes | 1.1k Views
第 3 章 80x86 汇编语言程序设计 ( 上 ). 注:本章中,用此颜色和字型说明的文字只适用于 32 位汇编. 3.1 80x86 的寻址方式. 有效地址 ( effective address EA ) —— 操作数在段内的偏移地址 寻址方式 —— 产生有效地址的方法. 80x86 指令的一般汇编语言格式: [ 标号 :] 指令助记符 [[ 目的操作数 ][, 源操作数 ]][; 注释 ] 其中 [ ] 表示可选项 ;. 3.1.1 操作数寻址. 80x86 的操作数寻址方式有: 1 、立即寻址 2 、寄存器寻址
E N D
第3章 80x86汇编语言程序设计(上) 注:本章中,用此颜色和字型说明的文字只适用于32位汇编
3.1 80x86的寻址方式 有效地址(effective address EA) —— 操作数在段内的偏移地址 寻址方式 —— 产生有效地址的方法 80x86指令的一般汇编语言格式: [标号:]指令助记符[[目的操作数][,源操作数]][;注释] 其中[ ]表示可选项; 3.1.1 操作数寻址 80x86的操作数寻址方式有: 1、立即寻址 2、寄存器寻址 3、存储器寻址 4、端口寻址
我们首先讨论两种与存储器无关的寻址方式: 1、立即寻址 操作数以常量形式直接放在指令中,紧跟在操作码之后 机器码存放形式如下: 代码段 代码段 低地址 操作码 OP OP 操作码 D16低8位 D8 8位操作数 高地址 16位操作数 D16高8位 立即寻址示例 MOV AH, -40; -40AH MOV AX, 34D8H ;34HAH, 0D8HAL MOV AX, -40; 0FFD8H(-40)AX MOV EAX, 12345678H ;12345678HEAX
2、寄存器寻址 操作数存放在某个寄存器中,指令指定寄存器号 指令 寄存器 操作数 寄存器号 寄存器寻址示例 MOV AH, BL;(BL)-->AH MOV DS, AX;(AX)-->DS MOV SI, AX;(AX)-->SI MOV ECX, EDX ;(EDX)ECX 说明:立即寻址和寄存器寻址方式不需再次访问存储器即可得到操作数,速度快
下面我们来讨论余下的几种与存储器有关的寻址方式,先介绍几个概念:下面我们来讨论余下的几种与存储器有关的寻址方式,先介绍几个概念: 有效地址(EA)的4种组成成分: 有效地址的计算: EA=基址 +(变址*比例因子)+ 位移量 • 位移量(displacement) 存放在指令中的8位、16位或32位的数,是一个地址 • 基址(base) 存放在基址寄存器中的内容,用于指向数组的首地址 • 变址(index) 存放在变址寄存器中的内容,用于访问数组的某个元素 • 比例因子(scale factor) • 其值可为1,2,4或8,386及其后继机型新增加的
访问非默认段数据的方法——段超越 数据的存放比较灵活,除了放在默认的DS段,还可以存放在别的段,此时访问他们需要使用段超越前缀,可用的段超越前缀有CS:, DS:, ES:, SS:, FS:, GS:。 段超越举例: MOV AX, [10H] ;DS段10H处的一个字的数据赋给AX寄存器 MOV AX, ES:[10H]; ES段10H处的一个字的数据赋给AX寄存器 不允许使用段超越前缀的情况: (1)串操作指令的目的串必须用ES段 (2)PUSH指令的目的和POP指令的源必须用SS段 (3)程序的指令必须存放在CS段
3、直接寻址 操作数地址的偏移量(EA)在指令中 段基地址 存储器 指令 操作数 EA + 物理地址=指定段的段基地址×16+偏移量(EA) 系统默认,操作数在数据段 MOV AX, 2000H ; 立即寻址 MOV AX, [2000H] ; 直接寻址
直接寻址示例1 MOV AX, [1000H]物理地址 设(DS)=10A0H 代码段+ OP 00H 10H 数据段 11A00H 30H 50H 1000H 10A0H 10A00H 1000H 低地址 11A00H 11A00H 30H 50H AX 50H 30H (本章中图示存储器地址从上到下递增)
直接寻址示例2 MOV BL, ES:[0100H]物理地址 设(ES)=3000H 30000H (DS)=2000H + 0100H 30100H 4B 00 BL 0100H 3000H 30100H 30100H 4B 4B 在汇编语言指令中,可以用符号地址代替数值地址 如:MOV AX, BUFF 或 MOV AX, [BUFF] 其中BUFF为存放数据单元的符号地址。
4、寄存器间接寻址 操作数在存储器中,操作数地址的偏移量(EA)在寄存器中 段基地址 指令 寄存器 存储器 基址或变址寄存器号 EA 操作数 + 寄存器间接寻址示例 MOV AL, [BX] MOV AX, CS:[SI] MOV [BP], AH MOV ECX, [EDX]
MOV AH, [BP] MOV BX, [SI] MOV CX, SI 设(SS)=1000H, (DS)=2000H , (BP)=0B10H, (SI)=032AH 物理地址 物理地址 10000H 20000H + 0B10H + 032AH 40H 00H 3EH 46H 1000H 2000H 0B10H 032AH 10B10H 10B10H 2032AH 2032AH AH 40H 10B10H SI 032AH 032AH 40H 10B11H … CX 032AH 2032AH 3EH 463EH BX 46 2032BH
5、基址寻址 操作数的有效地址是基址寄存器的内容加上指令中指定的位移量 指 令 段基地址 基址寄存器号 位移量 存储器 EA 操作数 + + 基址寄存器 地址 可用于数组元素的访问
基址寻址示例 MOV AX, 3000H[BX] (或[BX+3000H]) MOV AX, COUNT[BX]; COUNT是符号地址 (或 MOV AX,[COUNT+BX]) 若(DS)=3000H, (BX)=2000H,COUNT=4000H 30000H 2000H + 4000H 4000H 3000H 2000H 36000H 36000H 34H 36000H 34H 12H 12 1234H AX
6、变址寻址 1)无比例因子的变址寻址(16位寻址) 操作数的有效地址是变址寄存器的内容加上指令中指定的位移量 指 令 段基地址 变址寄存器号 位移量 存储器 操作数 + + 变址寄存器 EA 地址
变址寻址示例 MOV CX, 6020H[SI] (或[SI+6020H]) MOV DX, COUNT[SI];COUNT是符号地址 (或 MOV AX,[COUNT+SI]) 若(DS)=3000H, (SI)=2000H,COUNT=1000H 30000H 2000H + 1000H 3000H 2000H 1000H 33000H 33000H 33000H 34H 67H 34H 67 6734H DX
2)有比例因子的变址寻址 操作数的有效地址是变址寄存器的内容乘以指令中指定的比例因子及位移量之和 指 令 变址寄存器比例因子位移量 段基地址 存储器 变址寄存器 EA 变址值 下标 操作数 * + +
有比例因子的变址寻址示例 MOV EAX, COUNT[ESI*4] 存储器 EA=ESI*4+COUNT 设(ESI)=3,(DS)=1000H COUNT=2000H 12000H +1 +2 +3 +4 元素0 元素1 EAX 元素2 +12 元素3
7、基址变址寻址 1)无位移量的基址变址寻址 操作数的有效地址是一个基址寄存器和一个变址寄存器的内容之和 变址寄存器 指 令 段基地址 变址值 基址寄存器变址寄存器 存储器 操作数 + + 基址寄存器 EA 基址值
无位移量基址变址寻址示例 MOV AX, [BX+DI] MOV AX, [BX][DI] 若 (DS)=2100H, (BX)=0158H, (DI)=10A5H, 2100H 0158H 物理地址 21000H 0158H + 10A5H 10A5H 221FDH 221FDH 34H 221FDH 34H 12H 12 1234H AX
2)基址变址相对寻址 操作数的有效地址是一个基址寄存器的内容、 一个变址寄存器的内容及位移量之和 指 令 基址寄存器变址寄存器位移量 段基地址 存储器 变址寄存器 EA 变址值 + + 操作数 基址值 基址寄存器
基址变址相对寻址示例 MOV AX, MASK[BX+SI];MASK是符号地址 若 (DS)=3000H, (BX)=2000H, (SI)=1000H, MASK=0250H 物理地址 30000H 2000H 1000H + 0250H 33250H 20H 43H 3000H 1000H 2000H 0250H 33250H 33250H 20H 43 4320H AX
3)基址比例变址寻址 操作数的有效地址是变址寄存器的内容乘以指令 中指定的比例因子加基址寄存器的内容之和 指 令 基址寄存器变址寄存器比例因子 变址寄存器 变址值 下标 * 段基地址 存储器 基址寄存器 EA 基址值 操作数 + + 基址比例变址寻址示例 MOV ECX, [EBX+ESI*8]
4)相对基址比例变址寻址 操作数的有效地址是变址寄存器的内容乘以指令中指定的比例因子加基址寄存器的内容、再加位移量之和 指 令 基址寄存器变址寄存器比例因子位移量 段基地址 变址寄存器 存储器 变址值 EA 下标 操作数 * + + 基址寄存器 基址值 相对基址比例变址寻址示例 MOV EAX, TABLE[EBX+EDI*4]
8、端口寻址 1)直接寻址(I/O Port Direct Addressing) 直接寻址是使用一字节立即数寻址,因此I/O端口的寻址范围为00H~FFH,最多为256个。 IN AL, 20H;从20H端口读入1个字节 OUT 60H, AX;将AX中1个字送到60H端口 2)间接寻址(I/O Port Indirect Addressing) 间接寻址由DX寄存器间接给出I/O端口地址,为两个字节,所以最多可寻址216=64K个端口地址。 MOV DX, 3FCH IN AL, DX;从3FCH端口读入1个字节
3.1.2 转移操作寻址 直接寻址(段间) 指令中直接提供了转向段地址和偏移地址,用指令中提供的偏移地址取代IP寄存器,用指令中提供的段地址取代CS寄存器的内容就完成从一个段到另一个段的转移操作。 JMP FAR PTR NEXT_PRO
相对寻址(当前段内)转向的有效地址是当前IP寄存器的内容和指令中指定的位移量之和相对寻址(当前段内)转向的有效地址是当前IP寄存器的内容和指令中指定的位移量之和 • 位移量只有8位的为短(short)转移或条件转移 • 位移量有16位的为近(near)转移
间接寻址 • 段内间接寻址 • 转向有效地址是一个寄存器或是两个字节存储单元的内容 。所得到的转向的有效地址用来取代IP寄存器的内容。 • 设:(DS)=2000H,(BX)=1000H,变量TABLE的有效地址为1000H,(21000H)=0040H,(22000H)=5678H,则下列三条指令分别执行后结果如下: • JMP BX ;执行后IP=1000H • JMP [BX] ;执行后IP=0040H • JMP TABLE[BX] ;执行后IP=5678H
间接寻址 • 段间间接寻址 • 用存储器中的相继的四个字节的内容来取代IP和CS寄存器中的原始内容以达到段间转移的目的。 • 设:(DS)=2500H,(SI)=1300H,(26300H)=4500H,(26302H)=32F0H, 则执行以下指令后结果如下: • JMP DWORD PTR [SI];执行后CS=32F0H,IP=4500H
3.2 80x86汇编语言格式 • 汇编语言源程序结构 • 汇编语言上机过程 • 汇编语言语句格式 • 伪操作(伪指令)
3.2.1 源程序结构概览 数据段 说明: 堆栈段 1、各段顺序无关 2、除代码段外,可缺省 3、可有若干个数据段, 若干代码段 代码段 END [标号] 附加段
汇编语言程序例 .DATA BUF1 DB 34H ;变量定义 BUF2 DB 2AH SUM DB ? 数据段 .CODE START: MOV AX, @DATA MOV DS, AX ; 段寄存器赋值 MOV AL, BUF1 ADD AL, BUF2 MOV SUM, AL MOV AH, 4CH INT 21H ; 程序退出 END START 代码段
3.2.2 汇编语言程序上机过程 汇编 连接 masm link 源程序 .asm 目标程序 .obj 可执行程序 .exe 修改 调试 debug 调试 执行 DOS下执行 更多细节以及在VC6中实现C++中嵌入汇编请看 《汇编语言上机过程(自学).ppt》
3.2.3 汇编语言语句格式 有三类语句: 指令语句——完成操作功能,能翻译成机器指令 伪指令语句——为汇编程序在翻译源程序时提供 有关信息 宏指令语句——由若干条指令语句组成的语句 指令语句格式 [符号名:]指令助记符[目的操作数[,源操作数]][;注释] 伪指令语句格式: [符号名] 伪操作 [操作数[,操作数, …]] [;注释]
一、指令语句格式 1、符号名 由用户按一定规则定义的标识符,有标号和变量两种形式,在指令格式中用的是标号。可用符号是: 字母:A--Z, a--z 数字符: 0--9 专用字符:?, _, @, $ 长度不超过31个字符, 首字符不能为数字,不能和保留字同名。 2、指令助记符 指令助记符是汇编指令的符号代码,不可缺省。 汇编源程序时,系统使用内部对照表将每条指令的 助记符译成相应的机器码。
3、目的操作数 1)参与指令操作 2)暂存操作结果 除立即寻址方式外,其他寻址方式均适用于目的操作数. 4、源操作数 提供原始数据或操作对象,面向所有寻址方式 5、注释 注释在系统汇编时并不产生机器码 注释可以放在指令语句尾,也可单独使用 注释前面的“;”不可缺少 指令举例: START: MOV AX, 2000H MOV DS, AX ;为DS寄存器赋值
二、常量 常量有两种: 1、数值常量 二进制数 以B结尾,如01011101B 八进制数 以Q结尾,如235Q 十进制数 以D结尾或没有结尾字母,如98D或98 十六进制数 以H结尾,如5BH,当最高位为‘A’~‘F’,则在最高位前加‘0’ 2、字符串常量 用单引号括起来的一个或多个字符,如‘A’、‘AB’ 字符用ASCII码形式存储 常量的应用: (1)在指令语句中作立即数 MOV CX, 100 (2)在指令语句中作位移量 MOV AX, 34[SI] (3)在数据定义语句中作初值 X DB 12H, 34H,’abcd’
三、变量和标号 变量用来代表数据所在存储单元的地址,在数据段、附加段和堆栈段中使用,变量与其所代表的数据用空格隔开。变量有三种属性: 1、段属性——变量所在段的起始地址 2、偏移属性——从段起始地址到定义变量的位置之间的字节数 3、类型属性——该变量所保留的字节数 DB 1个字节 DW 2 个字节 DD 4个字节 DQ 8个字节 DT 10个字节
标号用来代表一条指令所在存储单元的地址,在代码段中使用。标号与其代表的指令间用冒号隔开。标号也有三种属性:标号用来代表一条指令所在存储单元的地址,在代码段中使用。标号与其代表的指令间用冒号隔开。标号也有三种属性: 1、段属性——定义标号所在段的起始地址 2、偏移属性——从段起始地址到定义标号的位置之间的字节数 3、类型属性——表示它的转移特性 NEAR (近) 段内转移 FAR (远) 段间转移
3.2.4 汇编伪指令 伪指令:帮助汇编程序正确翻译源程序的命令,本身不生成任何机器指令) • 处理器选择伪指令 • 数据定义和存储器分配伪指令 • 表达式赋值伪指令 • 地址计数器与对准伪指令
(一)处理器选择伪指令 .8086 可使用8086指令(一般不用写) .286 可使用80286指令 .286P 可使用保护方式下的80286指令 .386 可使用80386指令 .386P 可使用保护方式下的80386指令 .486 可使用80486指令 .486P 可使用保护方式下的80486指令 .586 可使用Pentium指令 .586P 可使用保护方式下Pentium的指令 .686 可使用Pentium Pro指令 .686P 可使用保护方式下Pentium Pro的指令 .MMX 可使用MMX指令 .XMM 可使用SSE指令 当源程序使用了286及以上的机型新增加的指令时,应该在程序开始使用相应的处理器选择伪指令。
(二)数据定义伪指令 格式:[变量名] 定义符 操作数项表 操作:为变量分配存储单元并将初值置入相应单元中 定义符可为: DB—— 定义字节 DW ——定义字(2个字节) DD——定义双字(4个字节) DF——定义六字节 DQ——定义八字节 DT——定义十字节 操作数项可为: 1、常数或表达式 2、字符串 3、?表达式 4、带DUP 的表达式 操作数项表: 操作数项[, 操作数项[, 操作数项…]]
操作数是常数或表达式 X1 DB 40H ;为X1分配1个字节,初值40H X2 DW 250*250 ;为X2分配2个字节,初值62500 X3 DD 10203040H ;为X3分配4个字节,初值为10203040H X4 DQ (120+50)/10 ;为X4分配8个字节,初值17 X5 DB 10, 20, 30 ;多项定义,X5被分配3个字节,初值分别为10,20,30,地址从低到高,各个值间用逗号分开
操作数为字符串 STRING1 DB ‘HELLO’ STRING2 DB ‘H’, ‘E’, ‘L’, ‘L’, ‘O’ 字符串用DB定义,被定义串以单引号括起来 串中可包含数字符、大小写英文字母、回车符、 换行符、 空格、?、$、下划线_等 字符串以ASCII码形式存储在存储单元中。 STRING1 ‘H’ +1 ‘E’ +2 ‘L’ +3 ‘L’ +4 ‘O’
区分 S1 DB ‘AB’ 与S2 DW ‘AB’ 它们的存储情况为: S1 S2 ‘A’ ‘B’ ‘B’ ‘A’ 操作数项为? ?用于预留空间,不置初值 Y1 DB 20H, ? ;定义2个字节,其中预留1个字节 Y2 DW ?, ? ;预留2个字 Y3 DD ? ;预留4个字节 Y4 DQ ? ;预留8个字节 Y5 DT ? ;预留10个字节
操作数项带重复定义符DUP 格式:N DUP(操作数项表) 操作:将操作数项表内容重复定义N次 VAR1 DW 2 DUP(2, 4), 1476H VAR2 DB 2 DUP(?, 2 DUP(‘A’, ‘B’) ) 存储情况为: VAR1 02H VAR2 ? 00H ‘A’ 04H ‘B’ 00H ‘A’ 02H ‘B’ 00H ? 04H ‘A’ 00H ‘B’ 76H ‘A’ 14H ‘B’
操作数运算符 • 算术运算符 • 逻辑运算符 • 关系运算符 • 数值回送运算符 • 属性运算符 • 运算符优先级 48
算术运算符(单目+, 单目-, +, -, *, /, MOD) 运算符 格 式 运 算 + +表达式 取表达式正值 - -表达式 取表达式负值 + 表达式1+表达式2 求表达式1、表达式2之和 - 表达式1-表达式2 求表达式1、表达式2之差 * 表达式1*表达式2 表达式1、表达式2之积 / 表达式1/表达式2 表达式1、表达式2之商 MOD 表达式1 MOD 表达式2 取余数 说明: 1、算术运算符可用于数值表达式或地址表达式 2、用于地址表达式时,只有其结果有物理意义时才有效 常用的是:地址+数字常量 (结果是地址) 地址-数字常量 (结果是地址) 地址-地址 (结果是常量)
算术运算符示例 (1) MOV AL, 20+30 ;50-->AL MOV BH, 100-2 ;98-->BH MOV CX, 50/2 ;25-->CX MOV AL, 80 MOD 15 ;5-->AL (2) 将首地址为BLOCK的字数组的第6个字传送到DX: MOV DX, BLOCK+(6-1)*2 ; 地址+常量,结果仍为一地址值 (3) 设数据定义如下: ARRAYA DW 1, 2, 3, 4, 5, 6, 7 WENDA DW ? 将数组长度(字数)存入CX: MOV CX, (WENDA-ARRAYA)/2 ; 地址-地址,结果为一常量