程序状态寄存器 |
Bit 31 30 29 28 27 26 25------------2 1 0 N Z C V I F 程 序 计 数 器 S1 S0标志的意义:
N Negative 如果结果是负数则置位 Z Zero 如果结果是零则置位 C Carry 如果发生进位则置位 O Overflow 如果发生溢出则置位 I IRQ 中断禁用 F FIQ 快速中断禁用 S1 和 S0 是处理器模式标志: S1 S0 模式 0 0 USR - 用户模式 0 1 FIQ - 快速中断模式 1 0 IRQ - 中断模式 1 1 SVC - 超级用户模式
在 R15
作为一个指令的第一个操作数的时候,只有程序计数器部分是可以获得的。所以,下列指令把
PC 复制到一个寄存器中并向这个目标寄存器加上 256:
ADD R0, R15, #256
(对于 BASIC 汇编器 R15 和 PC 的意思是相同的)
在 R15 作为第二个操作数的时候,所有 32 位都是可以获得的: 程序计数器、标志、和状态。下列代码段将标识当前的处理器模式:
MOV R0, #3 ; 装载一个位掩码(%11)到 R0 中 AND R0, R0, PC ; 把 R15 与 R0 做逻辑与并把结果放入 R0,来得到模式状态 CMP R0, #3 ; 把模式与 '3' 相比较(SVC) BEQ svc ; 如果等于 SVC 模式,分支到 'svc' CMP R0, #2 ; 把模式与 '2' 相比较 (IRQ) BEQ irq ; 如果等于 IRQ 模式,分支到 'irq' CMP R0, #1 ; 把模式与 '1' 相比较(FIQ) BEQ fiq ; 如果等于 FIQ 模式,分支到 'fiq' CMP R0, #0 ; 把模式与 '0' 相比较(USR) BEQ usr ; 如果等于 USR 模式,分支到 'usr'这个例子不遵从 32-bit 体系。如何在 32-bit 环境中读当前的模式请参照下面的章节。
新状态 = 旧状态 EOR (1 << 28)
可以成为改变 oVerflow
标志的伪码。但是我们不能做这个简单的 EORS
操作,原因是这将导致随后的两个指令被跳过。不要担心,指令
TEQ
做一个假装的 EOR (结果不存储到任何地方)。把它与
P
后缀组合,则把结果的第 0、1、和 26 至 31
位直接写到 R15 的第 0、1、和 26 至 31
位,这是改变标志的一个简便的方法: TEQP R15,
bit_mask
如果你处在允许你设置一个标志的一个模式中,则你只可以改变这个标志。
这个例子不遵从 32-bit 体系。如何在 32-bit 环境中改变模式请参照下面的章节。
可以被扩充它来改变处理器模式。例如,要进入 SVC 模式你可以:
MOV R6, PC ; 把 PC 的最初状态存储到 R6 中 ORR R7, R6, #3 ; 设置 SVC 模式 TEQP R7, #0 ; 把(在 R7 中的)模式标志写入 PC而返回最初的模式是:
TEQP R6, #0 ; 把(在 R6 中的)最初的模式写入 PC
在改变了模式之后,你应该进行一个空操作来允许这个寄存器安定下来。比如
MOV R0, R0
之类的东西就可以。废弃使用 NV
后缀的指令。
32 位模式是重要的,因为 26 位(在老的 PSR 中)把每个应用程序的可寻址内存的最大数量限制为 28Mb。这就是不管你安装了多少内存你不能拖动超过 28Mb 的下一个槽(drag the Next slot beyond 28Mb)的原因。
CPSR 寄存器(和保存它的 SPSR 寄存器)中的位分配如下:
31 30 29 28 --- 7 6 - 4 3 2 1 0 N Z C V I F M4 M3 M2 M1 M0 0 0 0 0 0 User26 模式 0 0 0 0 1 FIQ26 模式 0 0 0 1 0 IRQ26 模式 0 0 0 1 1 SVC26 模式 1 0 0 0 0 User 模式 1 0 0 0 1 FIQ 模式 1 0 0 1 0 IRQ 模式 1 0 0 1 1 SVC 模式 1 0 1 1 1 ABT 模式 1 1 0 1 1 UND 模式
典型的,处理器将在 User26、FIQ26、IRQ26 和 SVC26 下操作。可以进入一个 32 位模式,但要格外小心。RISC OS 不希望这样,并且如果它发现自己在其中会非常生气!
你不能在 32 位模式中使用 MOVS PC, R14
或 LDMFD
R13!, {registers, PC}^
。也不能使用 ORRS PC, R14,
#1<<28
来设置 V 标志。现在需要使用 MRS
和
MSR
。
复制一个寄存器到 PSR 中 MSR CPSR, R0 ; 复制 R0 到 CPSR 中 MSR SPSR, R0 ; 复制 R0 到 SPSR 中 MSR CPSR_flg, R0 ; 复制 R0 的标志位到 CPSR 中 MSR CPSR_flg, #1<<28 ; 复制(立即值)标志位到 CPSR 中
复制 PSR 到一个寄存器中 MRS R0, CPSR ; 复制 CPSR 到 R0 中 MRS R0, SPSR ; 复制 SPSR 到 R0 中指令格式
你有两个 PSR - CPSR
是当前的程序状态寄存器(Current
Program Status Register),而 SPSR
是保存的程序状态寄存器(Saved Program Status Register)(前面的处理器模式的
PSR)。每个有特权的模式都有自己的 SPSR,可获得的 PSR 有:
_flg
后缀允许你改变标志位而不影响控制位。
在 user(32) 模式中,保护 CPSR 的控制位,你只能改变条件标志。在其他模式中,可获得整个 CPSR。你不应该指定 R15 为一个源寄存器或一个目标寄存器。最后,在 user(32) 模式中,你不能尝试访问 SPSR,因为它不存在!
要设置 V 标志:
MSR CPSR_flg, #&10000000这将设置 V 标志但不影响控制位。
要改变模式:
MRS R0, CPSR_all ; 复制 PSR BIC R0, R0, #&1F ; 清除模式位 ORR R0, R0, #new_mode ; 把模式位设置为新模式 MSR CPSR_all, R0 ; 写回 PSR,变更模式
现在我们要做的是进入 SVC32 模式并设置 Z
标志。接着我们返回 SVC26 模式并‘测试’是否设置了 Z。
RISC OS 不希望发现自己处在 32
位模式中,所以我们要禁止所有中断并保持它们这样(keep them
that way)。尽管这些代码应该执行的非常快,但我们不应当冒任何风险...
你可能觉得 32 位模式不是非常有用。在当前版本的 RISC OS 下,这是事实。实际上,就我而言,32 位模式提供给你的只是:
本文档的最初版本,和最初的 ARM 汇编器指南包括...
尽管 32 位模式的利益好象不是多的那么惊人,新近的处理器(比如 Xscale)不再支持 26 位模式,所以 RISC OS 和它的应用程序要在 32 位环境下工作则必须经过修改。听起来不是很多,但是如果所有补偿/改变 R15 中的 PSR 位的引用都必须被变更为对不在 R15 中的独立的 PSR 的引用,这就突然变成一个非常重大的问题了。还有你不能继续用一个指令来恢复 PSR 并分支回到调用者,现在这需要两个独立的指令。为此代码必须重写。你不能简单的用另一个指令来修补...