4.对象文件结构
目标文件由记录序列定义。 以下语法显示了什么序列的记录是有效的,并且以下语义提供了由序列传递的重要信息,而不仅仅是记录的内容。 有效的记录字符串的定义由以下语法给出:
(注意:<ITEM> *表示<ITEM>可能出现零次或多次。)
<object file> ::= <module>* | <library>
<module> ::= MODULE_HEADER_RECORD
<definition record>*
<data/debug record>*
MODULE_END_RECORD
<definition record>::=SEGMENT_DEFINITIONS_RECORD
|PUBLIC_DEFINITIONS_RECORD
|EXTERNAL_DEFINITIONS_RECORD
<data/debug record>::=<data section> | <debug record>
<debug record> ::=SCOPE_DEFINITION_RECORD
| DEBUG_ITEMS_RECORD
<data section> ::=CONTENT_RECORD FIXUP_RECORD*
<library> ::=LIB_HEADER_RECORD
<module>*
LIB_MODULE_NAMES_RECORD
LIB_MODULE_LOCATIONS_RECORD
LIB_DICTIONARY_RECORD
目标文件可以是一系列模块或库。 模块由一对封装模块主体的模块头和模块结束记录组成。 模块的主体由定义部分和一系列调试记录和数据部分组成。
定义部分包含一组记录,指定模块中的段,驻留在模块中的公共符号以及其中使用的外部名称。
调试记录包含关于段符号,公共符号,模块本地符号和更高级别语句(“行号”)的位置的调试项记录。 它们可能被封装在一对范围定义记录中。
数据部分由内容记录组成,内容记录是一段代码的映像和一组Fixup记录,由RL51程序用于重新定位该部分并解析其中包含的外部引用。
库文件由一个库头文件组成,后跟一组模块,并由三个记录终止。 这些最后的记录列出了模块的名称,它们在文件中的位置以及每个模块中定义的公共符号的列表。
5记录格式
5.1记录
对象文件是一组类型化的记录,在本章的其余部分中有详细描述。 为了可视化给定的记录格式,使用以下典型方案:
每种格式都用两种尺寸的框绘制。整个概述的窄框代表单个字节。宽框,全部概述,代表两个字节。
宽框,但是在顶部和底部都有双行,表示可变数量的字节,一个或多个取决于内容。
指示NAME的任何字段具有以下内部结构:第一个字节包含介于0和40之间的数字,包括该数字,表示字段中剩余字节数。其余字节被解释为字节串;每个字节必须表示ASCII字符集的以下子集的成员:{大写字母(A..Z),十进制数字(0..9),特殊字符“_”,“?”和“@”}。
记录的某些部分可以重复0次以上。这些在盒子下方显示“重复”或“吸收”。
阴影字段是不携带信息的字段。它们存在以实现未来增强(例如SYMBOL TYPE字段)或出于兼容性原因并应具有零值。
每个记录以表示记录类型的记录类型开始,记录长度包含除前两个字段之外的记录中的字节数。该记录以校验和字节结束,该字节包含记录中所有其他字节的和(模256)的2的补码。因此,记录中所有字节的和(模256)为零。
一些字节字段包含位子字段。 为了描述它们,使用以下方案:
在上面的例子中,字节包含两个字段:FIELD_1从位3到位7,FIELD_0从位0到位2。
在以下部分中,绝对地址是一个16位整数,表示从相应地址空间开始的偏移量,以BIT类型的位为单位,否则以字节为单位。 OFFSET字段是一个16位整数,表示从相应段的开始的偏移量,以BIT类型的位为单位,否则以字节为单位。
在以下记录描述中,每当一个字段只能假设一组离散值(例如模块头文件记录中的TRN ID)时,这些未使用的值将被保留以供将来扩展。 特别地,未使用的记录类型被保留以备将来使用。
5.2模块头记录
每个模块必须以模块头记录开始。 它用于识别RL51和其他未来的8051对象文件的处理器的模块。 除了模块名称,记录包含:
“TRN ID”
该字节标识已生成此模块的程序:0FDH-ASM51,0FEH-PL / M-51,0FFH-RL51。
5.3模块结束记录
记录结束模块序列,并包含以下信息:特征
“MODULE NAME”
这里给出了模块的名称以进行一致性检查。 它必须匹配模块标题记录中给出的名称。
“REGISTER MASK (REG MSK)”
该字段包含四个寄存器组中的每一个的一位。 每个位,当设置指定模块使用相应的库时:
Bit 0 (the least significant bit) - bank #0.
Bit 1 - bank #1.
Bit 2 - bank #2.
Bit 3 - bank #3.
5.4定义记录
定义部分包含模块中使用的段,公共和外部的名称和其他属性。 定义部分由三种类型的记录组成:分段定义记录,公共定义记录和外部定义记录。
5.4.1段定义记录
该记录定义了在模块中使用的段。 该记录包含段定义的重复。 不允许转发对段定义的引用。 每个细分定义的结构如下:
“SEG ID”
该字段可以具有以下值:
0 - 识别绝对段。 在对象模块内的绝对引用不涉及绝对段定义。 绝对细分无法组合并具有零(零长度)名称。
1到255 - 标识可重定位段; (SEG ID-1)必须等于它们在模块中出现的段定义列表中其定义的顺序号(忽略绝对段定义!)。
因此,OMF允许在模块内定义多达255个可重新定位的段和任意数量的绝对段。
“SEG INFO (segment information)”
该模块的结构如下:
“Ë”
该位指定(设置时)段为零大小(空)。
“OVL”
该位指定(设置时)段可重叠(即,RL51可以由其他可兼容的可重叠段覆盖该段)。
“SEG REG”
该字段指定可以使用可叠加段的寄存器组。该字段仅对可重叠的段有意义。
位3和4具有以下含义:
00 - register bank # 0.
01 - register bank # 1.
10 - register bank # 2.
11 - register bank # 3.
非可覆盖段的非零SEG REG的组合保留供将来使用。
“SEG TYPE”
该字段指定段的类型:
0 - 代码
1 - XDATA。
2 - 数据。
3 - IDATA。
4位。
REL TYP(重定位类型)
段的重定位类型字段可以指定绝对段和四种类型的可重定位段:
0 - ABS。指定绝对段(不可重定位)。
1 - 单位。该段可以在单位边界上重新定位(BIT类型段的位边界和所有其他段的字节边界)。因此对其搬迁没有任何限制。
2 - 位寻址。该段必须位于内部数据空间的位寻址部分内。仅允许DATA类型段。
3 - 页内。该段将位于256字节的页面中。
4 - INBLOCK。该段将位于2048字节块内。
5 - PAGE。此段的基址将位于256字节页边界。
INPAGE和PAGE类型仅对CODE和XDATA段类型有效。 INBLOCK仅对CODE段类型有效。
“SEGMENT BASE”
该字段给出段的绝对地址。它仅用于绝对段。对于可重定位段,此字段包含零。
“SEGMENT SIZE”
在此模块中定义的段的部分占用的字节数(或BIT类型段的位数)。值为零表示大小为10000H(64K)字节。如果段为空(E设置),则忽略此字段。
“SEGMENT NAME”
段的名称。由于绝对段没有名称,它们的字段指定一个空名(零长度)。
该记录定义模块中使用的公共符号。
该模块的结构如下
“SEG ID”
0 - 标识绝对(不可重定位)符号。
1到255 - 标识可重定位符号。 指定的值标识包含公共符号的段定义(见5.4.1)。
“SYM INFO (symbol information)”:
该模块的结构如下:
“IND (indirectly_callable)”
该位指定(设置时)该过程是indirecly_callable。此字段仅对公共程序符号有意义。
“VAR”
该位指定(设置时)公共符号是变量(即不是过程)。
“RBF (register bank flag)”
该位指定(设置时)该符号寄存器(SYM REG)字段有效,即当该位未设置时,该过程可能会使用所有寄存器组。此字段仅对公共程序符号有意义。
“SYM REG”
该字段指定在该过程中使用的寄存器组。该字段只对程序符号有意义。
位4和5具有以下含义:
00 - register bank # 0.
01 - register bank # 1.
10 - register bank # 2.
11 - register bank # 3.
非过程符号的非零SYM REG的组合保留供将来使用。
“USAGE TYPE (USG TYP)”
该字段指定符号的用法:
0 - 代码地址。
1 - XDATA地址。
2 - 数据地址。
3 - IDATA地址。
4 - BIT地址。
5 - NUMBER。一个无类型的数字。可以匹配任何外部符号并在任何上下文中使用。
“OFFSET”
对于绝对符号,该字段给出其地址空间内符号的绝对地址。对于可重定位符号,该字段给出了由SEG ID标识的段的符号的偏移量。对于NUMBER符号,它给出其值。
“PUBLIC NAME”
该字段给出公共符号的名称。每个重定位和联动过程中的名称应该是唯一的。
5.4.2外部定义记录
该记录提供外部名称及其假定段类型的列表。外部名称记录根据其内部顺序和外观顺序,形成外部符号的顺序列表。对外部符号(EXT ID字段)的进一步引用被实现为该列表中其条目的索引。
OMF每个模块最多允许256个外部符号。
“ID BLK and EXT ID”
该对指定外部符号列表中外部符号定义条目的索引(见上文)。 ID BLK标识EXT ID所属的256个外部符号的块。目前它必须包含2. EXT ID字段给出该块中条目定义的索引。 EXT ID必须等于模块中定义的序号(0,1,...)。
“SYM INFO (symbol information)”
该字段等同于公共定义SYM INFO(见5.4.2),除了IND位始终为0.请注意,此字段提供符号声明给翻译器的符号信息。
5.5调试记录
如果用户从翻译器或RL51请求了调试选项,则这是一组出现在目标文件中的记录。
5.5.1范围定义记录
此记录用于将调试项记录中找到的符号和行号的范围限制在源程序中定义的块中。
“BLK TYP”
此字段可以采用以下值:
模块块。为每个模块生成一次。此类型的范围定义记录应该是模块中的第一个调试记录,因为它包含了模块中的整个调试信息(及其各自的模块结束类型范围定义记录)。
DO阻塞。为每个简单的DO语句生成,其中包含其块中的声明。
2.程序块。为包含过程块中声明的每个PROCEDURE语句生成。
3.模块结束。为关闭模块的每个END语句生成。此记录中的BLOCK NAME必须与最后一个模块范围定义的名称相匹配。
DO结束。为关闭DO块的每个END语句生成。此记录中的BLOCK NAME必须与上次打开的DO范围定义的名称相匹配。
程序结束生成的每个END语句关闭PROCEDURE块。此记录中的BLOCK NAME必须与上次打开的PROCEDURE范围定义的名称相匹配。
“BLOCK NAME”
块的名称(标签)。
5.5.2调试项记录
该记录提供有关模块/ DO块/过程本地的段符号,公共符号,行号和符号的信息(见5.5.1)。 它由ICE和其他调试工具使用。
“DEF TYP”
该字段指定在此记录中定义的项目:
0 - 本地符号。
1 - 公共符号。 这种物品不应出现在DO块或PROCEDURES块内。
2 - 段符号。
3 - 行号(在当前模块中)。
“INFO”
该字段的结构取决于DEF TYP。 用于本地或公共符号的INFO字段给出了符号的位置和名称:
对于段符号,INFO字段给出了符号的位置和名称。
“SEG ID”
见5.4.1。
“SYM INFO (symbol information)”
见5.4.2。
“SEG INFO (segment information)”
见5.4.1。
“OFFSET”
见5.4.2。 对于段符号,此字段仅在R&L过程之后才有意义。 然后给出段的绝对基址。
“SYMBOL NAME”
符号的名称。
行号的INFO字段将物理位置与源代码中的行号(语句号)相关联:
“SEG ID”
见5.4.2。 必须标识CODE类型段。
“OFFSET”
给出从语句编译的第一个代码字节的位置(见5.4.2)。
“LINE NUMBER”
二进制表示中的行号。
5.6数据部分
5.6.1内容记录
程序的实际存储器映像在OMF中以称为数据段的记录组给出。数据部分由内容记录组成,后面是一系列操作的修复记录
该记录提供一个或多个连续数据字节,可以从其构建存储器映像的一部分。
“SEG ID”
此字段标识包含数据的段(见5.4.1)。 此段的类型必须为CODE。
“OFFSET”
相对于模块中定义的段的部分的开始,给出记录中数据的第一个字节的位置(如果是绝对段,则为零)。
“DAT”
数据字节序列。 如果n是记录中的数据字节数,而不是OFFSET + n,则应小于或等于段定义记录中定义的段的大小(除非该段是绝对的)。
零个或多个数据字节表示可重定位或外部符号的引用。 这些字节应由RL51程序使用以下Fixup记录中提供的信息来解决。
5.6.2修正记录
Fixup记录指定一组应该应用于 previous Content Record (本文中称为PCR)中的引用的fixup。 定义由参考的位置,其类型和操作数指定为被称为ADDR(通常是目标的地址)的16位值(模64K无溢出检查)。 然后应使用参考类型,以确定如何将该值转换为PCR中的最终形式。
“REFERENCE LOCATION”
该字段给出了相对于PCR的数据部分的开头的引用的第一个字节的位置。 此字段指定的完整引用(一个或两个字节)必须在该数据部分内。 参考的位置在下面被称为REFLOC。
“REF TYP”
此字段指定应修复的引用的类型。该字段可以采用以下值:
0 - LOW。 ADDR的低位字节存储在REFLOC中。
1 - BYTE。 ADDR的低位字节存储在REFLOC中。 ADDR的高字节必须为零。
2 - RELATIVE。应从ADDR中减去REFLOC的绝对CODE地址。结果应该是+127到-128之间的2的补码。结果的低位字节存储在REFLOC。
3 - HIGH。高位字节ADDR存储在REFLOC中。
4 - WORD。 ADDR的高阶存储在REFLOC中。低阶部分存储在REFLOC + 1。
5 - INBLOCK。 ADDR(HI_BITS)的高位字节的3个低位被存储在REFLOC的3个高位中。低位字节(LO_BITS)存储在REFLOC + 1。 ADDR(BLOCK_NUMBER)高位字节中的5个高位必须与对应于REFLOC + 2的绝对地址中的相应位相同。这个稍微复杂的任务如下图所示:
6 - BIT。 ADDR应在0到127(位空间的内部RAM部分)的范围内。 ADDR的低位字节存储在REFLOC中。
7 - CONV。 此类型指定位地址可位字节中的位的地址。 在计算ADDR(特殊ADDR计算如下所述)之后,如上述BIT情况那样被处理。
该模块的结构如下:
OPERAND三元组(ID BLK,ID,OFFSET)指定参考计算的操作数,被评估为称为ADDR的16位值。它由逻辑上由两个组件组成:BASE,由两个字段ID BLK和ID定义,和OFFSET。
BASE定义如下:
ID BLK = 0:段操作数。
BASE设置为由ID标识的段的绝对基地址(即,ID在此被解释为SEG ID)。
ID BLK = 1:可重定位操作数。
BASE设置为PSEG的绝对基址。 I.E.,当前模块中定义的段的那部分。该段再次由ID标识。
ID BLK = 2:外部操作数。
BASE设置为由外部符号指定的公共符号的绝对基址。外部符号由ID标识。 (即ID被解释为EXT ID)。
ID BLK = 3到255:保留供将来扩展。
从BASE和OFFSET计算ADDR的方式如下:
IF REF_TYPE = CONV THEN
ADDR =(BASE - 20H)* 8 + OFFSET;
其他
ADDR = BASE + OFFSET;
5.7库记录
8051对象库文件的结构与OMF80 / 85的文件相同,即一个库标题记录,后跟一个模块序列,并由库尾终止。 库记录的记录格式也与相应的OMF80 / 85记录相同。
5.7.1库头记录
该记录是库文件中的第一个记录。 它立即在库中的模块(如果有的话)之前。 按照模块(如果有的话)还有3个以上的记录:库模块名称记录,库模块位置记录和库字典记录。
“MODULE COUNT”
该字段指示库中有多少个模块。 它可能具有0到65535之间的任何值。
“BLOCK NUMBER, BYTE NUMBER”
这些字段表示库文件中库模块名称记录的第一个字节的相对位置。
5.7.2库模块名称记录
该记录给出了库中所有模块的名称。 名称的顺序对应于库中模块的顺序。 只有一个库模块名称记录可能会出现在库中。
“MODULE NAME”
记录中的第i个MODULE NAME字段包含库中第i个模块的名称。
5.7.3库模块位置记录
该记录提供了库文件中每个模块(的模块标题记录)的第一个字节的相对位置。 只有这样的一个记录可能会出现在图书馆。
块号/字节数对的顺序对应于库内模块的顺序。
“BLOCK NUMBER, BYTE NUMBER”
第一对字段在库文件中提供库中第i个模块的第一个记录的第一个字节的相对位置。
5.7.4库词典记录
该记录给出了库中模块中公共符号的所有名称。 只有这样的一个记录可能会出现在图书馆。
由于名称必须具有非零长度,因此格式中的“00”字节可与“公共名称”字段区分开。 因此,'00'字节将公共名称分成组; 第i组中的所有名称都在图书馆的第i个模块中定义。
“PUBLIC NAME”
这是模块中公共符号的名称。 此记录中不会出现多个公共符号。