找回密码
 注册
关于网站域名变更的通知
查看: 786|回复: 3
打印 上一主题 下一主题

ARM条件执行

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-5-6 13:56 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
条件执行
指令格式4 ]  E% }! Q! j
ARM 处理器的一个非常特殊的特征是它的条件执行。我们指的不是基本的如果进位则分支,ARM 使这个逻辑阶段进一步深化为如果进位则 XXX - 这里的 XXX 是任何东西。" @  Z2 r# V  Z+ p; k' P
为了举例,下面是 Intel 8086 处理器分支指令的一个列表:1 t' O4 Q  X) i. [8 c
JA Jump if Above. V3 q9 w9 V- _
JAE Jump if Above or Equal
& r& x$ i/ G- O7 Q4 z7 C4 wJB Jump if Below$ Y# Z1 }% u* Z( K
JBE Jump if Below or Equal
  F4 R, P, j$ w8 x( mJC Jump if Carry; V% L9 S' R2 c) _7 }% Q. i
JCXZ Jump if CX Zero (CX is a register that can be used for loop counts)
- l; d$ f9 ~- gJE Jump if Equal, e9 Z8 _5 j/ ]$ V5 f6 C% U9 j
JG Jump if Greater than
! b8 C9 x& \) t" Q* e" tJGE Jump if Greater than or Equal% B& O0 [" z% ?1 o& U
JL Jump if Less than- E* O" z" m0 I2 |, v+ i" ?
JLE Jump if Less Than or Equal" l! o- U2 j  [8 n# c( _& _6 v, E
JMP JuMP
% R; R5 ]+ C% N' aJNA Jump if Not Above
. D) L: I0 ?0 e* N5 @$ n0 \JNAE Jump if Not Above or Equal5 k( V3 j  }$ G( ]# q+ Z+ }7 Z
JNB Jump if Not Below$ N2 J2 L* m  U) S
JNBE Jump if Not Below or Equal; Z+ d- B- p5 J" |2 O4 K
JNC Jump if No Carry' b3 t8 E/ Y0 o, l- M
JNE Jump if Not Equal
" o3 |- @' g  H0 v/ X7 E8 gJNG Jump if Not Greater than
. {4 J0 M0 a  X/ [JNGE Jump if Not Greater than or Equal- D0 G- p) `- H$ s  i
JNL Jump if Not Less than8 c; o& i. x+ x
JNLE Jump if Not Less than or Equal
! P( x1 r% i# Y' w% U! `$ RJNO Jump if Not OveRFlow
4 N0 b: T- P3 l0 ?) iJNP Jump if Not Parity
3 N& u- T1 K, p6 G3 QJNS Jump if Not Sign
- r8 Z8 E& j0 RJNZ Jump if Not Zero7 m, e+ U" l( T! \6 p( q6 r% D
JO Jump if Overflow+ Q& H! r* r  X2 o& F) I! c5 a" B
JP Jump if Parity
. R. }# a. x" RJPE Jump if Parity Even* N( Z. I4 }& Q: w/ B  x( S. p
JPO Jump if Parity Odd+ q4 }! m7 o; N' m, c' L  R
JS Jump if Sign, B4 _& k5 W' P1 z8 g4 `) \
JZ Jump if Zero, n$ I* a( V1 S+ Q6 Q
80386 添加了:3 U7 {0 F7 D) }; q" f7 m
JECXZ Jump if ECX Zero* t/ I" U- [4 z9 I; g- L& S8 @
作为对比,ARM 处理器只提供了:5 J- }3 P; D+ `7 m7 z& f6 L
B 分支
% W8 |7 ?8 g4 m, L# w, DBL 带连接的分支7 S; [0 q5 i6 J' c6 Q& O
但 ARM 提供了条件执行,你可以不受这个表面上不灵活的方式的限制:
4 R1 E" M1 m# w( n, |BEQ Branch if EQual1 Z2 w; H6 w# D$ }2 Q5 _
BNE Branch if Not Equal
" b% V5 J. P6 A  H" oBVS Branch if oVerflow Set
1 u8 N5 Z4 g6 m1 i% y$ M2 mBVC Branch if oVerflow Clear
9 K- r% q! V1 G0 PBHI Branch if HIgher4 Q! v" B) O  X% ^$ H* f
BLS Branch if Lower or the Same* m$ C; U" v$ q
BPL Branch if PLus
- L! Y. F) F2 `4 ]8 EBMI Branch if MInus
8 l2 V8 t9 J! a1 k% r  LBCS Branch if Carry Set& @; O# ]( ?# w# _+ W4 a0 G* l
BCC Branch if Carry Clear, a4 A7 \! R) |6 q5 I
BGE Branch if Greater than or Equal
  Z; a8 `/ M1 c9 N5 U: [0 CBGT Branch if Greater Than
4 C0 K' D$ L7 \BLE Branch if Less than or Equal, J7 i& b, G. q: g" d+ v5 a
BLT Branch if Less Than9 i5 x! d& F! L6 |
BLEQ Branch with Link if EQual
. R6 z/ P! F. l  l9 R2 x8 I....
9 }- f) ~# T6 RBLLT Branch with Link if Less Than$ f* {& N  K) r7 o5 c. |) m7 j% g
还有两个代码,
2 [% p. h( O$ g( ^6 E/ QAL - ALways,缺省条件所以不须指定9 k2 J0 V9 o* S: y! ^& o6 d
NV - NeVer,不是非常有用。你无论如何不要使用这个代码...
% Q# ]' }8 ]& a0 t当你发现所有 Bxx 指令实际上是同一个指令的时候,紧要关头就到了。接着你会想,如果你可以在一个分支指令上加上所有这些条件,那么对一个寄存器装载指令能否加上它们? 答案是可以。
6 Y" w+ |3 h0 `4 s" X下面是可获得的条件代码的列表:
+ f$ [3 y( h1 r0 Y5 `, p# s: ZEQ : 等于8 j: @# X% K2 c5 T' y$ ^
如果一次比较之后设置了 Z 标志。! k7 h5 v1 G( s0 V3 S% w2 h" W2 w4 E7 \
NE : 不等于0 \8 B% Y- B! O
如果一次比较之后清除了 Z 标志。
( M+ T" _7 R3 n1 H7 \1 FVS : 溢出设置
5 G" Y( ~; Y! l+ X8 j% X如果在一次算术操作之后设置了 V 标志,计算的结果不适合放入一个 32bit 目标寄存器中。
8 o, R( |: i, O; \; T, Q" vVC : 溢出清除! h7 k+ B/ R5 B% p
如果清除了 V 标志,与 VS 相反。% `' X8 A5 [  E' \. V; R
HI : 高于(无符号)8 v2 `: w# k& D& W9 U
如果一次比较之后设置了 C 标志并清除了 Z 标志。
/ d( [  f7 b6 t' w8 ]8 C6 I, D! c: e  BLS : 低于或同于(无符号)
6 R3 C& k; ]5 G) A$ V如果一次比较操作之后清除了 C 标志或设置了 Z 标志。3 C& q* w8 d! D5 H$ r" ]! R* o+ x) y
PL : 正号
4 l! [) |% ?7 B- Q2 d如果一次算术操作之后清除了 N。出于定义‘正号’的目的,零是正数的原因是它不是负数...
, c: _* @- i0 W( S6 DMI : 负号
: @+ h* [9 L  q' ]( O如果一次算术操作之后设置了 N 标志。, \, r! Y( m: }+ O7 X, i# z
CS : 进位设置# z; f9 T* u. I" g# K" u
如果一次算术操作或移位操作之后设置了 C 标志,操作的结果不能表示为 32bit。你可以把 C 标志当作结果的第 33 位。# M( H4 l/ q+ Z  H% g. R
CC : 进位清除% L  s+ L" G! n( G
与 CS 相反。
0 t7 W2 J+ l/ ~GE : 大于或等于(有符号)& ^0 i0 @, o7 @; k9 Z! n) W
如果一次比较之后...
* f5 d- l# m- a设置了 N 标志并设置了 V 标志3 Q9 \- \  ?- h4 |+ J2 X4 f
或者...
9 G; }6 e1 e; ^$ X/ l' n2 ]清除了 N 标志并清除了 V 标志。
6 X3 G% r8 Q3 vGT : 大于(有符号), y4 x3 {8 g, ]5 z: X$ n
如果一次比较之后...
4 Z5 b3 @7 ~; Q3 P7 E设置了 N 标志并设置了 V 标志
( N% b+ ~2 X7 a' w4 o或者...
" [+ {* P) z. c, k! Q  F清除了 N 标志并清除了 V 标志# X" `1 B$ z' m7 R1 V
并且...( Z: J! O' p0 w" I1 K4 w% ]# W" e4 x
清除了 Z 标志。
( M7 Y. i6 t: u+ ^LE : 小于或等于(有符号)
( f- b7 L: y: J! y; I" U# j- y6 ^如果一次比较之后...: l, W1 A' |- @7 i
设置了 N 标志并清除了 V 标志( \; A) t4 J" l- w$ O" c- e
或者...
% z7 }/ U1 U8 U清除了 N 标志并设置了 V 标志: v2 H7 |( f+ L- g
并且...
* a8 Z' E' N1 I设置了 Z 标志。% }: J+ F$ k' M: M5 i' M5 t8 t
LT : 小于(有符号)
( M- Y; D6 S. V如果一次比较之后...9 G1 P6 B  ]% Y3 [6 N& u; o
设置了 N 标志并清除了 V 标志。
5 p% z6 H2 h8 g0 k4 M* `; \& s或者...
0 _9 l! V, J8 `+ \0 l; t) x清除了 N 标志并设置了 V 标志。
  j9 ?' a, g7 a2 ^/ _AL : 总是  E, L3 r; ]& x1 ]* ]! V
缺省条件,所以不用明显声明。
3 a8 I; v' ?3 {$ \NV : 从不; X+ b: ?: L5 y
不是特别有用,它表示应当永远不执行这个指令。是穷人的 NOP。8 O: x6 @7 W8 T$ e. {0 A
包含 NV 是为了完整性(与 AL 相对),你不应该在你的代码中使用它。6 z0 U5 u) q! j- h9 k) |3 f4 c
有一个在最后的条件代码 S,它以相反的方式工作。当用于一个指令的时候,导致更改状态标志。这不是自动发生的 - 除非这些指令的目的是设置状态。例如:
9 Y. a  v' E9 V0 [2 m1 u4 Y7 lADD R0, R0, R14 y, ~% f( H6 X4 m9 \8 e/ u# Q
ADDS R0, R0, R1
1 m. ]& H" ~1 P( s' {ADDEQS R0, R0, R18 a4 Y; M6 Z" J4 u: b7 [, V% S
第一个例子是一个基本的加法(把 R1 的值增加到 R0),它不影响状态寄存器。# j- l$ ~. ]* ^# o
第二个例子是同一个加法,只不过它导致更改状态寄存器。
( e# d) t; K7 S/ V+ g最后一个例子是同一个加法,更改状态寄存器。不同在于它是一个有条件的指令。只有前一个操作的结果是 EQ (如果设置了 Z 标志)的时候它才执行。
1 o+ e, z/ H# R' {. o5 Q& B$ r) Y7 r下面是条件执行的一个工作中的例子。你把寄存器 0 与存储在寄存器 10 中内容相比较。如果不等于 R10,则调用一个软件中断,增加它并分支回来再次做这些。否则清除 R10 并返回到调用它的那部分代码(它的地址存储在 R14)。
6 j( w1 k; e4 g) d" o\ 条件执行的一个例子6 e, i, R+ ^0 }% T# @$ W" ~
.loop ; 标记循环开始位置
8 h+ {, e- X5 ]! a+ {6 \CMP R0, R10 ; 把 R0 与 R10 相比较1 `! S1 ~0 n5 P9 u
SWINE &40017 ; 不等于: 调用 SWI &400171 P* p' w5 B. G0 E
ADDNE R0, R0, #1 ; 向 R0 加 1# @* o/ y* R6 l, W9 ^8 c# S
BNE loop ; 分支到 loop1 A% W6 A4 A$ k! q' p) v' p5 ^
MOV R10, #0 ; 等于 : 设置 R10 为零
, r: F- o8 m" T/ T6 d0 b! ZLDMFD R13!, {R0-R12,PC} ; 返回到调用者- d* h7 k4 M  M. g% a4 E
注解:/ q1 M' Z7 u: G3 y
SWI 编号就象我写的这样。在 RISC OS 下,它是给 Econet_DoImmediate 的编号。不要字面的接受它,这只是一个例子!
/ }" F# a& e$ w! Z4 o你可能以前没见过 LDMFD,它从栈中装载多个寄存器。在这个例子中,我们从一个完全正式的栈中装载 R0 至 R12 和 R14。关于寄存器装载和存储的更多信息请参阅 str.html。
% C2 J* V! R5 v2 Y) K我说要装载 R14。那么为什么要把它放入 PC 中? 原因是此时 R14 存储的值包含返回地址。我们也可以采用:
2 T1 ^; Q  J0 v$ M" P9 n5 ^2 Y& ELDMFD R13!, {R0-R12,R14}
, C/ k. j' R3 eMOV PC, R14. y6 g8 V$ n- D; \
但是直接恢复到 PC 中可以省略这个 MOV 语句。
# H9 T6 ^( r( w' R2 ]最后,这些寄存器很有可能被一个 SWI 调用所占用(依赖于在调用期间执行的代码),所以你最好把你的重要的寄存器压入栈中,以后在恢复它们。
" p' F, I2 b$ p$ e6 j* B# |0 [
  • TA的每日心情
    开心
    2023-1-3 15:10
  • 签到天数: 2 天

    [LV.1]初来乍到

    4#
    发表于 2021-5-6 17:16 | 只看该作者
    很实用,收藏了

    该用户从未签到

    3#
    发表于 2021-5-6 15:24 | 只看该作者
    ARM条件执行云集, b4 c3 [* W' n) Q% U
  • TA的每日心情
    慵懒
    2022-12-26 15:28
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2021-5-6 14:43 | 只看该作者
    本帖最后由 nevadaooo 于 2021-5-6 17:52 编辑 8 r5 a% F3 X( d$ b8 E9 t$ p
    1 @+ D% M* V; |, Q5 ]
    很详细,先收了,后面练练
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-24 19:52 , Processed in 0.171875 second(s), 24 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表