一 :定义符号的伪指令 1)SEGMENT 格式: 段名符号 SEGMENT 段类型 [再定位类型] SEGMENT指令可声明一个可再定位(区别于CSEG,DSEG,XSEG,BSEG,ISEG等 定义的在相对应的空间固定地址定义的{jd1}段—在连接的过程中不允许重新定位)的段符号和一个可选的再定位类型,段符号可以用来定义段,L51连接器可将多个模块内的具有相同段名和再定位类型的几个段合成为一个段.段类型说明了段所处的地址空间. 如果是编写的汇编程序要与C源程序接口,即被C源程序调用,则全部的汇编子程序所命名的定义的代码段的段名必须是可用SEGMENT来定义的,而且名字的命名的方法也应该参照C51编译器产生的局部段的段名的转换规则.段名的作用主要是在汇编的时候用RSEG来xx的,在连接定位的时候用到的.与段名相应的是用于存储和传递参数的别名,可以在汇编源程序中直接应用局部段的别名,这个别名主要是在传递函数参数的时候用的.在汇编程序中要用PUBLIC 声明被其他模块引用的全局符号. DATA (可直接寻址的内部RAM空间) IDATA (可间接寻址的内部RAM空间) XDATA (外部数据存储空间) BIT (内部RAM低地址区的可位寻址的空间) CODE (程序存储器空间) 可选的再定位类型定义了L51连接时的定位方式,再定位类型: UNIT:定义一个可开始于任一单元的段对于BIT型的段,一个单元是一个位, 其它所有的段一个单元是一个字节. PAGE:定义一个起始地址必须是256的整数倍的段,段的{jd1}地址由L51自己计算,该类型只允许用于XDATA和CODE类型段. INPAGE:定义一个由L51连接后必须包含在256B的块中,只适用于XDATA和CODE段. INBLOCK:定义一个L51连接后必须包含在2KB中的段,只适用于CODE段. OVERLAYABLE:定义一个可与其他段交叠的覆盖段,其段名符号必须按C51或者PL/M51的规则命名.C51把局部数据段和局部位段定义成?DT?FUNCTIONNAME?MODULENAME和?BI?FUNCTIONNAME?MODULENAME这是在small模式下.其他的模式略有不同。 BITADDRESSABLE:定义一个L51连接后位于可位寻址的区,段长不能超过16B. 2) EQU 格式: 符号名 EQU 表达式 符号名 EQU 寄存器名 EQU伪指令定义一表示数值或寄存器的符号,该符号可用于表达式或助记符指令的操作数,EQU指令定义的符号不能被改变或重新定义,其段类型取决于表达式中的操作数类型类型,无类型的EQU符号可用于任何表达式中. LIMIT EQU 200 VALUE EQU LIMIT-100+’A’ COUNTER EQU R5 3) SET 格式: 符号名 SET 表达式 符号名 SET 寄存器名 SET指令的功能与EQU指令的功能一样,区别是SET指令定义的符号可以再定义和改变. VALUE EQU 200 VALUE SET VALUE/2 COUNTER SET R1 TEMP SET COUNTER/2 4) BIT 格式: 符号名 BIT 表达式 BIT指令定义一表示位地址的符号,该符号一经定义便不能重新定义和改变. DATA_BSEG SEGMENT BIT RSEG DATA_BSEG CTRL DS 1 FLAG BIT CTRL.1 FLAG2 BIT FLAG+1 5) DATA 格式: 符号名 DATA 表达式 DATA指令定义一表示MCS-51内部数据存储器字节地址的符号,表达式必须是一个{jd1}地址值或者是一个简单的再定位表达式(即数值确定的,且其值必须在0—255之间,类型必须是DATA或者是NUMBER类型) 例如在汇编程序中: PORT DATA 90H RESULT_L DATA 40H RESULT_H DATA RESULT_L+1 6) XDATA,IDATA,CODE 均是也和DATA一样,都是定义一个代表相应存储空间单元的地址符号,表达式也必须是相对应的类型或者是NUMBER类型。 二 初始化和保留指令 1)DS 格式: [标号:] DS 表达式 DS指令以字节为单位,在内部或者外部地址空间中保留存储空间,表达式中不能包含前向地址参考量,可为除BIT段的任何类型。该伪指令语句使当前地址计数器加上表达式的值,需要注意的是地址计数器加上表达式结果的值不能超出地址空间的范围。(无论是汇编器还是编译器,对每一种不同类型的地址空间(DATA,CODE,PDATA,XDATA,BIT)都产生一个独立的地址计数器,每汇编一条指令,计数器都会自动增加,不过可以用ORG伪指令改变当前段地址计数器,用ORG伪指令表达式的值作为当前段地址计数器的初值,而当前段的改变可以用RSEG伪指令来改变。 RSEG ?DT?FUNCTION?MODULENAE----声明当前段为局部数据段 ?FUNCTION?BYTE:-------------函数局部段的别名 TIME: DS 5 2) DBIT 格式 [标号:] DBIT 表达式 以位为单位在可位寻址段内保留存储空间, 表达式中不能包含前向地址参考量或者是再定位的符号和外部符号,该指令使当前地址计数器增加表达式结果值,其增加量以位为单位. 3) DB DW 格式: [标号]: DB/DW 表达式1[,表达式2,………] 这两个指令的作用相同,均是以字节或者是字初始化程序存储空间,上面是保留存储空间,存储空间可以使RAM和ROM,而这两个指令直接就是初始化程序存储空间. Table: DB “any key to continue!” Requst: DB LOW(Table),HIGH(Table) 三:程序连接伪指令 1) PUBLIC 格式: PUBLIC 符号1 [,符号2,符号3….] PUBLIC 指令声明可被其他模块使用的全局符号,该符号必须在本模块内定义,但是寄存器和段名不能声明全局符号,全局符号在汇编模块中就是语句前的标号,一般在编写C调用用汇编语言实现的函数很有用. 例如: ?PR?FUNCTION_NAME?FILE_NAME ? SEGMENT CODE PUBLIC FUNCTION_NAME/_FUNCTIONAME RSEG ?PR?FUNCTION_NAME?FILE_NAME? FUNCTION_NAME/_FUNCTIONAME: 从寄存器或者存储区域中取回需要的参数 汇编代码 ; 把返回值放入需要规定的寄存器 RET/RETI --------返回 FUNCTION_NAME前有没有下滑线取决于函数有没有使用寄存器传递参数. 2) EXTRN 格式 EXTRN 段类型1 (符号表1) [,段类型2 (符号表2) , …] 指令声明本模块引用的外部全局符号,该指令可出现在出现在源程序的任何地方,每个外部符号都必须是CODE,DATA,IDATA,XDATA,BIT或者NUMBER等段类型之一,段的类型限制了符号使用的范围,例如CODE只能做JMP和CALL等转移和调用类指令的目标地址,而不能做MOV等指令的操作数,L51在连接的时候检查外部符号是否和相应的全局符号相匹配,无类型的符号可以任何段类型的同名符号相匹配. 3) NAME 格式 NAME 目标模块名 --- module_name 目标模块名 NAME指令定义当前程序模块的目标模块名,目标模块名不同于目标文件名,也不同于源程序名,当未给出目标模块名的时候,则以不带扩展名的源文件名命名,且每个目标模块只允许一个名字. 四:状态和段选择指令 1) END 该指令必须位于源程序的{zh1}一行,且只能在程序中出现一次,在END的语句不汇编. 2) ORG 格式 ORG 表达式 ORG伪指令改变当前汇编器当前段地址计数器,用表达式的值作为当前段地址计数器的值,表达式中不能有前向参考量,并且只能是一个{jd1}地址或简单再定位表达式. 3) RSEG 格式 RSEG 段名 RSEG指令选择一个已定义的再定位的段作为当前有效段,具体什么段,由在定义段名的时候段的类型决定, 可在当前段保留存储空间,初始化程序空间,安排程序代码. 例如: DATA_SEG SEGMENT DATA CODE_SEG SEGMENT CODE RSEG DATA_SEG DS 2 COUNT: DS 3 RSEG CODE_SEG STRING: DB “Press any key to continue”,0 START: MOV A,#80H <汇编代码> END 4) CSEG,DSEG,ISEG,XSEG,BSEG 格式: CSEG [AT {jd1}地址值] DSEG [AT {jd1}地址值] ISEG [AT {jd1}地址值] XSEG [AT {jd1}地址值] BSEG [AT {jd1}地址值] 以上的几条指令分别和CODE,DATA,IDATA,XDATA,BIT段相对应,当指令中包含一个基地址(AT{jd1}地址值时),汇编器结束当前段并产生一个起始于{jd1}地址的新段,如果指令中不包含一个基地址选项,则当汇编器已经有当前段的时候,则不改变当前段,即忽略该指令, 例如: BSEG AT 70H DECMODE: DS 2 CSEG AT 0H LJMP MAIN LJMP INT_0 需要注意的是:这里的AT和变量的{jd1}定位_at_不一样,那是C51编译器的关键字的扩展,在C元文件中可以用的,而这个指令是在A51中的. 5) USING 格式 :USING 表达式 USING指令使A51选择适当的寄存器组计算寄存器的{jd1}地址,该指令类似于C51中的REGISTERBANK编译控制指令的功能,USING不进行寄存器组的切换,表达式的值必须是0—3之间,由表达式的值A51可以计算出寄存器符号AR0—AR7的{jd1}地址,当程序中需要使用Arn的时候,有必要先使用Using. 例如: USING POP AR2 PUSH AR3 |