单一数据传送xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
典型的汇编语法:
LDR Rd, [Rn, Rm, ASL#1]!
STR Rd, [Rn],#2
LDRT Rd, [Rn]
LDRB Rd, [Rn]
这些指令装载/存储内存的一个字从/到一个寄存器。在指定地址时使用的第一个寄存器在术语上叫做基址寄存器。
如果设置了 L 位,则进行装载,否则进行存储。
如果设置了 P 位,则使用预先变址寻址,否则使用过后变址寻址。
如果设置了 U 位,则给出的偏移量被加到基址寄存器上 - 否则从中减去偏移量。
如果设置了 B 位,传送内存的一个字节,否则传送一个字。这在汇编器中表示为给根助记符的加上后缀‘B’。
W 位的解释依赖于使用的地址模式:
对于预先变址寻址,设置 W 位强制把用做地址转换的最终地址写回基址寄存器中。(例如,传送的副作用是 Rn := Rn +/- offset。这在汇编器中表示为给指令加上后缀 ‘!’。) 对于过后变址寻址,地址总是写回,设置 W 位指示在进行传送之前强制地址转换。这在汇编器中表示为给指令加上后缀‘T’。 地址转换导致芯片告知内存系统这是一个用户模式传送,而不管此时芯片是处于用户模式中还是处于特权模式中。这是有用的,例如在写模拟器的时候: 假如一个用户模式程序一个内存区域执行了一个 STF 指令,而用户模式代码不可以写这个内存区域。如果由一个 FPA 来指令它,它将异常终止。如果由一个 FPE 来执行它,它也应该异常终止。但是 FPE 运行在一个特权模式下,所以如果它使用普通存储指令,则它不会异常终止。为了使异常终止正确工作,在一个特权模式调用它时使用 STRT 替代普通存储指令,使其如同调用自用户模式。
如果使用这个指令的立即数形式,o 字段给出一个 12-bit 偏移量。如果使用了寄存器形式,则按对数据处理指令那样解码它,限制是不允许使用寄存器指令移位量。
如果 R15 被用做 Rd,不修改 PSR。PC 不应该被用在 Op2 中。
其他限制:
在基址寄存器是 PC 的时候不要使用写回或过后变址。 不要使用 PC 作为给 LDRB 或 STRB 的 Rd。 在使用带有寄存器偏移量的过后变址时,不要让 Rn 和 Rm 是同一个寄存器(这样做导致不可能从异常终止中恢复)。 装载使用 1S + 1N + 1I + (1S + 1N 如果改变了 PC)个周期,而存储使用 2N 个周期。
块数据传送xxxx100P USWLnnnn llllllll llllllll
典型的汇编语法:
LDMFD Rn!, {R0-R4, R8, R12}
STMEQIA Rn, {R0-R3}
STMIB Rn, {R0-R3}^
使用这些指令来同时装载/存储多个寄存器从/到内存。使用的内存地址从在基址寄存器 Rn 中持有的值指定的内存地址要么增加要么减少地址,(可以存储基址寄存器自身),并且最终的地址可以被写回到基址寄存器中。这些指令适合于实现栈,在进入/退出一个子例程时存储/恢复寄存器的内容。
U 位指示对每个寄存器地址将被 +4 (设置)所修改,还是被 -4 (清除)所修改。
W 位总是指示写回。
如果设置了 L 位,则指示进行一个装载操作,如果清除了,则指示存储。
使用 P 位指示在每次装载/存储之前还是之后增加/减少基址寄存器(参见下面表格)。
如果这个操作要装载/存储 Rl 则设置位 l。
汇编器典型的用条件代码跟随助记符根,并随后用两个字母代码指示 U 和 W 位的设置。
根 意思 P U
DA 在每次存储/装载之后减少 Rn 0 0
DB 在每次存储/装载之前减少 Rn 1 0
IA 在每次存储/装载之后增加 Rn 0 1
IB 在每次存储/装载之前增加 Rn 1 1
在实现栈的时候有更清楚的同义词:
根 意思
EA 空升序栈
ED 空降序栈
FA 满升序栈
FD 满降序栈
在一个空栈中,栈指针指向下一个空位置。在一个满栈中栈指针指向最顶端满位置。升序栈向高位置增长,而降序栈向低位置增长。
存储的寄存器总是最低编号的寄存器在内存中在最低地址。这可以影响入栈和出栈代码。例如,如果我想把 R1-R4 压入栈中,接着每次把它们中的两个装载回来,要使它们回到原先的寄存器,对于降序栈我需要做类似下面的事:
STMFD R13!,{R1,R2,R3,R4} ;放置 R1 在内存低端,就是说在栈顶
LDMFD R13!,{R1,R2}
LDMFD R13!,{R3,R4}
对于升序栈则是: STMFA R13!,{R1,R2,R3,R4} ; 放置 R4 在内存高端,就是说在栈顶
LDMFA R13!,{R3,R4}
LDMFA R13!,{R1,R2}
同义的代码如下:
代码 装载 存储
EA DB IA
ED IB DA
FA DA IB
FD IA DB
S 为控制两个特殊的功能,它们被汇编器指示为在指令的结束处放置“^”: 如果设置了 S 位,并且指令是 LDM 而 R15 在寄存器列表中,则: 在 26-bit 特权模式下,装载 R15 的所有 32 位。 在 26-bit 用户模式下,装载 R15 的 4 个标志位和 24 个 PC 位。忽略装载值的位 27、26、1 和 0。 在 32-bit 模式下,装载 R15 的所有 32 位,但要注意底端的两位总是零,所以忽略装载到它们的任何东西。除此之外,把当前模式的 SPSR 传送到 CPSR;因为用户模式没有 SPSR,这种类型的指令不应该用在 32-bit 用户模式下。 如果设置了 S 位,并且要么指令是 STM 要么 R15 不在寄存器列表中,则传送用户模式的寄存器而不是当前模式的寄存器。在用户模式下不应该使用这个指令。 特殊情况发生在基址寄存器存在于要传送的寄存器列表中的时候。
基址寄存器总是可以被装载而没有任何问题。但是,如果基址寄存器被装载则不能指定写回 - 你不能同时把写回值和装载值二者写到基址寄存器中! 如果不使用写回则可以存储基址寄存器而没有任何问题。 如果在存储包含基址寄存器的一个寄存器列表的时候使用了写回,则只有在基址寄存器是列表的第一个的情况下,才在写回之前写基址寄存器的值到内存。其他情况,写到内存中的值未被定义。 进一步的特殊情况发生在程序计数器存在于要装载和保存的寄存器列表中。
(在 26 位模式下) PSR 总是与 PC 一起保存((在所有模式下) PC 总是超出当前执行的指令的地址 12 字节,而不是通常的 8 字节)。 在装载时,只有在设置了 S 位的时候,才影响 PSR 的在当前模式下可改变的位。 PC 不应该作为基址寄存器。
块装载使用 nS + 1N + 1I + (1S + 1N 如果改变了 PC )个周期,而块存储使用 (n-1)S + 2N 个周期,这里的“n”是被传送的字的数目。 |