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

ARM条件执行

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
条件执行
指令格式
) h: W  W& n; x) {. I* K9 kARM 处理器的一个非常特殊的特征是它的条件执行。我们指的不是基本的如果进位则分支,ARM 使这个逻辑阶段进一步深化为如果进位则 XXX - 这里的 XXX 是任何东西。# p- Z( n( |& P, [( h
为了举例,下面是 Intel 8086 处理器分支指令的一个列表:
/ B: B& ^$ S/ U& x% ]* P- _JA Jump if Above
% q  U1 f9 j/ O6 Z7 w0 NJAE Jump if Above or Equal$ k8 @  u$ Z  j. w
JB Jump if Below
" j! c% n( a+ b& SJBE Jump if Below or Equal
8 z0 x8 j- Q9 m$ JJC Jump if Carry, P! H' ~+ p9 W1 J8 x8 I' H
JCXZ Jump if CX Zero (CX is a register that can be used for loop counts)
$ j. L6 C5 [" Y$ q* ]JE Jump if Equal  F0 \/ f( u3 g7 ^, T4 ^
JG Jump if Greater than
3 m7 M1 z5 Y! }# O; VJGE Jump if Greater than or Equal
* D9 }9 m5 a/ O8 O2 j- ]3 aJL Jump if Less than1 x5 N* }7 i1 z- q5 w2 C
JLE Jump if Less Than or Equal
, h. w5 [7 ^9 e7 v6 M: UJMP JuMP/ U' E: v$ F  a0 u9 A. V1 b
JNA Jump if Not Above
+ y% V8 l4 a9 M) M$ M$ P0 z1 WJNAE Jump if Not Above or Equal4 O3 w' R. e2 i  w, j# [5 E" g/ |3 I
JNB Jump if Not Below
% v# _% S6 `# T5 w% MJNBE Jump if Not Below or Equal
3 ~0 ~. U+ K2 F' B# Q5 @* W2 KJNC Jump if No Carry
2 b7 e9 s8 B, ~2 y1 q( hJNE Jump if Not Equal4 @. I3 V( E2 h) y2 d! B
JNG Jump if Not Greater than
4 I( ~4 {* j" a! k. w5 XJNGE Jump if Not Greater than or Equal1 h4 x6 K5 g5 s! A! f
JNL Jump if Not Less than" i) Z- M9 R) I% Z( {5 Y- i2 d) U/ ~; z
JNLE Jump if Not Less than or Equal
: |+ U# e% m$ a$ c7 F9 U/ RJNO Jump if Not OveRFlow  Q$ u1 T0 C. H6 w3 A' w* I
JNP Jump if Not Parity
7 I9 _1 J* j* T1 Z' E* r, `JNS Jump if Not Sign
3 o; Z4 ?2 u: P+ m( h' jJNZ Jump if Not Zero
$ z  c# Y- {  FJO Jump if Overflow
2 C$ Y9 J, i5 E8 }JP Jump if Parity
8 C: {1 \: w3 F7 `2 s) `JPE Jump if Parity Even3 |# @6 L. c' g! g. ]+ x/ ]
JPO Jump if Parity Odd1 q( A) }  V4 L+ S# u/ l
JS Jump if Sign
, J1 J/ m: u& }+ AJZ Jump if Zero
1 c! _1 |! V; D6 U, w5 u7 q80386 添加了:5 D% [! E4 z4 d6 Z9 Q& D  @
JECXZ Jump if ECX Zero4 [3 [, ?! f1 T& c- J  L4 [2 \
作为对比,ARM 处理器只提供了:
0 N4 ^! R* V& \6 kB 分支: Z4 ^2 k5 S. c+ C  E( p% g4 ^
BL 带连接的分支
4 G- r- K; Z* G& r* E: r但 ARM 提供了条件执行,你可以不受这个表面上不灵活的方式的限制:
+ Q9 S# A9 I$ pBEQ Branch if EQual# m/ u5 C2 ~' Y0 A" H% {& b8 Z
BNE Branch if Not Equal% r( u7 A  F2 l0 v
BVS Branch if oVerflow Set
( O9 {; O' C4 n! D2 H" k/ @# Q) mBVC Branch if oVerflow Clear  |4 B, l5 b6 z4 s5 c$ i* z, _
BHI Branch if HIgher
9 e. Z3 G6 a  N; ^' r( Y- `& mBLS Branch if Lower or the Same
* ^4 E! W2 @# I7 KBPL Branch if PLus4 L/ \4 `9 J2 e5 F4 ]; o. k
BMI Branch if MInus
& _" {& @5 f8 ?0 iBCS Branch if Carry Set
6 T1 h' N4 b) jBCC Branch if Carry Clear
: o, R" ?# N$ t9 N* U2 \BGE Branch if Greater than or Equal( C; g1 ?, |+ [- ~) v
BGT Branch if Greater Than
$ ]8 ^0 H& i; aBLE Branch if Less than or Equal
; L9 X* u8 m3 JBLT Branch if Less Than- ?7 y5 m! }0 \* x% k
BLEQ Branch with Link if EQual$ C# X( M; y( c. l/ X
....
; z5 a' W# x8 U, n) d1 a+ ]( SBLLT Branch with Link if Less Than$ t, B! K+ d8 i- ]; M+ h
还有两个代码,) h: [$ l# o1 L
AL - ALways,缺省条件所以不须指定
# _5 _) A( e  U' lNV - NeVer,不是非常有用。你无论如何不要使用这个代码.../ Q- G+ ~' m5 U3 L8 B& m
当你发现所有 Bxx 指令实际上是同一个指令的时候,紧要关头就到了。接着你会想,如果你可以在一个分支指令上加上所有这些条件,那么对一个寄存器装载指令能否加上它们? 答案是可以。# c4 j: W4 {; Q9 G1 i/ `4 ^3 L. P' e
下面是可获得的条件代码的列表:
1 S* x) J/ I: ?1 J& w1 D  p& IEQ : 等于8 o. U0 @/ E; S; h, D
如果一次比较之后设置了 Z 标志。
7 a2 i8 H- Y  vNE : 不等于
$ ^+ ^' Z3 K) |  H2 S" [如果一次比较之后清除了 Z 标志。
6 l8 r3 {) A% I( K6 ~VS : 溢出设置1 ^3 D5 P( K, q% c$ I
如果在一次算术操作之后设置了 V 标志,计算的结果不适合放入一个 32bit 目标寄存器中。
: O% W; h- b- {4 a4 w3 fVC : 溢出清除
  J- d. q' p8 {- p4 V/ J9 C! f如果清除了 V 标志,与 VS 相反。2 B1 a3 y4 w! y0 N) u
HI : 高于(无符号)
- F+ V! P& r7 n如果一次比较之后设置了 C 标志并清除了 Z 标志。
9 o1 x' Z& E5 TLS : 低于或同于(无符号)9 Z: l+ g: @2 R4 @1 f
如果一次比较操作之后清除了 C 标志或设置了 Z 标志。6 j, x* v3 L1 E! E; T
PL : 正号
$ X2 ~( E: E/ W. g/ }: Q如果一次算术操作之后清除了 N。出于定义‘正号’的目的,零是正数的原因是它不是负数...
  Z- [5 {8 {0 m0 YMI : 负号
$ Z1 a3 w3 ?( M, `' d. l如果一次算术操作之后设置了 N 标志。0 s8 B. v: S' T. ~  o4 j
CS : 进位设置
* {4 ~- s9 T& L9 s' `& |2 m如果一次算术操作或移位操作之后设置了 C 标志,操作的结果不能表示为 32bit。你可以把 C 标志当作结果的第 33 位。$ I/ {* X" p. C. M$ w
CC : 进位清除7 X: S4 O; s. O" p$ }7 F* _
与 CS 相反。& \9 S3 R  i& x0 y. P
GE : 大于或等于(有符号)
4 U/ S/ l. P0 y1 ]如果一次比较之后...8 Y; t% G, j& K0 V7 t& m2 w9 b9 N
设置了 N 标志并设置了 V 标志( e0 }, i- d& g- Z$ s8 y6 Q
或者...
: Y0 x# F4 I, {* u+ r/ l8 l/ A清除了 N 标志并清除了 V 标志。" V5 l( f3 O" o  x# U' ~
GT : 大于(有符号)
0 n2 A* {' a- B8 {$ a如果一次比较之后...
; ]% V5 ?1 _/ ]1 `. P1 ^! q设置了 N 标志并设置了 V 标志
- o% y/ e. G" m& a或者...
' m( o, r. ^6 O& K6 N清除了 N 标志并清除了 V 标志
. @% @7 Q1 b4 m2 k2 x* ]并且...
+ L, Q$ Z- G! y6 ~& H& `清除了 Z 标志。
; c' }4 P0 p0 y/ HLE : 小于或等于(有符号)% y4 ^- T! Y% s. [. R+ l
如果一次比较之后...
' E+ |6 w; F$ G* Z" v2 ?5 ^设置了 N 标志并清除了 V 标志
1 X  E' n1 k5 v; {2 f. H或者...5 p+ ^7 _: a( y1 g
清除了 N 标志并设置了 V 标志
6 I' M7 k8 R5 C并且...
' h- h% |; q( t设置了 Z 标志。/ A2 ^7 O8 \' ]* ~8 I% [2 O0 ~: v$ b
LT : 小于(有符号)) g( V: t5 n5 W' ?6 m" i" k; G9 o
如果一次比较之后...
8 m, d. D/ I' T# \5 u, ^0 u设置了 N 标志并清除了 V 标志。% b9 F& Z; U$ Y' E, ^! p) D
或者...
5 W/ [! s+ H' K$ u" e; i& P清除了 N 标志并设置了 V 标志。3 Q( X- s: [1 ^5 s& \% r0 b
AL : 总是3 s7 i4 }: i7 {7 r/ V9 g9 v
缺省条件,所以不用明显声明。
  V% ~2 ]2 K5 {3 o# MNV : 从不
( n) Q) a; m& T. n8 `( \不是特别有用,它表示应当永远不执行这个指令。是穷人的 NOP。
, L4 i2 ]8 s) {$ C* }. C* ?+ {包含 NV 是为了完整性(与 AL 相对),你不应该在你的代码中使用它。& a  l, }& X, Z! ~
有一个在最后的条件代码 S,它以相反的方式工作。当用于一个指令的时候,导致更改状态标志。这不是自动发生的 - 除非这些指令的目的是设置状态。例如:: h' q% m3 I  l% a
ADD R0, R0, R1" T6 N- C8 w4 |9 B" R2 [1 C9 e
ADDS R0, R0, R1" L$ ^7 I0 K- U, a* X7 }$ N8 T
ADDEQS R0, R0, R18 `) b9 k! K! G7 N9 Q' q- N# Z; K7 M/ w2 P
第一个例子是一个基本的加法(把 R1 的值增加到 R0),它不影响状态寄存器。
( n$ f+ |$ j4 I第二个例子是同一个加法,只不过它导致更改状态寄存器。) _( `1 D% Z* X2 M6 j
最后一个例子是同一个加法,更改状态寄存器。不同在于它是一个有条件的指令。只有前一个操作的结果是 EQ (如果设置了 Z 标志)的时候它才执行。( T8 Y" g1 R! b4 `2 r- S: V" n7 J, j
下面是条件执行的一个工作中的例子。你把寄存器 0 与存储在寄存器 10 中内容相比较。如果不等于 R10,则调用一个软件中断,增加它并分支回来再次做这些。否则清除 R10 并返回到调用它的那部分代码(它的地址存储在 R14)。3 ^% h2 U: L: f; i, M
\ 条件执行的一个例子5 n' m2 M. V2 r) y4 \6 B4 d) `! l
.loop ; 标记循环开始位置0 l* {' d( u! u
CMP R0, R10 ; 把 R0 与 R10 相比较
8 C9 Q0 M6 v3 |% @. TSWINE &40017 ; 不等于: 调用 SWI &40017
1 W2 k) R7 q" o4 r9 E) V  I, tADDNE R0, R0, #1 ; 向 R0 加 1* i* g3 L, U. B. a3 y7 u, X  V( ?
BNE loop ; 分支到 loop% o+ z6 X0 K* R  [( J
MOV R10, #0 ; 等于 : 设置 R10 为零. a* R8 M* g7 G1 i% b
LDMFD R13!, {R0-R12,PC} ; 返回到调用者
2 k# U8 I- Y' S注解:
9 g9 V$ w! O( l. z. H* rSWI 编号就象我写的这样。在 RISC OS 下,它是给 Econet_DoImmediate 的编号。不要字面的接受它,这只是一个例子!) Y* K4 Z" J6 E4 D. U  [- q
你可能以前没见过 LDMFD,它从栈中装载多个寄存器。在这个例子中,我们从一个完全正式的栈中装载 R0 至 R12 和 R14。关于寄存器装载和存储的更多信息请参阅 str.html。+ G9 V. w0 t1 w
我说要装载 R14。那么为什么要把它放入 PC 中? 原因是此时 R14 存储的值包含返回地址。我们也可以采用:
, L: M, Y1 L3 y7 H) tLDMFD R13!, {R0-R12,R14}
$ U/ b& {7 b0 ?6 B( vMOV PC, R14
2 |% J1 |. ?; i5 W/ f8 Z/ |% g但是直接恢复到 PC 中可以省略这个 MOV 语句。
2 j2 [9 M0 O( j, n最后,这些寄存器很有可能被一个 SWI 调用所占用(依赖于在调用期间执行的代码),所以你最好把你的重要的寄存器压入栈中,以后在恢复它们。

5 U4 b! Q3 |5 n/ {+ S
  • TA的每日心情
    慵懒
    2022-12-26 15:28
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2021-5-6 14:43 | 只看该作者
    本帖最后由 nevadaooo 于 2021-5-6 17:52 编辑
    " c3 r& Z' ?; R: g; J' N" d! K+ R, }7 {- z: F! m: W& z9 J# a
    很详细,先收了,后面练练

    该用户从未签到

    3#
    发表于 2021-5-6 15:24 | 只看该作者
    ARM条件执行云集% F9 y& X" q2 L! @0 U
  • TA的每日心情
    开心
    2023-1-3 15:10
  • 签到天数: 2 天

    [LV.1]初来乍到

    4#
    发表于 2021-5-6 17:16 | 只看该作者
    很实用,收藏了
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

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

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

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

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