汇编语言程序设计第三章
Windows 汇编程序基础提纲
3.1 机器语言、汇编语言和高级语言
3.2 汇编语言程序的上机过程
3.3 汇编源程序的格式
3.4 操作数的寻址方式
3.5 数据定义
3.6 操作符
3.7 寻址方式的应用
3.1 机器语言、汇编语言和高级语言程序设计程序语言分为三大类:机器语言、
汇编语言和高级语言。
高级语言目前使用较多的是高级语言编程
用高级语言编写的程序便于阅读和修改
计算机不能直接执行
需要由编译程序或解释程序将它翻译成计算机能够接受的机器语言程序
C,C++,java等都是高级语言。
机器语言
计算机能够直接识别的语言
机器指令用二进制代码组成
每条机器指令都由 CPU执行,控制计算机完成一个基本操作机器语言编写的程序是计算机惟一能够直接识别并执行的程序,而用其他语言编写的程序必须经过翻译变换成机器语言程序。
汇编语言
介于机器语言和高级语言之间
充分利用计算机的硬件特性和操作系统底层功能
直接利用 CPU的指令系统
3.2 汇编语言程序的上机过程
开发过程的最终目的是产生一个可执行文件
先要编写相应的程序源文件 ( 源程序 )
再进行编译链接
3.2.1 汇编程序的开发过程
汇编程序的开发过程分为编辑、编译、链接、运行等几个步骤
3.2.1 汇编程序的开发过程(续)
1.汇编程序的后缀为,asm,可以用任何文本编辑程序来编写,但是必须使用,纯文本,格式保存。
2.在编辑生成源文件后,下一步操作就是运行汇编程序对源文件进行汇编,如果没有错误就生成 obj目标代码文件。
3.目标代码文件不能直接运行,将,obj文件和用到的库文件链接起来,生成最终的,exe文件。
4.在得到可执行文件后,再运行可执行文件,检查程序是否可以正确运行 。
如何找到逻辑错误?
一般来说,有 3种常用的方法来查找错误:静态分析,中间结果打印,动态调试 。
3.2.2 MASM汇编器
MASM汇编器的命令行用法为:
ml [/选项 ] 汇编程序源文件 [/link 链接选项 ]
选项 功能
/c 仅进行编译,不自动进行链接
/coff 产生的 obj文件格式为 COFF格式
/Cp 源程序中区分大小写
/Fo filename 指定输出的 obj文件名
/Fl [filename] 产生,lst列表文件
/I pathname 指定 include文件的路径
/link 指定链接时使用的选项
3.2.3 LINK链接器
LINK编译器的命令行用法为:
link [选项 ] [文件列表 ]
选 项 功 能
/out:输出文件名 输出的文件名,扩展名默认为,exe
/map:文件名 生成 MAP文件
/libpath:目录名 指定库文件的目录路径
/implib:文件名 指定导入库文件
/entry:标号 指定入口
/comment:字符串 在 PE 文件的文件头后面加上文本注释(版权信息)
/stack:数字 设定堆栈的大小
/subsystem:系统名 指定程序运行的环境,可以是以下几种之一:
Native,Windows,Console,Windowsce,Posix
以一个源程序文件 hello.asm为例,对它进行汇编链接,最后运行 。
用 MASM汇编一个程序的方法为
ml /c /coff hello.asm
用 LINK链接生成可执行文件的方法为:
link /subsystem:console hello.obj
可以简化为:
ml /coff hello.asm /link /subsystem:console
3.2.4 汇编链接步骤
3.3 汇编源程序的格式
3.3.1 一个显示字符串的汇编程序举例 hello.asm
等同于下面的 C程序
#include <stdio.h>
int main( )
{
printf("Hello World!\n");
return 0;
}
3.3.2 程序格式
1,模式定义程序的第一部分是有关模式定义的 3条语句:
.386
.model flat,stdcall
option casemap:none
这些语句定义了程序使用的指令集,工作模式 。
下面讲一下指令集和工作模式
( 1)指令集
,386语句是汇编语言的伪指令,说明使用的指令集是哪一种 CPU的。
如果用汇编语言编写的是驱动程序或者驱动程序的一个小模块,而且驱动程序在特权级 0上运行,就需要使用,386p,后面带 p的伪指令表示程序中可以使用特权指令。
在编程中如果使用了 MMX指令,除了定义,586之外,还要加上一句,mmx伪指令:
.586
.mmx
( 2)工作模式
.model语句用来定义程序工作的模式,它的格式是:
.model 内存模式 [,调用规则 ][,其他模式 ]
内存模式的定义影响最后生成的可执行文件
在 DOS的可执行程序中,可用到,com文件和,exe文件 。
在 Windows环境下,可执行程序只有一种内存模式,
即 Flat( 平坦 ) 模式 。
( 2)工作模式(续)
在 DOS下的汇编语言程序中,常常有这样的程序片段:
MOV AX,DATA
MOV DS,AX 其作用是给数据段寄存器 DS赋值 。
在编程时,必须考虑这些 DS,ES,SS等段寄存器是否正确设置 。
在 Windows汇编语言程序中,则不必考虑这些问题 。 在程序中,不需要也不应该给 CS,DS,ES,SS等段寄存器赋值 。
( 3) option语句
option语句有许多选项,这里介绍一种,
option casemap:none
这条语句说明程序中的变量和子程序名是否对大小写敏感。
由于 Windows API函数中的函数名称是区分大小写的,所以应该指定这个选项,casemap,none”
3.3.2 程序格式
2,includelib语句汇编程序中也需要调用一些外部模块 ( 子程序 /函数 ) 来完成部分功能 。
例如:使用下面语句通知链接程序使用 msvcrt.lib
includelib msvcrt.lib
若要使用使用其他库文件,只需重复编写
Includelib 库文件名
3.3.2 程序格式
3,函数声明语句对于所有要用到的库函数或 Windows API函数,
在程序的开始部分必须预先声明,包括函数的名称,参数的类型等 。
格式:
函数名称 PROTO [调用规则 ]:[第一个参数类型 ][,:后续参数类型 ]
3.3.2 程序格式
4,include语句
include语句的语法是,include 文件名例如:
include kernel32.inc
include user32.inc
以后程序中用到 user32.dll和 kernel32.dll中的函数时,
不需要事先声明就可以直接使用 。
3.3.2 程序格式
5,数据和代码部分程序中的数据部分和代码部分是分开定义的,
分别以,data 和,code 开始,以 end结束。
end语句一般是整个程序的最后一条语句,end
语句后面跟的是起始标号,指出了程序执行的第一条指令的位置 。
3.3.2 程序格式
6,跨行的语句当源程序的某一语句过长,不利于书写和阅读时,可以用反斜杠 ( \) 作为换行符,将这条语句分为几行来写 。
3.3.3 一个 Windows界面的汇编程序
下面给出一个使用 Windows图形界面的汇编源程序 。
hellow2.asm( 显示一个 Windows消息框 )
在编译链接时,必须在 subsystem选项中指定
,windows”,而不是,console”。 命令为:
ml /coff hellow.asm /link /subsystem:windows
运行结果:
3.4 操作数的寻址方式
寻址方式就是如何表示操作数的各种方法。
以 MOV指令为例:
格式,MOV DST,SRC
DST为目标操作数,SRC为源操作数,即 SRC→ DST
DST和 SRC的数据类型应该一致举例
例如,以下的一些数据传送操作都是用 MOV指令完成的
MOV AL,127; 将 AL的内容设置为 127,即 7FH
MOV DX,100; 将 DX的内容设置为 100,即 0064H
MOV EAX,0; 将 EAX的内容设置为 0
MOV EBX,EAX; 将 EAX的内容复制到 EBX
MOV X,-1; 将 X设置为 -1,变量 X可定义为字节,字,双字类型
3.4.1 立即寻址
操作数直接包含在指令中,紧跟在操作码之后的寻址方式称为立即寻址方式,该操作数也被称为立即数。
举例:
MOV AL,0 0,190,- 1和
MOV AX,190 0FFFFFFFFH为
MOV EAX,-1 立即数 。
MOV EAX,0FFFFFFFFH
操作数包含在 CPU内部的寄存器中举例,MOV BL,80
源操作数使用的是立即寻址;
目标操作数使用寄存器寻址举例,MOV EAX,EBX
EBX和 EAX都是寄存器寻址
3.4.2 寄存器寻址
3.4.3 直接寻址
指令中直接给出了操作数的地址例如,dVar是定义好的一个双字型变
MOV EAX,dVar
MOV dVar,EBX
执行指令,MOV EAX,dVar”时,CPU从指令中得知 dVar的地址,再从地址取出一个双字,送给 EAX。
3.4.4 寄存器间接寻址
操作数的地址放在寄存器中,CPU从寄存器中取得操作数的地址,
例如:
MOV ESI,00404011H
MOV EAX,[ESI]
ESI外面加一对方括号,表示把 ESI作为地址,
从内存中取出一个双字。
3.4.5 寄存器相对寻址
操作数的地址是寄存器和一个立即数相加后得到的结果举例:
MOV ESI,0040200AH
MOV EDI,[ESI+4]
ESI加上 4后得到的结果,作为一个操作数的地址。
再从这个地址中取出一个双字送给 EDI。
3.4.6 基址变址寻址
操作数的地址是两个寄存器相加后得到的结果,两个寄存器分别称为基址寄存器和变址寄存器 。
举例:
MOV ESI,0040200AH
MOV EBX,4
MOV EDI,[EBX+ESI]
3.4.6 基址变址寻址(续)
基址寄存器有两个,BX和 BP
变址寄存器也有两个,SI和 DI
基址变址寄存器只能是 4种组合之一:
[BX+SI],[BX+DI],[BP+SI]和 [BP+DI]。
3.4.7 基址变址相对寻址
操作数的地址是两个寄存器以及一个立即数相加后得到的结果,即基址寄存器,
变址寄存器和相对量。
举例:
MOV ESI,0040200AH
MOV EBX,4
MOV EDI,[EBX+ESI+4]
3.4.8 基址变址比例相对寻址
操作数的地址是由基址寄存器、变址寄存器乘以一个比例数和相对量这 3个部分相加得到的结果。比例数只能有 1,2,4,
8,这 4种取值。
举例:
MOV ESI,0040200AH
MOV EBX,4
MOV EDI,[ESI+EBX*2+4]
3.4.9 寻址方式总结有效地址的计算方式
EA的计算中包括基址,变址,比例,相对这 4个部分 。
每个部分都可以从上面的可选项中任选其一 。
它可以转换为以下几种寻址方式:
比例数取 1时,就变成基址变址相对寻址方式 。
比例数取 1且相对量不出现时,就变成基址变址寻址方式 。
变址寄存器不出现时,就变成寄存器相对寻址方式 。
变址寄存器和相对量不出现时,就变成寄存器间接方式 。
基址寄存器和变址寄存器不出现时,就变成直接方式 。
3.4.10 段超越
内存操作数的地址由两个部分指定:
段和有效地址。
寻址方式中只确定有效地址
段寄存器确定段地址
没有指定段寄存器且寻址方式使用了 ESP
和 EBP寄存器,就使用 SS段寄存器。
其他情况,使用 DS段寄存器。
例如,下面指令中的内存操作数在 SS段中:
MOV EAX,[EBP+8]
MOV EBX,[ESP-4]
下面指令中的内存操作数在 DS段中:
MOV EAX,[EBX+8]
MOV EBX,[ESI-4]
MOV EAX,[0040200AH]
3.5 数据定义
3.5.1 常数的表示
3.5.2 简单数据类型
3.5.3 DUP伪操作
3.5.4 数据定义的例子程序
3.5.1 常数的表示
二进制数字后面跟 b或 B,如 00011011b
八进制数字后面跟 o或 O; 如 33o
十进制数字后面跟 d或 D,如 27d
十六进制数字后面跟 h或 H,如 1BH
数字后面不跟字母时,被当做十进制数
可用,radix指定默认数值 ( 一般不用)
3.5.2 简单数据类型
3.5.2 简单数据类型(续)
定义数据的语句为:
[变量名 ] 助记符 表达式 [,表达式 …]
举例,
bVar DB 120
wVar WORD 200,300
3.5.3 DUP伪操作
为连续的存储单元提供重复数据
格式,N DUP (表达式 )
N为重复因子,只能取正整数
DUP还可以嵌套
常用来定义数组,例如:
bArray WORD 50 DUP (0)
表示字型数组 bArray,有 50个元素,每个元素初值为
0
3.5.4 数据定义的例子程序
说明数据变量的定义和使用方法 的例子
defvar.asm
命令,ml /coff defvar.asm /link subsystem:console
结果:在 VC调试程序中查看数据区的内容如图,
3.6 操作符
3.6.1 常用伪操作
1,PTR伪操作
2,EQU伪操作
3,?(等号)伪操作
4,$ 伪操作
5,ORG伪操作
6,offset操作符
7,type操作符
8,length操作符
9,size操作符
1,PTR伪操作
用法,类型 PTR 地址表达式
类型的取值,BYTE,WORD,DWORD等
作用
( 1)在指令中临时改变变量的类型
( 2)确定指令中操作数的类型
2,EQU伪操作用法为,符号名 EQU 表达式
举例:
NULL EQU 0
MB_OKEQU 0
在程序中就可以使用这些符号来替代这些常量,
EQU的作用和 C语言中的,#define”相似 。
3,?(等号)伪操作用法:符号名? 表达式作用,为常量,表达式及其他各种符号定义一个等价的符号名举例,I = 100
可多次重复定义,以最后一次定义的值为准
而 EQU定义的符号名则只能定义一次
4,$ 伪操作
$ 在程序中表示当前地址计数器的值举例:
wVar WORD 0102h,1000,100*100
BYTESOFWVAR EQU $-wVar
$ 代表该行所在的地址计数器,减去 wVar的地址,
就得到了 wVar所占用的字节数 。
5,ORG伪操作
用法为,ORG 数值表达式
作用:将程序下一行的地址计数器的值设置成数值表达式的值举例:
aVar BYTE 01h
ORG $+10
bVar BYTE 02h
在 aVar和 bVar两个变量中插入 10字节的空间
6,offset操作符
用法为,offset [变量 |标号 ]
作用,取出变量或标号的地址举例:下面 2条语句等价
dVar3 DWORD wVar2
dVar3 DWORD offset wVar2
7,type操作符
用法为,type [变量 ]
作用:返回该变量的一个数据项占用的字节数
8,length操作符
用法为,length [变量 ]
作用:返回定义该变量用 DUP重复的数目,
若没有用 DUP定义该变量,则返回 1
9,size操作符
用法为,size [变量 ]
作用:返回 type返回值乘以 length的值
3.6.2 算术操作符
包括?,?,*,/和 MOD操作符
/表示取商(整数)
MOD表示取余
3.6.3 逻辑操作符
包括 AND,OR,XOR和 NOT
按位操作
只能用在数值表达式中
3.6.4 关系操作符
包括 EQ,NE,LT,LE,GT,GE
对其前后的两个操作数进行比较
操作结果为逻辑值
操作数必须是常数或常数表达式
3.7 寻址方式的应用
解决,如何确定操作数,的问题
可以直接使用 CPU所提供的寻址方式
3.7.1 立即数
可用二进制数、十进制数、十六进制数等表示
可用正数、负数表示
可用字符来表示在内存中都是按二进制数以字节、字或双字等表示
3.7.2 数组元素的访问
bVar,wVar和 dVar分别是有 4,3,4个元素的数组,如何访问这些数组中下标为 2
的元素
MOV EBX,2
MOV AL,bVar[EBX]
MOV AX,wVar[EBX*2]
MOV EAX,dVar[EBX*4]
3.7.3 指针
指针本身也是内存中的一个双字,使用前,应该对它进行初始化
指针中的内容必须是一个有效的地址
END
Windows 汇编程序基础提纲
3.1 机器语言、汇编语言和高级语言
3.2 汇编语言程序的上机过程
3.3 汇编源程序的格式
3.4 操作数的寻址方式
3.5 数据定义
3.6 操作符
3.7 寻址方式的应用
3.1 机器语言、汇编语言和高级语言程序设计程序语言分为三大类:机器语言、
汇编语言和高级语言。
高级语言目前使用较多的是高级语言编程
用高级语言编写的程序便于阅读和修改
计算机不能直接执行
需要由编译程序或解释程序将它翻译成计算机能够接受的机器语言程序
C,C++,java等都是高级语言。
机器语言
计算机能够直接识别的语言
机器指令用二进制代码组成
每条机器指令都由 CPU执行,控制计算机完成一个基本操作机器语言编写的程序是计算机惟一能够直接识别并执行的程序,而用其他语言编写的程序必须经过翻译变换成机器语言程序。
汇编语言
介于机器语言和高级语言之间
充分利用计算机的硬件特性和操作系统底层功能
直接利用 CPU的指令系统
3.2 汇编语言程序的上机过程
开发过程的最终目的是产生一个可执行文件
先要编写相应的程序源文件 ( 源程序 )
再进行编译链接
3.2.1 汇编程序的开发过程
汇编程序的开发过程分为编辑、编译、链接、运行等几个步骤
3.2.1 汇编程序的开发过程(续)
1.汇编程序的后缀为,asm,可以用任何文本编辑程序来编写,但是必须使用,纯文本,格式保存。
2.在编辑生成源文件后,下一步操作就是运行汇编程序对源文件进行汇编,如果没有错误就生成 obj目标代码文件。
3.目标代码文件不能直接运行,将,obj文件和用到的库文件链接起来,生成最终的,exe文件。
4.在得到可执行文件后,再运行可执行文件,检查程序是否可以正确运行 。
如何找到逻辑错误?
一般来说,有 3种常用的方法来查找错误:静态分析,中间结果打印,动态调试 。
3.2.2 MASM汇编器
MASM汇编器的命令行用法为:
ml [/选项 ] 汇编程序源文件 [/link 链接选项 ]
选项 功能
/c 仅进行编译,不自动进行链接
/coff 产生的 obj文件格式为 COFF格式
/Cp 源程序中区分大小写
/Fo filename 指定输出的 obj文件名
/Fl [filename] 产生,lst列表文件
/I pathname 指定 include文件的路径
/link 指定链接时使用的选项
3.2.3 LINK链接器
LINK编译器的命令行用法为:
link [选项 ] [文件列表 ]
选 项 功 能
/out:输出文件名 输出的文件名,扩展名默认为,exe
/map:文件名 生成 MAP文件
/libpath:目录名 指定库文件的目录路径
/implib:文件名 指定导入库文件
/entry:标号 指定入口
/comment:字符串 在 PE 文件的文件头后面加上文本注释(版权信息)
/stack:数字 设定堆栈的大小
/subsystem:系统名 指定程序运行的环境,可以是以下几种之一:
Native,Windows,Console,Windowsce,Posix
以一个源程序文件 hello.asm为例,对它进行汇编链接,最后运行 。
用 MASM汇编一个程序的方法为
ml /c /coff hello.asm
用 LINK链接生成可执行文件的方法为:
link /subsystem:console hello.obj
可以简化为:
ml /coff hello.asm /link /subsystem:console
3.2.4 汇编链接步骤
3.3 汇编源程序的格式
3.3.1 一个显示字符串的汇编程序举例 hello.asm
等同于下面的 C程序
#include <stdio.h>
int main( )
{
printf("Hello World!\n");
return 0;
}
3.3.2 程序格式
1,模式定义程序的第一部分是有关模式定义的 3条语句:
.386
.model flat,stdcall
option casemap:none
这些语句定义了程序使用的指令集,工作模式 。
下面讲一下指令集和工作模式
( 1)指令集
,386语句是汇编语言的伪指令,说明使用的指令集是哪一种 CPU的。
如果用汇编语言编写的是驱动程序或者驱动程序的一个小模块,而且驱动程序在特权级 0上运行,就需要使用,386p,后面带 p的伪指令表示程序中可以使用特权指令。
在编程中如果使用了 MMX指令,除了定义,586之外,还要加上一句,mmx伪指令:
.586
.mmx
( 2)工作模式
.model语句用来定义程序工作的模式,它的格式是:
.model 内存模式 [,调用规则 ][,其他模式 ]
内存模式的定义影响最后生成的可执行文件
在 DOS的可执行程序中,可用到,com文件和,exe文件 。
在 Windows环境下,可执行程序只有一种内存模式,
即 Flat( 平坦 ) 模式 。
( 2)工作模式(续)
在 DOS下的汇编语言程序中,常常有这样的程序片段:
MOV AX,DATA
MOV DS,AX 其作用是给数据段寄存器 DS赋值 。
在编程时,必须考虑这些 DS,ES,SS等段寄存器是否正确设置 。
在 Windows汇编语言程序中,则不必考虑这些问题 。 在程序中,不需要也不应该给 CS,DS,ES,SS等段寄存器赋值 。
( 3) option语句
option语句有许多选项,这里介绍一种,
option casemap:none
这条语句说明程序中的变量和子程序名是否对大小写敏感。
由于 Windows API函数中的函数名称是区分大小写的,所以应该指定这个选项,casemap,none”
3.3.2 程序格式
2,includelib语句汇编程序中也需要调用一些外部模块 ( 子程序 /函数 ) 来完成部分功能 。
例如:使用下面语句通知链接程序使用 msvcrt.lib
includelib msvcrt.lib
若要使用使用其他库文件,只需重复编写
Includelib 库文件名
3.3.2 程序格式
3,函数声明语句对于所有要用到的库函数或 Windows API函数,
在程序的开始部分必须预先声明,包括函数的名称,参数的类型等 。
格式:
函数名称 PROTO [调用规则 ]:[第一个参数类型 ][,:后续参数类型 ]
3.3.2 程序格式
4,include语句
include语句的语法是,include 文件名例如:
include kernel32.inc
include user32.inc
以后程序中用到 user32.dll和 kernel32.dll中的函数时,
不需要事先声明就可以直接使用 。
3.3.2 程序格式
5,数据和代码部分程序中的数据部分和代码部分是分开定义的,
分别以,data 和,code 开始,以 end结束。
end语句一般是整个程序的最后一条语句,end
语句后面跟的是起始标号,指出了程序执行的第一条指令的位置 。
3.3.2 程序格式
6,跨行的语句当源程序的某一语句过长,不利于书写和阅读时,可以用反斜杠 ( \) 作为换行符,将这条语句分为几行来写 。
3.3.3 一个 Windows界面的汇编程序
下面给出一个使用 Windows图形界面的汇编源程序 。
hellow2.asm( 显示一个 Windows消息框 )
在编译链接时,必须在 subsystem选项中指定
,windows”,而不是,console”。 命令为:
ml /coff hellow.asm /link /subsystem:windows
运行结果:
3.4 操作数的寻址方式
寻址方式就是如何表示操作数的各种方法。
以 MOV指令为例:
格式,MOV DST,SRC
DST为目标操作数,SRC为源操作数,即 SRC→ DST
DST和 SRC的数据类型应该一致举例
例如,以下的一些数据传送操作都是用 MOV指令完成的
MOV AL,127; 将 AL的内容设置为 127,即 7FH
MOV DX,100; 将 DX的内容设置为 100,即 0064H
MOV EAX,0; 将 EAX的内容设置为 0
MOV EBX,EAX; 将 EAX的内容复制到 EBX
MOV X,-1; 将 X设置为 -1,变量 X可定义为字节,字,双字类型
3.4.1 立即寻址
操作数直接包含在指令中,紧跟在操作码之后的寻址方式称为立即寻址方式,该操作数也被称为立即数。
举例:
MOV AL,0 0,190,- 1和
MOV AX,190 0FFFFFFFFH为
MOV EAX,-1 立即数 。
MOV EAX,0FFFFFFFFH
操作数包含在 CPU内部的寄存器中举例,MOV BL,80
源操作数使用的是立即寻址;
目标操作数使用寄存器寻址举例,MOV EAX,EBX
EBX和 EAX都是寄存器寻址
3.4.2 寄存器寻址
3.4.3 直接寻址
指令中直接给出了操作数的地址例如,dVar是定义好的一个双字型变
MOV EAX,dVar
MOV dVar,EBX
执行指令,MOV EAX,dVar”时,CPU从指令中得知 dVar的地址,再从地址取出一个双字,送给 EAX。
3.4.4 寄存器间接寻址
操作数的地址放在寄存器中,CPU从寄存器中取得操作数的地址,
例如:
MOV ESI,00404011H
MOV EAX,[ESI]
ESI外面加一对方括号,表示把 ESI作为地址,
从内存中取出一个双字。
3.4.5 寄存器相对寻址
操作数的地址是寄存器和一个立即数相加后得到的结果举例:
MOV ESI,0040200AH
MOV EDI,[ESI+4]
ESI加上 4后得到的结果,作为一个操作数的地址。
再从这个地址中取出一个双字送给 EDI。
3.4.6 基址变址寻址
操作数的地址是两个寄存器相加后得到的结果,两个寄存器分别称为基址寄存器和变址寄存器 。
举例:
MOV ESI,0040200AH
MOV EBX,4
MOV EDI,[EBX+ESI]
3.4.6 基址变址寻址(续)
基址寄存器有两个,BX和 BP
变址寄存器也有两个,SI和 DI
基址变址寄存器只能是 4种组合之一:
[BX+SI],[BX+DI],[BP+SI]和 [BP+DI]。
3.4.7 基址变址相对寻址
操作数的地址是两个寄存器以及一个立即数相加后得到的结果,即基址寄存器,
变址寄存器和相对量。
举例:
MOV ESI,0040200AH
MOV EBX,4
MOV EDI,[EBX+ESI+4]
3.4.8 基址变址比例相对寻址
操作数的地址是由基址寄存器、变址寄存器乘以一个比例数和相对量这 3个部分相加得到的结果。比例数只能有 1,2,4,
8,这 4种取值。
举例:
MOV ESI,0040200AH
MOV EBX,4
MOV EDI,[ESI+EBX*2+4]
3.4.9 寻址方式总结有效地址的计算方式
EA的计算中包括基址,变址,比例,相对这 4个部分 。
每个部分都可以从上面的可选项中任选其一 。
它可以转换为以下几种寻址方式:
比例数取 1时,就变成基址变址相对寻址方式 。
比例数取 1且相对量不出现时,就变成基址变址寻址方式 。
变址寄存器不出现时,就变成寄存器相对寻址方式 。
变址寄存器和相对量不出现时,就变成寄存器间接方式 。
基址寄存器和变址寄存器不出现时,就变成直接方式 。
3.4.10 段超越
内存操作数的地址由两个部分指定:
段和有效地址。
寻址方式中只确定有效地址
段寄存器确定段地址
没有指定段寄存器且寻址方式使用了 ESP
和 EBP寄存器,就使用 SS段寄存器。
其他情况,使用 DS段寄存器。
例如,下面指令中的内存操作数在 SS段中:
MOV EAX,[EBP+8]
MOV EBX,[ESP-4]
下面指令中的内存操作数在 DS段中:
MOV EAX,[EBX+8]
MOV EBX,[ESI-4]
MOV EAX,[0040200AH]
3.5 数据定义
3.5.1 常数的表示
3.5.2 简单数据类型
3.5.3 DUP伪操作
3.5.4 数据定义的例子程序
3.5.1 常数的表示
二进制数字后面跟 b或 B,如 00011011b
八进制数字后面跟 o或 O; 如 33o
十进制数字后面跟 d或 D,如 27d
十六进制数字后面跟 h或 H,如 1BH
数字后面不跟字母时,被当做十进制数
可用,radix指定默认数值 ( 一般不用)
3.5.2 简单数据类型
3.5.2 简单数据类型(续)
定义数据的语句为:
[变量名 ] 助记符 表达式 [,表达式 …]
举例,
bVar DB 120
wVar WORD 200,300
3.5.3 DUP伪操作
为连续的存储单元提供重复数据
格式,N DUP (表达式 )
N为重复因子,只能取正整数
DUP还可以嵌套
常用来定义数组,例如:
bArray WORD 50 DUP (0)
表示字型数组 bArray,有 50个元素,每个元素初值为
0
3.5.4 数据定义的例子程序
说明数据变量的定义和使用方法 的例子
defvar.asm
命令,ml /coff defvar.asm /link subsystem:console
结果:在 VC调试程序中查看数据区的内容如图,
3.6 操作符
3.6.1 常用伪操作
1,PTR伪操作
2,EQU伪操作
3,?(等号)伪操作
4,$ 伪操作
5,ORG伪操作
6,offset操作符
7,type操作符
8,length操作符
9,size操作符
1,PTR伪操作
用法,类型 PTR 地址表达式
类型的取值,BYTE,WORD,DWORD等
作用
( 1)在指令中临时改变变量的类型
( 2)确定指令中操作数的类型
2,EQU伪操作用法为,符号名 EQU 表达式
举例:
NULL EQU 0
MB_OKEQU 0
在程序中就可以使用这些符号来替代这些常量,
EQU的作用和 C语言中的,#define”相似 。
3,?(等号)伪操作用法:符号名? 表达式作用,为常量,表达式及其他各种符号定义一个等价的符号名举例,I = 100
可多次重复定义,以最后一次定义的值为准
而 EQU定义的符号名则只能定义一次
4,$ 伪操作
$ 在程序中表示当前地址计数器的值举例:
wVar WORD 0102h,1000,100*100
BYTESOFWVAR EQU $-wVar
$ 代表该行所在的地址计数器,减去 wVar的地址,
就得到了 wVar所占用的字节数 。
5,ORG伪操作
用法为,ORG 数值表达式
作用:将程序下一行的地址计数器的值设置成数值表达式的值举例:
aVar BYTE 01h
ORG $+10
bVar BYTE 02h
在 aVar和 bVar两个变量中插入 10字节的空间
6,offset操作符
用法为,offset [变量 |标号 ]
作用,取出变量或标号的地址举例:下面 2条语句等价
dVar3 DWORD wVar2
dVar3 DWORD offset wVar2
7,type操作符
用法为,type [变量 ]
作用:返回该变量的一个数据项占用的字节数
8,length操作符
用法为,length [变量 ]
作用:返回定义该变量用 DUP重复的数目,
若没有用 DUP定义该变量,则返回 1
9,size操作符
用法为,size [变量 ]
作用:返回 type返回值乘以 length的值
3.6.2 算术操作符
包括?,?,*,/和 MOD操作符
/表示取商(整数)
MOD表示取余
3.6.3 逻辑操作符
包括 AND,OR,XOR和 NOT
按位操作
只能用在数值表达式中
3.6.4 关系操作符
包括 EQ,NE,LT,LE,GT,GE
对其前后的两个操作数进行比较
操作结果为逻辑值
操作数必须是常数或常数表达式
3.7 寻址方式的应用
解决,如何确定操作数,的问题
可以直接使用 CPU所提供的寻址方式
3.7.1 立即数
可用二进制数、十进制数、十六进制数等表示
可用正数、负数表示
可用字符来表示在内存中都是按二进制数以字节、字或双字等表示
3.7.2 数组元素的访问
bVar,wVar和 dVar分别是有 4,3,4个元素的数组,如何访问这些数组中下标为 2
的元素
MOV EBX,2
MOV AL,bVar[EBX]
MOV AX,wVar[EBX*2]
MOV EAX,dVar[EBX*4]
3.7.3 指针
指针本身也是内存中的一个双字,使用前,应该对它进行初始化
指针中的内容必须是一个有效的地址
END