我进入华为公司后,做开源生态的工作。在工作时需要用到plan9汇编指令,现在我把一些plan9的一些东西放在这里,希望对大家有所帮助。
1)汇编程序中所有预定义好的符号都是大写的。数据寄存器从R0到R7;地址寄存器从A0到A7;浮点寄存器从F0到F7。
2)其中,A6中的一个指针被C编译器用来指向数据,这样可以更加频繁的使用短地址;A6的值是常量,必须在C程序初始化外部定义的符号a6base的地址时设置。
3)在汇编器中定义了以下硬件寄存器:CAAR, CACR, CCR, DFC, ISP, MSP, SFC, SR, USP, VBR;
4)汇编器还定义了一些操纵堆栈的伪寄存器: FP, SP和 TOS。
FP 是栈帧指针,因此 0(FP) 是第一个参数, 4(FP) 是第二个参数,依此类推。
SP 是本地堆栈指针,其中保存了自动变量; 0(SP) 是第一个自动的,依此类推。
TOS 是堆栈顶部的寄存器,用于将参数推送到过程,保存临时值等。
5)汇编器和加载器跟踪这些伪寄存器 。名称 A7 指的是硬件堆栈指针,但要小心混合使用 A7 和上述与堆栈相关的伪寄存器,这会造成麻烦。还要注意, 加载程序会观察PEA指令来更改SP,因此会在所有返回之前插入相应的弹出窗口。汇编器接受要附加到FP 和 SP 用途的类似标签的名称 ,例如 p + 0(FP),以帮助记录 p 是例程的第一个参数。该名称位于符号表中,但对程序结果没有任何意义。
1)所有外部引用必须相对于某些伪寄存器( PC (虚拟程序计数器)或 SB (“静态基数”寄存器))进行。 PC 计算指令,而不是数据字节。例如,要跳转到第二条指令,即跳过一条指令,可以写一条
BRA 2(PC)
标签允许,如
BRA return
NOP
return:
RTS
2)使用标签时,没有 (PC) 注释。伪寄存器 SB 是指程序的地址空间的开头。因此,对全局数据和过程的引用被写为SB的偏移量 ,如
MOVL $array(SB), TOS
将全局数组的地址压入堆栈,推送数组的第二个(4字节)元素。注意偏移量的使用;
MOVL array+4(SB), TOS
寻址模式的完整列表如下。同样,子例程调用必须使用 SB:
BSR exit(SB)
静态变量具有语法
local<>+4(SB)
在<> 将在加载时由一个唯一的整数填充。
3)程序启动时必须执行
MOVL $a6base(SB), A6
所有汇编程序都共享简单的寻址模式。出于完整性考虑,此处列出所有68020寻址模式的表格,因为该机器设置最丰富。在该表中, 如果可以忽略零,o 是一个偏移量; d 是位移,它是介于-128和127之间的常数。列出的许多模式具有相同的名称。仔细检查格式将显示正在应用的默认值。
1)将数据放入指令流中很容易:伪指令 LONG 和 WORD (但不是 BYTE)放置适当大小的单个参数的值,例如:
LONG $12345 // 将12345(10进制)放置在指令流中
在数据部分中放置信息会更加痛苦。伪指令 DATA 提供了两个参数来完成这项工作:放置项目的地址(包括其大小)和放置在那里的值。例如,要定义一个 包含字符 abc 和终止null 的字符数组 数组:
DATA array+0(SB)/1, $’a’
DATA array+1(SB)/1, $’b’
DATA array+2(SB)/1, $’c’
GLOBL array(SB), $4
或者:
DATA array+0(SB)/4, $"abc\z"
GLOBL array(SB), $4
注意:
1)“/1” 表示字节数, GLOBL 表示全球标志和 $ 4 表示符号多少字节占据。未初始化的数据将自动归零。
2)字符 “\z”等效于C中的 \ 0。DATA 语句中 的字符串 最多可包含八个字节。分段构建更大的字符串。DYNT 和 INIT这两个伪指令允许(已经过时的)Alef编译器在加载阶段构建动态类型信息。该 DYNT 伪指令有两种形式:
DYNT , ALEF_SI_5+0(SB)
DYNT ALEF_AS+0(SB), ALEF_SI_5+0(SB)
在第一种形式中, DYNT 将符号定义为一个小的唯一整数常量,由加载程序选择,该常量是字长的倍数。在第二种形式中, DYNT 以相同的方式定义第二个符号,将第一个符号指定的数组中最近定义的文本符号的地址放置在第二个符号的值定义的索引处,然后调整大小相应的数组。
该 INIT 伪指令采用相同的参数作为 数据 的语句。它的符号用作数组的基础,数据项以最新DYNT 伪指令指定的偏移量安装在数组中 。数组的大小会相应调整。
1)入口点由伪操作TEXT定义,伪操作TEXT以函数的名称(包括普遍存在的(SB))和要在堆栈上预分配的自动存储的字节数作为参数。当操作时 ,该字节数通常为零,编写汇编语言程序。这是一个返回其两个参数之和的完整过程:
TEXT sum(SB), $0
MOVL arg1+0(FP), R0
ADDL arg2+4(FP), R0
RTS
2)TEXT 伪操作的可选操作是中间参数, 是加载程序选项的位字段。当为程序的其余部分启用了性能分析时,将1位置1会暂停性能分析。例如,
TEXT sum(SB), 1, $0
MOVL arg1+0(FP), R0
ADDL arg2+4(FP), R0
RTS
1)汇编程序可通过 R14 和 PC来访问 R0。堆栈指针为 R13,链接寄存器为 R14,静态基址寄存器为 R12。 R0 是返回寄存器,也是保存子例程第一个参数的寄存器。plan9的C中的外部寄存器从R10 向下分配 。 加载程序将R11用作临时寄存器。汇编器支持 CPSR 和 SPSR 寄存器。它还知道协处理器寄存器 C0 至 C15。浮动寄存器为 F0 通过 F7, FPSR 和 FPCR。
2)与其他架构一样,加载和存储称为 MOV,例如 MOVW 用于加载字或存储字,而 MOVM 用于加载或存储多个字,具体取决于操作数。
3)指令的后缀支持寻址模式: .IA (之后递增) 、. IB (之前递增) 、. DA (之后递减)和 .DB (之前递减)。这些只能与MOV 指令一起使用 。多重移动指令 MOVM使用括号定义寄存器范围,例如 [R0-R12]。特殊 MOVM 寻址模式位 W,U,和 P 以相同的方式写入,例如, MOVM.DB.W. A .S 。suffix后缀允许 MOVM 指令到访问用户在另一个处理器模式下,R13 和 R14。二进制运算符<< (逻辑左移), >> (逻辑右移), -> (算术右移)和@> (右旋转)支持寻址模式下的 移位和 旋转。例如 R7 >> R2或 R2 @> 2。汇编器不支持通过移位表达式进行索引;只有名称可以被双重索引。
4)任何指令之后可以是一个后缀,使指令有条件的: .EQ, .NE,等等,如在ARM手册,利用同义词 杂项文件 (对于 .CS)和 .LO (对于 .CC),例如 添加。 在ARM允许下,算术和逻辑指令可以带有 .S后缀来设置条件代码。
5)MCR 和 MRC 协处理器指令的语法在 很大程度上与手册中的内容相同,并进行了常规调整。汇编程序仅直接支持编译器使用的ARM浮点协处理器操作: CMP, ADD, SUB, MUL和 DIV,所有 后缀均带有 F 或 D后缀,用于选择单精度或双精度。浮点加载或存储成为 MOVF 和 MOVD。转换指令还通过移动指定: MOVWD, MOVWF, MOVDW, MOVWD, MOVFD和 MOVDF。