【VC++开源代码栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了VC++开源代码-汇编语言程序设计初步 - 综合课件的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
第5章汇编语言程序设计初步绍汇编语言源程序的一般结构以及其用于编制源程序的各种伪指令–汇编语言程序的编辑、汇编、连接和调试的过程。
–汇编语言源程序的框架结构。
–常量的使用变量定义及使用标号的定义与使用。
–常用的基本伪指令和操作符。
–一些高级汇编伪指令5.1 概述用指令助记符和符号地址来编写程序汇编程序将源
代码翻译成二进制编码包括指令助记符、数据和存放数据的变量、标号、伪指令及相应的使用规则源程序中一条汇编指令或伪指令均占一行–指令语句标号: 助记符Op1Op2…注释–伪指令语句符号 伪指令助记符Op1Op2…注释开发过程开发过程以下以DOS环境下为例介绍开发过程例在屏幕上显示“Hello World”_STACKSEGMENT STACK STACK 定义堆栈段DB 32766 DUP0 堆栈区长度32766232KBTOSDW 0 初始堆栈栈顶_STACKENDS 堆栈段定义结束_DATASEGMENT 定义数据段MsgDBHello World 1310_DATAENDS 数据段定义结束_TEXTSEGMENTCODE 定义
代码段ASSUME CS: _TEXT DS:_DATA SS:_STACKStart:MOVAX _DATA 取数据内存区段地址MOVDS AX 设置数据段寄存器CLI 设置堆栈期间禁止响应中断MOVAX _STACK 取堆栈内存区段地址MOVSS AX 设置堆栈段寄存器MOVSP Offset TOS 设置初始状态时的堆栈指针STI 堆栈设置完毕允许中断MOVDX Offset MsgMOVAH 9INT21h 中断21h的9号功能显示DS:DX指向的字符串MOVAX 4C00hINT21h 运行结束返回DOS_TEXTENDS
代码段定义结束ENDStart 源程序到此为止开发过程续11. 汇编源程序的编辑纯文本处理软件均可编辑源程序DOS下的EDIT记事本…。
以.ASM类型保存如Exam.ASM。
2. 汇编源程序的汇编将汇编语言源程序汇编成目标
代码.OBJ文件。
在DOS环境下操作如下MASMExam.ASM??Exam.ASM经MASM汇编后可生成Exam.OBJ–程序汇编的主要功能是检查源程序是否符合汇编语言的规则即进行语法检查。
通过语法检查后再将指令助记符、符号地址等转换成二进制编码形成目标
代码。
否则给出相应的错误信息这时应根据错误信息重新编辑源程序后再进行汇编。
MASM 6.15中的MASM.EXE调用ML.EXE实际上是ML /cExam.ASM??开发过程续23. 目标
代码的连接将目标
代码转换成执行文件.EXE等类型。
LINKExam.OBJ??汇编、连接这两个操作过程可由ML直接完成MLExam.ASM??4. 可执行程序的运行与调试生成运行程序Exam.EXE后在DOS下输入文件名运行Exam??DOS将Exam.EXE调入内存并运行。
运行结束后返回DOS汇编语言程序的调试工具有Debug、Codeview以及其他一些可视的化界面调试工具需要观察相关变量即内存单元、寄存器等内容的变化、标志寄存器各标志状态的改变、堆栈状态的变化EXAM.ASM编辑程序汇编程序连接程序EXAM.CRFEXAM.OBJEXAM.lstEXAM.objEXAM.MAPEXAM.EXE运行5.2 源程序的基本框架结构汇编语言程序对内存是分段使用的一般情况下内存被分为三种类型区–堆栈段区CS指向正当前运行的
代码段–数据段区DS指向当前的数据段–
代码段区SS指向当前的堆栈段下面以一个简单的程序例子来介绍汇编语言程序的基本框架结构5.2.1 内存的分段使用完整源程序应有堆栈段数据段
代码段1. 堆栈段–定义并分配供堆栈使用的内存区并用一个符号表示栈内存区最高栈单元指示初始栈顶位置方便对SP的初始赋值2. 数据段–为数据提供内存区。
通常变量都应放在数据段中3.
代码段–为指令
代码提供内存区。
通常指令
代码都应放在
代码段内堆栈段_STACKSEGMENT STACK STACK 定义堆栈段DB 32766 DUP0 堆栈区长度32766232KBTOSDW 0 初始堆栈栈顶_STACKENDS 堆栈段定义结束_DATASEGMENTDATA 定义数据段MsgDBHello World 1310_DATAENDS 数据段定义结束_TEXTSEGMENTCODE 定义
代码段ASSUME CS: _TEXT DS:_DATA SS:_STACKStart:MOVAX _DATA 取数据内存区段地址MOVDS AX 设置数据段寄存器CLI 设置堆栈期间禁止响应中断MOVAX _STACK 取堆栈内存区段地址MOVSS AX 设置堆栈段寄存器MOVSP Offset TOS 设置初始状态时的堆栈指针STI 堆栈设置完毕允许中断MOVDX Offset MsgMOVAH 9INT21h 中断21h的9号功能显示DS:DX指向的字符串MOVAX 4C00hINT21h 运行结束返回DOS_TEXTENDS
代码段定义结束ENDStart 源程序到此为止分配空间32768B栈顶位置设置堆栈数据段定义变量等设置数据段
代码段5.2.2 源程序的结束与执行入口语言源程序总是以END作为结束标志END后面可附带一个在程序中已定义的标号用以说明程序的在调入时开始执行的第一条指令所在位置–源程序是一个独立的程序或主模块那么伪指令END后面必须附带一个标号–源程序仅是一个普通模块那么其END后面就不能附带标号运行于操作系统下的汇编语言程序须在程序中通过操作系统的相关功能调用来结束其运行_STACKSEGMENT STACK STACK 定义堆栈段DB 32766 DUP0 堆栈区长度32766232KBTOSDW 0 初始堆栈栈顶_STACKENDS 堆栈段定义结束_DATASEGMENTDATA 定义数据段MsgDBHello World 1310_DATAENDS 数据段定义结束_TEXTSEGMENTCODE 定义
代码段ASSUME CS: _TEXT DS:_DATA SS:_STACKStart:MOVAX _DATA 取数据内存区段地址MOVDS AX 设置数据段寄存器CLI 设置堆栈期间禁止响应中断MOVAX _STACK 取堆栈内存区段地址MOVSS AX 设置堆栈段寄存器MOVSP Offset TOS 设置初始状态时的堆栈指针STI 堆栈设置完毕允许中断MOVDX Offset MsgMOVAH 9INT21h 中断21h的9号功能显示DS:DX指向的字符串MOVAX 4C00hINT21h 运行结束返回DOS_TEXTENDS
代码段定义结束ENDStart 源程序到此为止源程序到此为止标号指明调入内存后开始运行的第一条指令。
主模块END后面必须有一个标号非主模块那么其END后面就不能有标号通过4Ch号DOS功能调用结束程序运行返回操作系统5.2.3 汇编语言程序的运行平台汇编语言可开发运行在不同的系统平台上的应用程序基本框架结构相似但是在具体的系统功能调用不同DOS环境下的源程序框架结构
VC中汇编集成环境的设置Win32以
VC 6.0为例1 创建一个空Project2 将源程序加入到Source Files中3 Debug和Release的设置Win32 Debug的设置??CommandsD:MASMML /c /coff /Zi /Zd /FoOutDirInputName.OBJ InputPath??OutputsOutDirInputName.OBJWin32 Release的设置??CommandsD:MASMML /c /coff /FoOutDirInputName.OBJ InputPath??OutputsOutDirInputName.OBJ5.3 常数、变量和标号汇编语言程序其他两方面内容–与数据相关的常量与变量–与转移地址相关的标号与过程标号名、变量名、过程名、段名等称为标识符–组成标识符字符字母AZ az、数字09及、.、、和_下画线。
–数字不能作首字符.只能作为标识符的首字符。
–标识符的长度没有严格限制一般不应超过31字符–保留字不能作为标识符使用。
5.3.1 常数常量是数的本身不对应任何存储单元寄存器或内存单元其数值在汇编期间已能够完全确定且在程序运行期间也不会发生变化。
常量一般可分为–数值常数–字符串常数。
1. 数值常数1 整数常数十进制常数09组成以D或d结尾如255D十六进制常数09 AF或af组成以H或h结尾如64h 0B8h。
–为区别于标识符字母开头的十六进制数前须加0二进制常数由0 1组成以B或b结尾如1100B八进制常数由07组成以Q或q如144Q通常常数默认为十进制此时后面D或d可省略–可以用伪指令RADIX改变默认的数制其格式为–.RADIX 用十进制形式表示的基数2 实数常数实数其实就是带小数点的数。
实数常数有两种形式表示–带小数点的十进制数形式例如-1.414–指数形式例如4.56E-2 -1.732E10实常数以浮点格式存放2. 字符串常数字符串常数是用“‘”单撇号或“””双撇号括起来的单个字符或多个字符对于ASCII字符来说其数值是字符对应的ASCII码的值例如–d对应的是64h–AB对应的是41h 42h–Hello World对应的是48h 65h 6Ch 6Ch 6Fh 2Ch 20h 57h 6Fh 72h 6Ch 64h 21h对于汉字来说其数值是汉字的内码如–你好对应是0C4h 0E3h 0Bah 0C3h 21h3. 常数的应用1 作为立即数出现在指令中MOVAX 1234hSUBAL 0ANDEAX 7FFFFFFFh2 作为内存操作数的位移量地址编号MOVAX 1000hADD100hBX ALTESTEAX 1000hEBXEDX43 为数据定义预置初始值VariableDW1234hStrDBHello World 13 10 xDQ4.756E3 5.3.2 变量变量是存放数据的内存单元名称–变量名是符号地址–具有类型属性字节、字、双字…1. 变量的定义数据定义伪指令的格式是变量名 数据定义伪指令初值表注释 分配一个或多个指定类型的内存单元并可用变量表示该内存单元如果有变量名那么它仅代表所定义的数据存储区的第一个单元地址用DB、DW、DD、DF、DQ、DT定义并分配1个或多个1B、2B、4B、6B、8B、10B类型的存储单元变量定义示例MsgDBHello 定义变量分配5个1B空间置初值DB13 10 分配3个B空间置初值CntDW520 -2 定义变量分配2个2B空间置初值S1DB 定义变量分配4个1B空间未置初值DD123456h 分配2个4B空间1. 变量的定义续—初值表用逗号分隔的若干个数据项每项是定义并分配的存储单元的一个初始内容1 常数或常数表达式MsgDBHelloDB13 10 CntDW520 -2LDD1234A1B2h 87654321hFDQ1.5–定义并分配的数据存储单元及初始化情况2“”形式–分配一个或多个存储单元但内容不确定。
–一般情况下程序在汇编时以0填充。
3 符号地址及地址表达式–符号地址对应的地址编号–是无符号整型常数MsgDBHello 13 10 p1DWMsg Msg5p2DDMsg Msg54 可用DUP把某项重复n次。
其格式为nDUP数据项 s1DB你好 2DUP 2DUP A B 3 DUP1 2 2 DUP–定义了以s1为首地址的22个字节单元其初始内容是0C4h 0E3h 0BAh 0C3h 21h 21h41h 42h 41h 42h 01h02h24h24h01h02h24h24h01h02h24h24h 2. 变量的属性1 地址属性–段地址可由SEG运算符返回–偏移地址可由运算符OFFSET返回MOV AXSEG Msg将Msg的段地址送到AXMOV BXOFFSET Msg将Msg的偏移地址送到BX当需要存取某一变量时必须先将该段的段地址放到相应的段寄存器如DS、ES等 MOVAX _DATAMOVDS AX 2 类型属性伪指令DB DW DD DF DQ DT可定义1 2 4 6 8 10字节类型可以指定数据类型Byte Ptr指定数据或变量为字节类型8位Word Ptr指定数据或变量为2字节字类型16位DWord Ptr指定数据或变量为4字节双字类型32位FWord Ptr指定数据或变量为6字节类型48位QWord Ptr 指定数据或变量为8字节四字类型64位TByte Ptr指定数据或变量为10字节类型80位变量名对应的是内存单元地址是无符号符号整常数加、减一个整常数就是地址编号加、减一个整常数仍然对应一个内存单元地址其类型与原变量相同LDD1234A1B2h 87654321h–L是4字节类型单元L1对应的也是4字节类型单元其内容是211234A1h–L1可以写成L1注意L1是L的偏移地址加1而不是加1×4每种数据类型的类型值就是其占用的字节数可用运算符TYPE将它分离出来3. 变量的使用对于内存操作数除寄存器间接寻址方式不使用变量名外其余各种寻址方式均可使用变量名表示VariableDW100 DUP0用变量名表示的内存操作数寻址为–直接寻址MOVAX Variable–寄存器相对寻址MOVAX Variable SI–相对基址变址寻址MOVAX Variable BXDI–比例因子寻址MOVEAX DWord Ptr Variable EBX4ECX5.3.3 标号1. 标号的定义标号表示的是指令在内存中存放的位置。
标号定义的格式是标号名:表示标号后首条指令在内存中地址标号既可以定义在目的指令同一行的最前面也可以在目的指令前一行单独用一行定义2. 标号的属性1 地址属性标号代表的是其后首条指令在内存中地址–用SEG来返回标号所在段的段地址–用OFFSET来返回标号所在段的偏移地址MOV AXSEG loc1将loc1的段地址送到AXMOV BXOFFSET loc1将loc1的偏移地址送到BX2 类型属性标号具有NEAR和FAR两种属性其类型值分别为-1和-2可用运算符TYPE返回其类型值例5.4编写程序从键盘输入两个字符并输出其中ASCII码较大的字符。
参照图5.2所示的程序框架结构将堆栈区大小、数据定义、实现题目要求的指令序列分别填写在相应处_STACKSEGMENTSTACK STACKDB 2046 DUP0分配堆栈区空间204622KBTOSDW 0_STACKENDS_DATASEGMENTsDB 13 10 is greater“定义字符串变量s_DATAENDS_TEXTSEGMENTCODEASSUMECS: _TEXT DS: _DATASS: _STACKStart:MOVAX _DATAMOVDS AXCLIMOVAX _STACKMOVSS AXMOVSP Offset TOSSTIMOVAH 1INT21hMOVs2 ALMOVAH 1INT21hCMPAL s2解决问题的指令JBloc1MOVs2 ALloc1:MOVDX Offset sMOVAH 9INT21hMOVAX 4C00hINT21h_TEXTENDSENDStart5.3.4 变量名和标号的其他定义方式用LABEL和EQU来定义变量名或标号–标识符LABEL类型–标识符EQUTHIS类型功能定义一个指定类型的变量名或标号–类型为BYTE WORD DWORD FWORD QWORD和TBYTE等则定义变量名–类型是NEAR和FAR则定义标号只是将当前地址定义为一个变量名或标号并不为它们分配内存空间bVariableLABELBYTEwVariableDW100第一条伪指令仅仅定义了一个具有字节类型的变量名但并没有为它分配存储空间第二条伪指令定义了一个字类型的变量而且为它分配了2字节的存储空间。
符号地址bVariable与wVariable代表的是同一个地址但具有不同的数据类型属性。
Loc LABEL FAR定义了一个具有远转移类型的标号该标号指向其后第一条汇编指令的存放地址。
wVariableEQU THISDWORDdwVariableDB100第一条伪指令仅仅定义了一个具有2字节类型的变量名但并没有为它分配存储空间第二条伪指令定义了一个4字节类型的变量而且为它分配了4字节的存储空间。
符号地址dwVariable与wVariable代表的是同一个地址但具有不同的数据类型属性。
Loc EQU THIS NEAR定义了一个具有近转移类型的标号该标号指向其后第一条汇编指令的存放地址。
5.3.5 表达式和运算符将常数、符号地址及其符号常量用运算符连接起来的有意义的式子值的计算是在源程序汇编过程中完成的运算符分为–算术运算符–逻辑运算符–关系运算符–数值返回运算符–属性运算符–字节分离运算符1. 算术运算符运算符格式功能描述表达式值取正--表达式值取负两式相乘//两式相除MODMOD两式整除取余两式相加--两式相减SHRSHR将表达式的值右移N位SHLSHL将表达式的值左移N位 表达式2等同2. 逻辑运算符运算符格式功能描述NOTNOT表达式值按位取“反”ANDAND两表达式值按位“与”OROR两表达式值按位“或”XORXOR两表达式值按位“异或”3. 关系运算符运算符格式功能EQEQ两个表达式值相等为真否则为假NENE两个表达式值不相等为真否则为假LTLT表达式1表达式2为真否则为假GEGE表达式1≥表达式2为真否则为假4. 数值返回运算符运算符格式功能描述SEGSEG返回符号地址的段地址OFFSETOFFSET返回符号地址的偏移地址LENGTHLENGTH返回变量元素个数SIZESIZE返回变量所占字节数TYPETYPE返回变量或标号的类型值5. 属性运算符类型运算符功能描述Byte Ptr指定数据或变量为字节类型8位Word Ptr指定数据或变量为2字节字类型16位DWord Ptr指定数据或变量为4字节双字类型32位FWord Ptr指定数据或变量为6字节类型48位QWord Ptr指定数据或变量为8字节四字类型64位TByte Ptr指定数据或变量为10字节类型80位Near Ptr指定标号为近转移目标地址Far Ptr指定标号为远转移目标地址5.4 MASM的基本伪指令伪指令在汇编程序对源程序汇编期间由汇编程序处理的操作它们可以完成诸如定义程序段、定义数据、分配存储区和指示程序结束等功能。
伪指令在形式上与一般指令相似但伪指令只是为汇编程序提供有关信息不产生相应的机器
代码5.4.1 指令集选择伪指令MASM在默认情况下只接受8086指令集。
如果程序员需要使用8086以后微处理器新增加的指令必须使用指令集选择伪指令伪指令功能描述.8086仅接受8086指令默认状态.186接受80186指令.286接受除特权指令外的80286指令.286P接受全部80286指令包括特权指令.386接受除特权指令外的80386指令.386P接受全部80386指令包括特权指令.486接受除特权指令外的80486指令包括浮点指令.486P接受全部80486指令包括特权指令和浮点指令.8087接受8087数学协处理器指令.287接受80287数学协处理器指令.387接受80387数学协处理器指令.No87取消使用协处理器指令.586接受除特权以外的Pentium指令.586P接受全部的Pentium指令.686接受除特权以外的Pentium Pro指令.686P接受全部的Pentium Pro指令.MMX接受MMX指令.K3D接受AMD处理器的3DNow指令.XMM接受SEE指令和SSE2指令5.4.2 完整的段定义伪指令使用完整的段定义伪指令来定义一个段可具体控制汇编程序MASM和连接程序LINK在内存中组织
代码和数据的方式格式段名SEGMENT 定位类型 组合方式 地址模式 分类名段名ENDS功能在程序中定义一个逻辑段指定段的名字和范围段在内存中的起始位置以及段与段之间的连接关系。
1 段名是由程序员指定的一个标识符。
–段开始与结束的段名必须一致–可以定义若干个段段名可以各不相同也可以重复汇编程序将同名段处理成一个段2 每个逻辑段都以SEGMENT伪指令为开始标记以ENDS伪指令为结束标记3 将DS和SS指向使用的数据段和堆栈段4 定位类型、组合方式、地址模式、分类名是可选项视情况可以选用或省略定位类型规定该段在内存中起始位置的对齐方式–BYTE段可以从任何地址开始这样起始的偏移地址可能不为0。
–WORD段必须从字的边界开始即段起始地址必须为偶数。
–DWORD段必须从双字的边界开始即段起始地址必须为4的整数倍。
–PARA段必须从节边界开始即段起始地址必须是16的整数倍。
–PAGE段必须从页边界开始即段起始地址必须是256的整数倍。
默认项是PARA
上一篇:
VS2010 C++下编译调试MongoDB源码
下一篇:
浅析普外科围手术期抗菌药物的应用