Part 6:条件状态和分支

在探讨CPSR时我们已经接触了条件状态。我们通过跳转(分支)或者一些只有满足特定条件才执行的指令来控制程序在运行时的执行流。通过CPSR寄存器中的特定bit位来表示条件状态。这些位根据指令每次执行的结果而不断变化。例如,比较运算时如果两个数相等,那么就置CPSR中的Zero位(Z=1),实际上是因为:a - b = 0,这种情况下就是相等状态。如果第一个数大,那么就是大于状态。如果第二个数大,就是小于状态。除此之外,还有小于等于大于等于等等。

下面的表格列出了可用的条件状态码,描述和标志位:

在下面代码片段中看一下执行条件加法时的实际用法L:

.global main
​
main:mov     r0, #2     /* 初始化变量 */cmp     r0, #3     /* 将R0中的值与3比较,负数位置1 */addlt   r0, r0, #1 /* 如果上一条比较结果是小于(查看CPSR),则将R0加1 */cmp     r0, #3     /* 将R0中的值再与3比较, 零位置1,同时负数位重置为0 */addlt   r0, r0, #1 /* 如果上一条比较结果是小于(查看CPSR),则将R0加1 */bx      lr

第一条cmp指令结果导致CPSR中的负数位置1(2- 3 = -1)意思是R0小于R3。因为满足小于条件(CPSR中的溢出位不等于负数位V != N)所以接下来的ADDLT指令执行。在执行下一条cmp指令时,R0 = 3。所以清除负数位(3 - 3 = 0,负数位清零),零位置位(Z = 1)。现在溢出位是0,负数位是0,不满足小于条件。所以最后一条ADDLT指令不执行,R0值保持3不变。

Thumb模式下的条件执行

我们在介绍指令集的章节讨论了Thumb状态下的不同。具体而言是Thumb-2版本支持条件执行。某些 ARM 处理器版本支持"IT"指令,允许在 Thumb 状态下支持多达4个条件执行指令。参考:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABIJDIC.html

语法:IT{x{y{z}}} cond

  • cond 指定 IT 块的第一个指令的条件。
  • x 指定 IT 块中第二个指令的条件开关。
  • y 指定 IT 块中第三个指令的条件开关。
  • z 指定 IT 块中第四个指令的条件开关。

其实IT指令的结构就是“IF-Then-(Else)”,语法都是由字母“T”和“E”构成:

  • IT:If-Then(下一条指令是条件的);
  • ITT:If-Then-Then(后两条指令是条件的);
  • ITE:If-Then-Else(后两条指令是条件的);
  • ITTE:If-Then-Then-Else(后三条指令是条件的);
  • ITTEE:If-Then-Then-Else-Else(后四条指令是条件的);

IT块中的每条指令必须指定相同或逻辑相反的条件后缀。意思是,如果使用ITE,那么前两个指令必须有相同的后缀,而第三个必须是逻辑相反的后缀。下面是 ARM 参考手册中的一些示例,说明了这些逻辑:

ITTE   NE           ; 接下来的3条指令都是有条件的。
ANDNE  R0, R0, R1   ; ANDNE不更新条件标志。
ADDSNE R2, R2, #1   ; ADDSNE更新条件标志。
MOVEQ  R2, R3       ; 有条件的移动
​
ITE    GT           ; 接下来的2条指令都是有条件的。
ADDGT  R1, R0, #55  ; 条件满足大于时进行相加。
ADDLE  R1, R0, #48  ; 条件不满足大于时进行相加。
​
ITTEE  EQ           ; 接下来的4条指令都是有条件的。
MOVEQ  R0, R1       ; 有条件的MOV
ADDEQ  R2, R2, #10  ; 有条件的ADD
ANDNE  R3, R3, #1   ; 有条件的AND
BNE.W  dloop        ; 分支指令只能在IT块的最后一个指令中使用。

错误示例:

IT     NE           ; 下一条指令是条件的。
ADD    R0, R0, R1   ; 语法错误,不是有条件的指令。

下面是条件代码和相反代码:

现在使用以下代码来测试:

.syntax unified    @ 非常重要!
.text
.global _start
​
_start:.code 32add r3, pc, #1   @ PC的值加1并存储到R3。bx r3            @ 跳转到R3中的地址处,并切换运行模式 ->切换到Thumb模式,因为R3最低有效位(LSB) = 1。
​.code 16         @ Thumb模式cmp r0, #10      ite eq           @ 如果R0等于10...addeq r1, #2     @ ... 那么 R1 = R1 + 2addne r1, #3     @ ... 否则 R1 = R1 + 3bkpt

