📄 程序状态寄存器.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0049)http://www.linuxforum.net/books/mhss/arm/psr.html -->
<HTML><HEAD><TITLE>PSR and conditional execution</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META http-equiv=Content-Language content=zh-cn>
<META content="MSHTML 6.00.2600.0" name=GENERATOR>
<META content=FrontPage.Editor.Document name=ProgId></HEAD>
<BODY text=#000000 vLink=#002288 link=#0022dd bgColor=#f0f0f0>
<TABLE width="100%" border=0>
<TBODY>
<TR>
<TD align=middle width=100></TD>
<TD>
<H1 align=center><FONT color=#800080>程序状态寄存器</FONT></H1></TD>
<TD align=middle width=100></TD></TR></TBODY></TABLE>
<UL>
<LI><A href="http://www.linuxforum.net/books/mhss/arm/psr.html#mrs">MRS</A>
<LI><A href="http://www.linuxforum.net/books/mhss/arm/psr.html#msr">MSR</A>
</LI></UL>
<P><A href="http://www.linuxforum.net/books/mhss/arm/psr.html#32bit">直接查看
R15/PSR 在 32-bit 模式下的详情</A>
<H2>寄存器 15 (26-bit 模式):</H2>R15 构造如下: <PRE> Bit 31 30 29 28 27 26 25------------2 1 0
N Z C V I F 程 序 计 数 器 S1 S0
</PRE>标志的意义: <PRE> 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 - 超级用户模式
</PRE>
<P>在 R15 作为一个指令的第一个操作数的时候,只有程序计数器部分是可以获得的。所以,下列指令把 PC 复制到一个寄存器中并向这个目标寄存器加上
256:<BR><CODE> ADD R0, R15, #256</CODE><BR>(对于
BASIC 汇编器 R15 和 PC 的意思是相同的)
<P>在 R15 作为第二个操作数的时候,所有 32 位都是可以获得的: 程序计数器、标志、和状态。下列代码段将标识当前的处理器模式: <PRE> 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'
</PRE><FONT color=red>这个例子不遵从 32-bit 体系。如何在 32-bit 环境中读当前的模式请参照<A
href="http://www.linuxforum.net/books/mhss/arm/psr.html#mrs">下面的章节</A>。</FONT><BR><!--<div align = right><a href="sw/currmode.basic"><i>Download example: currmode.basic</i></a></div>-->
<H2>改变处理器的状态:</H2>要改变处理器模式、或者任何标志,我们需要用想要的标志 EOR(异或)状态标志,<CODE>新状态 = 旧状态 EOR (1
<< 28)</CODE> 可以成为改变 oVerflow 标志的伪码。但是我们不能做这个简单的 <CODE>EORS</CODE>
操作,原因是这将导致随后的两个指令被跳过。不要担心,指令 <CODE>TEQ</CODE> 做一个假装的 EOR (结果不存储到任何地方)。把它与
<CODE>P</CODE> 后缀组合,则把结果的第 0、1、和 26 至 31 位直接写到 R15 的第 0、1、和 26 至 31
位,这是改变标志的一个简便的方法: <CODE> TEQP R15, bit_mask</CODE>
<P <i>如果你处在允许你设置一个标志的一个模式中,则你只可以改变这个标志。
<P <i><FONT color=red>这个例子不遵从 32-bit 体系。如何在 32-bit 环境中改变模式请参照<A
href="http://www.linuxforum.net/books/mhss/arm/psr.html#mrs">下面的章节</A>。</FONT></P>
<P>可以被扩充它来改变处理器模式。例如,要进入 SVC 模式你可以: <PRE> MOV R6, PC ; 把 PC 的最初状态存储到 R6 中
ORR R7, R6, #3 ; 设置 SVC 模式
TEQP R7, #0 ; 把(在 R7 中的)模式标志写入 PC
</PRE>而返回最初的模式是: <PRE> TEQP R6, #0 ; 把(在 R6 中的)最初的模式写入 PC
</PRE><!--<div align = right><a href="sw/setmode.basic"><i>Download example: setmode.basic</i></a></div>-->
<P>在改变了模式之后,你应该进行一个空操作来允许这个寄存器安定下来。比如 <CODE>MOV R0, R0</CODE> 之类的东西就可以。废弃使用 NV
后缀的指令。
<P>
<P><A name=32bit></A>
<H2>32 位 PSR</H2>如同在<A
href="http://www.linuxforum.net/books/mhss/arm/32bit.html">32 位操作</A>中描述的那样,ARM
3 之后的处理器提供一个 32 bit 地址空间,它们把 PSR 移出 R15 并给予 R15 完整的 32
位位域,在其中存储当前位置的地址。目前,除了一些不太可能遇到的情况之外,RISC OS 工作在 26 位模式。
<P>32 位模式是重要的,因为 26 位(在老的 PSR 中)把每个应用程序的可寻址内存的最大数量限制为 28Mb。这就是不管你安装了多少内存你不能拖动超过
28Mb 的下一个槽(drag the Next slot beyond 28Mb)的原因。</P>
<P>CPSR 寄存器(和保存它的 SPSR 寄存器)中的位分配如下: <PRE> 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 模式
</PRE>
<P>典型的,处理器将在 User26、FIQ26、IRQ26 和 SVC26 下操作。可以进入一个 32 位模式,但要格外小心。RISC OS
不希望这样,并且如果它发现自己在其中会非常生气!
<P><A name=msr></A><A name=mrs></A>
<H2>操纵 32 位 PSR 的指令</H2>
<P>你不能在 32 位模式中使用 <CODE>MOVS PC, R14</CODE> 或 <CODE>LDMFD R13!,
{<I>registers</I>, PC}^</CODE>。也不能使用 <CODE>ORRS PC, R14, #1<<28</CODE> 来设置
V 标志。现在需要使用 <CODE>MRS</CODE> 和 <CODE>MSR</CODE>。</P><PRE>复制一个寄存器到 PSR 中
MSR CPSR, R0 ; 复制 R0 到 CPSR 中
MSR SPSR, R0 ; 复制 R0 到 SPSR 中
MSR CPSR_flg, R0 ; 复制 R0 的标志位到 CPSR 中
MSR CPSR_flg, #1<<28 ; 复制(立即值)标志位到 CPSR 中
</PRE><PRE>复制 PSR 到一个寄存器中
MRS R0, CPSR ; 复制 CPSR 到 R0 中
MRS R0, SPSR ; 复制 SPSR 到 R0 中
</PRE><A
href="http://www.linuxforum.net/books/mhss/arm/ARMinstrs.html#Status">指令格式</A>
<P>你有两个 PSR - <CODE>CPSR</CODE> 是当前的程序状态寄存器(Current Program Status Register),而
<CODE>SPSR</CODE> 是保存的程序状态寄存器(Saved Program Status Register)(前面的处理器模式的
PSR)。每个有特权的模式都有自己的 SPSR,可获得的 PSR 有:</P>
<UL>
<LI>CPSR_all - 当前的
<LI>SPSR_svc - 保存的,SVC(32) 模式
<LI>SPSR_irq - 保存的,IRQ(32) 模式
<LI>SPSR_abt - 保存的,ABT(32) 模式
<LI>SPSR_und - 保存的,UND(32) 模式
<LI>SPSR_fiq - 保存的,FIQ(32) 模式 </LI></UL>你不能显式的指定把 CPSR 保存到哪个 SPSR 中,比如
SPSR_fiq。而是必须变更到 FIQ 模式并接着保存到 SPSR。换句话说,你只能在你所在的模式中改变这个模式的 SPSR。使用
<CODE>_flg</CODE> 后缀允许你改变标志位而不影响控制位。
<P>在 user(32) 模式中,保护 CPSR 的控制位,你只能改变条件标志。在其他模式中,可获得整个 CPSR。你不应该指定 R15
为一个源寄存器或一个目标寄存器。最后,在 user(32) 模式中,你不能尝试访问 SPSR,因为它不存在!
<P>要设置 V 标志: <PRE> MSR CPSR_flg, #&10000000</PRE>这将设置 V 标志但不影响控制位。
<P>要改变模式: <PRE> MRS R0, CPSR_all ; 复制 PSR
BIC R0, R0, #&1F ; 清除模式位
ORR R0, R0, #new_mode ; 把模式位设置为新模式
MSR CPSR_all, R0 ; 写回 PSR,变更模式
</PRE>
<P>现在我们要做的是进入 SVC32 模式并设置 Z 标志。接着我们返回 SVC26 模式并‘测试’是否设置了 Z。<BR>RISC OS 不希望发现自己处在
32 位模式中,所以我们要禁止所有中断并保持它们这样(keep them that way)。尽管这些代码应该执行的非常快,但我们不应当冒任何风险... <!--<div align = right><a href="sw/32bittest.basic"><i>Download this example</i></a></div>-->
<P>你可能觉得 32 位模式不是非常有用。在当前版本的 RISC OS 下,这是事实。实际上,就我而言,32 位模式提供给你的只是:
<UL>
<LI>访问大于 28Mb 的区域。在 RISC OS 上这不是真的很重要,在这个系统里 web 浏览器适合于 1 M 或 2
M,而重要的艺术程序为那些非常巨大的图象提供它们自己的虚拟内存系统。 </LI></UL>
<P>本文档的最初版本,和最初的 ARM 汇编器指南包括...
<UL>
<LI>StrongARM 提供了两个指令(UMUL 和 UMLA、IIRC),它们处理 64 位乘法。这只能在 32 位模式下获得。
</LI></UL>这是<B>错误</B>的。在 26 位模式下可以使用扩展的乘法;MP3 解码器就使用了它!
<P>尽管 32 位模式的利益好象不是多的那么惊人,新近的处理器(比如 Xscale)不再支持 26 位模式,所以 RISC OS 和它的应用程序要在 32
位环境下工作则必须经过修改。听起来不是很多,但是如果所有补偿/改变 R15 中的 PSR 位的引用都必须被变更为对不在 R15 中的独立的 PSR
的引用,这就突然变成一个非常重大的问题了。还有你不能继续用一个指令来恢复 PSR
并分支回到调用者,现在这需要两个独立的指令。为此代码必须重写。你不能简单的用另一个指令来修补...
<P> </P>
<HR SIZE=3>
<A href="http://www.linuxforum.net/books/mhss/arm/index.html">Return to
assembler index</A>
<HR SIZE=3>
<ADDRESS>Copyright © 2001 Richard Murray </ADDRESS></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -