宏汇编程序
宏汇编程序是具有宏加工功能的汇编程序。可以用它定义含参数的程序段,在使用的位置上调用它们,汇编时将进行宏(指令)展开,把宏定义所预先定义的指令目标代码插在该位置上。1
宏汇编程序的主要特点是在汇编程序中增加宏加工功能。它允许用户方便地定义和使用宏指令,适用于程序中多处出现、具有一定格式、可以通过少数参数调节改变的程序段落的场合。采用这种方法不仅减少程序的长度,增加可读性,而且程序段落的格式需要改变时,只须改动定义处,而不必改动每一使用处。2
宏指令与宏定义按其最简单的形式,宏指令(通常简称宏)是单个计算机指令,它表示一个给定的指令序列。要实现宏,就需要一段称为宏处理程序的软件,它本身往往是汇编语言软件系统的一部分。几乎在所有的计算机上都有宏处理程序,但是它们的设计还未标准化。一个宏处理程序的作业很简单。程序员提供一些宏定义,它们定义宏和代替宏的指令,宏处理程序则在该宏的每次出现时进行代替。
例如,假设一个程序员要在程序中几个地方使一个名字为COUNT的变量增1。又假设运用如下三个汇编语言指令:
LOAD COUNT ADD 1
STORE COUNT
若继续全部写出这三个指令将浪费程序员的时间。最好选用单个名字(例如BUMPCOUNT)来代表这些指令,然后每当需要指定这三个指令时写这个名字。于是源程序按图1所示进行处理。
宏定义定义BUMPCOUNT和取代它的指令。在实际中,也许还有其他几个宏定义。然后宏处理程序扫描该程序,把BUMPCOUNT的每次出现都用其扩展形式代替。其他已定义的宏也同样处理。由此,该程序则处于纯汇编语言表示,它可被传送到汇编程序,汇编程序以常规的方式对它进行处理。 3
错误码汇编程序在对源程序的汇编过程中,若检查出某语句有语法错误,随时在屏幕上给出出错信息,。操作人员指定的列表文件名(即.LST),汇编程序亦将在列表文件中出错的下面给出出错信息,以便操作人员即时查找错误,给予更正。
MASM5.0出错信息格式如下:
源程序文件行:WARNING/ERROR错误信息码:错误描述信息
错误码组成错误描述信息码由五个字符组成:
(1)第一个是字母A:表示汇编语言程序出错;
(2)接着有一个数字指明出错类别:'2'为严重错误,'4'为严肃警告,'5'为建议性警告;
(3)最后三位为错误编号。
错误编号及其对应的错误描述0:Block nesting error:嵌套出错。嵌套的过程、段、结构、宏指令或重复块等非正常结束。例如在嵌套语句中有外层的结束语句,而无内层的结束语局。
1:Extra characters on line:一语句行有多余字符,可能是语句中给出的参数太多。
2:Internal error-Register already defined:这是一个内部错误。如出现该错误,请记下发生错误的条件,并使用Product Assistance Request 表与Microsoft公司联系。
3:Unkown type specifer:未知的类型说明符。例如类型字符拼错,把BYTE写成BIT,NEAR写成NAER等。
4:Redefinition of symbol:符号重定义。同一标识符在两个位置上定义。在汇编第一遍扫描时,在这个标识符的第二个定义位置上给出这个错误。
5:Symbol is multidefined:符号多重定义。同一标识符在两个位置上定义。在汇编第二遍扫描时,每当遇到这个标识符都给出这个错误。
6:Phase error between passes:两次扫描间的遍错。一个标号在二次扫描时得到不同的地址值,就会给出这种错误。若在启动MASM时使用/D任选项,产生第一遍扫描的列表文件,它可帮助你查找这种错误。
7:Already had ELSE clause:已有ELSE语句。在一个条件块里使用多于一个的ELSE语句。
8:Must be in conditional block:没有在条件块里。通常是有ENDIF或ELSE语句,而无IF 语句。
9:Symbol not defined:符号未定义,在程序中引用了未定义的标识符。
10:Syntax error:语法错误。不是汇编程序所能识别的一个语句。
11:Type illegal in context:指定非法类型。例如对一个过程指定BYTE类型,而不是NEAR或FAR。
12:Group name must be unique:组名应是唯一的。作为组名的符号作为其他符号使用。
13:Must be declared during pass 1:必须在第一遍扫描期间定义。在第一遍扫描期间,如一个符号在未定义前就引用,就会出现这种错误。
14:Illegal public declaration:一个标识符被非法的指定为PUBLIC类型。
15:Symbol already defferent kind:重新定义一个符号为不同种类符号。例如一个段名重新被当作变量名定义使用。
16:Reserved word used as symbol:把汇编语言规定的保留字作标识符使用。
17:Forward reference illegal:非法的向前引用。在第一遍扫描期间,引用一个未定义符号。
18:Operand must be register:操作数位置上应是寄存器,但出现了标识符。
19:Wrong type of register:使用寄存器出错。
20:Operand must be segment or group:应该给出一个段名或组名。例如ASSUME语句中应为某段寄存器和指定一个段名或组名,而不应是别的标号或变量名等。
21:Symbol has no segment:不知道标识符的段属性。
22:Operand must be type specifier:操作数应给出类型说明,如NEAR,FAR,BYTE等。
23:Symbol alread defined locally:以被指定为内部的标识符,企图在EXTRN语句中又定义外部标识。
24:Segment paraneters are changed:段参数被改变。如同一标识符定义在不同段内。
25:Improper align/combin type:段定义时的定位类型/组合类型使用出错。
26:Reference to multidefined symbol:指令引用了多重定义的标识符。
27:Operand expected:需要一个操作数,只有操作符。
28:Operator expected:需要一个操作符,但只有操作数。
29:Divdsion by 0 or overflow:除以0或溢出。
30:Negative shift count:运算符SHL或SHR的移位表达式值为负数。
31:Operand type must match:操作数类型不匹配。双操作数指令的两个操作数长度不一致,一个是字节,一个是字。
32:Illegal use of external:外部符号使用出错。
33:Must be record field name:应为记录字段名。在记录字段名位置上出现另外的符号。
34:Must be record name or field name:应为记录名或记录字段名。在记录名或记录字段名位置上出现另外的符号。
35:Operand must be size:应指明操作数的长度(如BYTE,WORD等)。通常使用PTR运算即可改正。
36:Must be variable,label,or constant:应该是变量名,标号,或常数的位置上出现了其他信息。
37:Must be stucture field name:应该为结构字段名。在结构字段名位置上出现了另外的符号。
38:Lefe operand must segment:操作数的左边应该是段的信息。如设DA1,DA2均是变量名,下列语句就是错误的:"MOV AX,DA1:DA2"。DA1位置上应使用某段寄存器名。
39:One operand must constant:操作数必须是常数。
40:Operand must be in same segment or one constant:"—"运算符用错。例如"MOV AL,—VAR",其中VAR是变量名,应有一常数参加运算。又如两个不同段的变量名相减出错。
41:Normal type operand expected:要求给出一个正常的操作数。
42:Constant expected:要求给出一个常数。
43:Operand must have segment:运算符SEG用错。
44:Must be associated with data:在必须与数据段有关的位置上出现了代码段有关的项。
45:Must be associated with code:在必须与代码段有关的位置上出现了数据段有关的项。
46:Multiple base registers:同时使用了多个基址寄存器。 如"MOV AX ,[SI][BP]"。
47:Multiple index registers:同时使用了多个变址寄存器。 如"MOV AX ,[SI][DI]"。
48:Must be index or base register:指令仅要求使用基址寄存器或变址寄存器, 而不能使用其他寄存器。
49:Illegal use of register:非法使用寄存器出错。
50:Value is out of range:数值太大, 超过允许值。 例如:"MOV AL ,100H"。
51:Operand not in current CS ASSUME segment:操作数不在当前代码段内。 通常指转移指令的目标地址不在当前CS段内。
52:Improper operand type:操作数类型使用不当。 例如:"MOV VAR1,VAR2"。 两个操作数均为存储器操作数, 不能汇编出目标代码。
53:Jump out of range by %ld byte:条件转移指令跳转范围超过-128~ 127 个字节。 出错厂, 信息同时给出超过的字节数。
54:Index displacement must be constant:变址寻址的位移量必须是常数。
55:Illegal register value:非法的寄存器值。 目标代码中表达寄存器的值超过7。
56:Immediate mode illegal:不允许使用立即数寻址。 例如"MOV DS,CODE"其中CODE是段名, 不能把段名作为立即数传送给段寄存器DS。
57:Illegal size for operand:使用操作数大小( 字节数) 出错。 例如: 使用双字的存储器操作数。
58:Byte register illegal:要求用字寄存器的指令使用了字节寄存器。 如PUSH,POP指令的操作数寄存器必须是字寄存器。
59:Illegal uer of CS register:指令中错误使用了段寄存器CS。如:"MOV CS,AX"CS 不能做目的操作数。
60:Must be accumulator register:要求用AX或AL 的位置上使用可其他寄存器。 如IN,OUT 指令必须使用累加器AX或AL。
61:Improper uer of segment register:不允许使用段寄存器的位置上使用了段寄存器。 如"SHLDS,1"。
62:Missing or unreachable CS:试图跳转去执行一个CS达不到的标号。 通常是指缺少ASSUME语句中CS与代码段相关联。
63:Operand combination illegal:双操作数指令中两个操作数组合出错。
64:Near JMP/CALL to different CS:试图用NEAR属性的转移指令跳转到不在当前段的一个地址。
65:Label cannot have segment override:段前缀使用出错。
66:Must have instuction agter prefix:在重复前缀REP,REPE,REPNE后面必须有指令。
67:Cannot override ES for destination:串操作指令中目的操作数不能用其他段寄存器替代ES。
68:Cannot address with srgment register:指令中寻找一个操作数, 但ASSUME语句中未指明哪个段寄存器与该操作数所在段有关联。
69:Must be in segment block:指令语句没有在段内。
70:Cannot use EVEN or ALIGN with byte alignment:在段定义伪指令的定位类型中选用BYTE,这时不能使用EVEN或ALIGN伪指令。
71:Forward needs override or FAR:转移指令的目标没有在源程序中说明为FAR属性, 可用PTR指定。
72:Illegal value for DUP count:操作符DUP前的重复次数是非法的或未定义。
73:Symbol id already external:在模块内试图定义的符号, 它已在外部符号伪指令中说明。
74:DUP nesting too deep:操作数DUP的嵌套太深。
75:Illegak use of undefinde operand( ):不定操作符" " 使用不当。 例如"DB 10H DUP( 2)"。
76:Too many valer for struc or record initialization:在定义结构变量或记录变量时, 初始值太多。
77:Angle brackets requored around initialized list:定义结构体变量时, 初始值未用尖括号() 括起来。
78:Directive illegal structure:在结构体定义中的伪指令使用不当。 结构定义中的伪指令语句仅二种: 分号(;) 开始的注释语句和用DB,DW等数据定义伪指令语句。
79:Override with DUP illegal:在结构变量初始值表中使用DUP操作符出错。
80:Field cannot be overridden:在定义结构变量语句中试图对一个不允许修改的字段设置初值。
81:Override id of wrong type:在定义结构变量语句中设置初值时类型出错。
82:Circular chain of EQU aliases:用等值语句定义的符号名, 最后又返回指向它自己。 如:A EQU B,
B EQU A。
83:Cannot emulate cooprocessor opcode:仿真器不能支持的8087 协处理器操作码。
84:End of file,not END directive :程序文件无END文件。
85:Data emitted with no segment:语句数据没有在段内。