.code 32

示例中的代码开始在ARM模式下,第一条指令将PC中的地址值加1并存储到R3,然后bx指令跳转到R3中的地址位置,并且模式切换成Thumb模式,因为R3中的值最低有效位为1(0不切换)。为此使用bx(分支+交换)非常重要。

.code 16

Thumb模式下,首先比较R010,结果将负数位N置位(0 - 10 = -10)。之后使用If-Then-Else块,因为零位Z(Zero)没有被置位所以ADDEQ指令被跳过,然后因为结果不相等所以执行ADDNE指令。

GDB 中单步执行此代码会干扰结果,因为你要在 ITE 块中执行这两个指令。 但是,在 GDB 中运行代码而不设置断点并单步执行每个指令将生成正确的结果设置 R1 = 3。

分支

分支(跳转)允许我们跳转到另一个代码段。当你需要跳过(或者重复)某块代码或者跳转到指定的函数的时候,分支很有用。此类情形中最佳的示例是IF和循环。先来看看IF案例。

.global main
​
main:mov     r1, #2     /* 设置初始变量a */mov     r2, #3     /* 设置初始变量b */cmp     r1, r2     /* 比较两个变量值看哪个更大 */blt     r1_lower   /* 因为R2更大(N==1),跳转到r1_lower */mov     r0, r1     /* 如果没有跳转, 例如R1的值更大(或者相等),则将R1的值存储到R0 */b       end        /* 结束 */
r1_lower:mov r0, r2         /* R1小于R2时跳转到此处, 将R2的值存储到R0 */b end              /* 结束 */
end:bx lr              /* THE END */

上面代码是比较两个初始值并返回最大值,C语言伪代码:

int main() {int max = 0;int a = 2;int b = 3;if(a < b) {max = b;}else {max = a;}return max;
}

现在再看一下怎么使用条件分支实现循环:

.global main
​
main:mov     r0, #0     /* 设置初始变量a */
loop:cmp     r0, #4     /* 比较a==4 */beq     end        /* 如果a==4,结束 */add     r0, r0, #1 /* 否则将R0中的值递增1 */b loop             /* 跳转到loop开始位置 */
end:bx lr              /* THE END */

C语言伪代码:

int main() {int a = 0;while(a < 4) {a= a+1;}return a;
}

B、BX、BLX指令

有三种类型的分支指令:

  • 普通分支(B)

    • 简单的跳转到一个函数。
  • 带链接的跳转(BL)

    • 将PC+4的值保存到LR寄存器,然后跳转。
  • 带状态切换的跳转(BX)和带状态切换及链接的跳转(BLX)

    • 与B和BL一致,只是添加了工作状态的切换(ARM模式-Thumb模式)。
    • 需要寄存器作为第一个操作数。

BX、BLX用来切换ARM模式到Thumb模式。

.text
.global _start
​
_start:.code 32         @ ARM modeadd r2, pc, #1   @ put PC+1 into R2bx r2            @ branch + exchange to R2
​.code 16          @ Thumb modemov r0, #1

这里的技巧是获得当前PC的值,加1然后保存到一个寄存器,然后跳转(并且切换状态模式)到这个寄存器内的地址。可以看到加指令(add r2, pc, #1)获取到有效的PC地址值(当前PC内的值+8=0x805C)然后加1(0x805C + 1 = 0x805D)。接下来,我们跳转的地址( 0x805D = 10000000 01011101)最低有效位为1,那么意味着地址不是4字节(32bit)对齐的。跳转到这样的地址不会导致非对齐问题。在GDB中运行的样子(含GEF):

注意上面的gif图片是在低版本的GEF下创建的,所以你的显示界面可能不一样,但是逻辑是一样的。

条件分支

分支也可以有条件地执行,用于在满足特定条件时跳转到函数。我们看一个使用BEQ应用条件分支的例子,这是一段没太有用的汇编代码,只不过是在寄存器等于特定值时将一个值移动到寄存器并跳转到另一个函数的过程。

.text
.global _start
​
_start:mov r0, #2mov r1, #2add r0, r0, r1cmp r0, #4beq func1add r1, #5b func2
func1:mov r1, r0bx  lr
func2:mov r0, r1bx  lr

<end>

arm b bl 地址无关码_ARM汇编语言入门(六)相关推荐

  1. arm b bl 地址无关码_ARM_异常和中断

    ARM_异常和中断 问题1.中断向量表为于存储器的什么位置? ARM7系列,除ARM720T可以放高端地址,ARM9或更高都放高端地址上. 2.FIQ或IRQ异常返回指令是什么? 答案见下面.... ...

  2. arm b bl 地址无关码_32位和64位下的arm_pwn初探

    32位和64位下的arm_pwn初探 前言: pwn的学习之路一直在进行,今天看了arm_pwn,搞环境就搞了半天,琢磨工具使用到做题,这里总结下,希望能帮助到大家,少走一点弯路,后期有机会继续更新. ...

  3. arm b bl 地址无关码_海边同居有甜有虐,又一部BL日剧来了

    关注公众号日剧部屋,每天都有日剧看 最近BL剧特别多,<到了30岁还是处男,就会变成魔法师>很多人都在苦苦等着每周的更新吧,本季还有一部BL剧,Kis-My-Ft2两位成员玉森裕太和宫田俊 ...

  4. 地址有关码和地址无关码

    几个地址的说明:    (cpu看来)    (程序员看来) 1.运行地址<---->链接地址 2.加载地址<---->存储地址 他们对应等价,只是从不同的角度说. 进一步阐述 ...

  5. .jsp后缀语言_ARM汇编语言入门(三)

    Part 3 ARM指令集 ARM模式和Thumb模式 ARM处理器主要有两种工作模式(先不算Jazelle)-ARM状态和Thumb状态.这些状态模式与权限级别无关,它们主要区别是指令集,在ARM模 ...

  6. 移植 u-boot-2020.07 到 iTOP-4412(二)地址相关码 boot

    文章目录 前言 一.重新编写脚本 1. init_env.sh 2. build.sh 3. sdflush.sh 二.spl 启动流程 1. start.S 2. board_init_f() 2. ...

  7. ARM 汇编语言入门

    [翻译]二进制漏洞利用(二)ARM32位汇编下的TCP Bind shell:https://bbs.pediy.com/thread-253511.htm ARM汇编语言入门 From:ARM汇编语 ...

  8. Cortex-M3 动态加载一(地址无关代码实现)

    这篇文章是自己疑惑究竟地址无关性是如何实现,然后查看汇编和CPU指令手册,最后分析解除自己疑惑的,高手不要鄙视,哈哈. 编译C代码时候需要制定--acps/ropi选项,如下例子: 1 void Sy ...

  9. 重定位——重定位的简介与操作(涉及位置无关码)

    以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除. 参考博客:位置无关码.位置有关码 - biaohc - 博客园 一.链接地址与运行地址 1.链接地址 链接地址,是指程序员通过Makef ...

最新文章

  1. apache日志分析简介
  2. Editplus下载、安装并最佳配色方案(强烈推荐)
  3. SingleR包注释单细胞数据
  4. 浅谈Android组件化
  5. 软件官网与memcached介绍
  6. list中的linkedlist的用法
  7. 【机器学习基础】Python机器学习入门指南(全)
  8. pmp每日三题(2022年2月21日)
  9. Verilog定义计算位宽的函数clogb2
  10. chrome面板介绍
  11. java 抽象类语法_JAVA基础语法8--多态/抽象类/抽象方法
  12. MySQL乱码问题如何排查
  13. 百度seo排名规则_百度seo排名优化要点讲解(已帮助5184人)
  14. dtreeviz 画树模型
  15. Centos6.7 64位安装配置kvm虚拟化
  16. 如何一条命令查询笔记本电池损耗情况-生成报告
  17. 愚你相遇,好幸运:遇见你,遇见了最好的自己
  18. 今年大厂新孵化的app们,让我开眼了
  19. 模电-常见符号-中英文全称
  20. Nodejs+express+vue+Elementui酒店客房管理系统

热门文章

  1. 查询手机号段对应地区编码_2020陕西专升本考试今日起查询成绩啦
  2. ImageLoader实现图片异步加载
  3. Python爬虫实现:三连文章参与抽奖
  4. OFD文件结构--Signatures.xml
  5. Lambda 表达式详解~Stream Pipelines
  6. Effective Java~9. try-with-resource 优先于 try-catch
  7. 使用IDA Pro动态调试SO文件
  8. 关于高考报志愿的一些规划建议
  9. 王者荣耀服务器维护bug,8月23日王者荣耀ios版更新一直显示维护是什么情况?更新出现bug 附处理方法...
  10. 软件工程 之 画扇面