IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> ARM汇编教程四 -> 正文阅读

[嵌入式]ARM汇编教程四

预备知识

1.关于ARM架构

ARM架构,过去称作高级精简指令集机器(英语:Advanced RISC Machine,更早称作Acorn精简指令集机器,AcornRISC Machine),是一个精简指令集(RISC)处理器架构家族,其广泛地使用在许多嵌入式系统设计。由于节能的特点,其在其他领域上也有很多作为。ARM处理器非常适用于移动通信领域,匹配其主要设计目标为低成本、高性能、低耗电的特性。另一方面,超级计算机消耗大量电能,ARM同样被视作更高效的选择。安谋控股开发此架构并授权其他公司使用,以供他们实现ARM的某一个架构,开发自主的系统单片机和系统模块(system-on-module,SoC)。

2.关于汇编语言

汇编语言(英语:assembly language)是一种用于电子计算机、微处理器、微控制器,或其他可编程器件的低级语言。在不同的设备中,汇编语言对应着不同的机器语言指令集。 一种汇编语言专用于某种计算机系统结构,而不像许多高级语言,可以在不同系统平台之间移植。

3.树莓派安装参考

link

实验目的

通过该实验了解ARM汇编基础语法,这是我们学习ARM下的漏洞利用程序编写的基础。

实验环境

服务器:Ubuntu IP地址:随机分配
测试文件请在实验机内下载使用:http://tools.hetianlab.com/tools/T052.zip
启动树莓派命令:

$ qemu-system-arm -kernel ~/qemu_vms/qemu-rpi-kernel/kernel-qemu-4.4.34-jessie -cpu arm1176 -m 256 -M versatilepb -serial stdio -append "root=/dev/sda2 rootfstype=ext4 rw" -hda ~/qemu_vms/rasbian.img -redir tcp:5022::22 -no-reboot

SSH连接树莓派:

$ ssh pi@127.0.0.1 -p 5022

pi账户密码raspberry。

实验步骤一

任务描述:学习条件指令。
当特定条件满足时,借助条件指令, 通过跳转(分支)或执行某些特定指令来控制程序的流动方向。相关条件被描述为CPSR寄存器中的特定位的状态,这些位根据指令计算后的结果实时改变。比如,如果我们比较两个数并且他们相等,就将零标志位置位(Z=1),因为在系统底层发生了a-b=0。在这个例子里两个数是相等的,但如果第一个数字比第二个大,会得出大于结论。而相反的情况下得出小于结论。当然还有很多其他的条件,比如小于等于(LE),大于等于(GE)等等。
下表列出了可能的条件指令,他们的含义以及被检测的状态标志位:
在这里插入图片描述
结合上表,我们看段demo:

.global main
main:
mov     r0, #2      /* setting up initial variable */
cmp     r0, #3      /*  R0与数字3比较,2小于3,所以N位置1*/
addlt   r0, r0, #1  /*   如果R0比3小就将R0自增1*/
cmp     r0, #3      /*  再次比较r0和3,此时2+1=3,所以Z标志位置1,N置0 */
addlt   r0, r0, #1  /*  如果r0小于3给r0自增1*/
bx      lr

结合注释,就很好理解了。
代码中,第一个CMP比较指令执行后触发了N标志位的置位(2-3=-1),这表明r0的值比数字3要小。随后,由于条件满足,所以执行了addlt指令。再次比较r0和3,此时2+1=3,所以Z标志位置1,N置0,此时条件不成立,结果就是第二个addlt没有执行,r0也没改变,程序退出并返回结果3。
接下来我们看看Thumb模式下的条件执行:
注意,只有在特定版本中(Thumb-2)才能执行条件执行指令。
语法结构:IT{x{y{z}}}cond(注:xyz指IT后最多再跟三个大写字母,大写字母可以是T,可以是E,T就是then,E就是else)。
cond规定了执行IT语句块里的第一条指令需要满足的条件。
x规定了执行的IT语句块中第二条指令需要满足的条件。
y规定了执行IT语句块里的第三条指令需要满足的条件。
z规定了执行IT语句块里的第四条指令需要满足的条件。
IT指令集的结构是:“IF-Then-(Else)”,它的语法结构由两个字母构成:
IT代表If-Then(下一条指令是条件指令)。
ITT代表If-Then-Then(接下来的两条指令是条件指令)。
ITE代表If-Then-Else(接下来的两条指令是条件指令)。
ITTE代表If-Then-Then-Else(接下来的三条指令是条件指令)。
ITTEE代表If-Then-Then-Else-Else(接下来的四条指令是条件指令)。
IT语句块内的每个指令必须指定一个条件后缀,该条件后缀要么相同要么在逻辑上相反。这意味着,如果使用了ITE,第一和第二指令(If-Then)必须具有相同的条件后缀,而第三条指令(else语句)必须和前面两条语句逻辑相反。
下面是ARM参考是手册下的部分指令,已经给出的中文注释:

ITTE   NE           ;  接下来的三条指令是条件指令
ANDNE  R0, R0, R1   ;  ANDNE不更新条件标志位
ADDSNE R2, R2, #1   ;  ANDNE更新条件标志位
MOVEQ  R2, R3       ;  条件赋值指令 
ITE    GT           ;  下面两条指令是条件指令
ADDGT  R1, R0, #55  ;  如果GT为1执行条件的相加指令
ADDLE  R1, R0, #48  ;  如果GT为0执行的条件相加指令
ITTEE  EQ           ;  下面四条指令是条件指令
MOVEQ  R0, R1       ;  条件赋值指令
ADDEQ  R2, R2, #10  ;  条件相加指令
ANDNE  R3, R3, #1   ;  条件与指令
BNE.W  dloop        ;  条件分支指令只能用于IT语句块的结尾

一个典型的错误例子是这样子的:

IT     NE           ;  下面一条不是条件执行指令
ADD    R0, R0, R1   ;  语法错误:IT语句块中没有使用条件执行指令

以下总结了条件指令和逻辑相反的指令:
在这里插入图片描述

实验步骤二

任务描述:了解这些基础之后,我们看一下一个实例。
代码在如下,在test7.s:

.syntax unified     @ this is important!这句话很关键
.text
.global _start
_start:
.code 32
add r3, pc, #1      @ increase value of PC by 1 and add it to R3
bx r3               @ branch + exchange to the address in R3 -> switch to Thumb state because LSB = 1
.code 16            @ Thumb state
cmp r0, #10      
ite eq              @ if R0 is equal 10...
addeq r1, #2        @ ... then R1 = R1 + 2
addne r1, #3        @ ... else R1 = R1 + 3
bkpt

.code32
这段示例代码以ARM状态开始。第一条指令将PC里的地址值加1后传送给r3,接着跳转到分支地址R3。这样做会导致切换到Thumb状态,因为LSB(最低有效位)是1,因此不是4个字节。使用bx指令(分支+切换)达成这个目标,分支指令执行完成后,T(Thumb)标志位被置位,我们现在处于Thumb模式。
.code16
Thumb模式下首先用R0和立即数10比较。这会将N标志位置位(0-10=-10)。接着我们使用了一个 If-Then-Else语句块。这个块会跳过ADDEQ因为Z(零)标志位没有被置位,由于结果等于10,是NE的(not equal不等于0的),接着会执行ADDNE指令。
这里在Gdb中单步步过这段指令会把结果搞乱,因为在ITE语句块中两条语句都执行了。所以我们不设置断点运行代码,并且单步步过每条指令会产生正确的结果:R1=3。
编译链接:
在这里插入图片描述
使用gdb调试:
在这里插入图片描述
直接run查看寄存器r1的值,确实为3:
在这里插入图片描述

实验步骤三

任务描述:学习分支指令。
分支指令(也叫做跳转)允许我们跳转到另一个代码段运行。当我们需要跳过(或者重复)执行代码段或者跳向特定功能的函数时就显得尤为有用。这方面最好的范例就是IFs和循环。我们先看看IF是什么情况。
示例代码如下:

.global main
main:
mov     r1, #2     /* setting up initial variable a */
mov     r2, #3     /* setting up initial variable b */
cmp     r1, r2     /* comparing variables to determine which is bigger */
blt     r1_lower   /* jump to r1_lower in case r2 is bigger(N==1) */
mov     r0, r1     /* if branching/jumping did not occur, r1is bigger (or the same) so store r1 into r0 */
b       end        /* proceed to the end */
r1_lower:
mov r0, r2         /* We ended uphere because r1 was smaller than r2, so move r2 into r0 */
b end              /* proceed tothe 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;
}

在test8.s:
在这里插入图片描述
编译链接后使用gdb调试。
在main下断点,然后run:
在这里插入图片描述
可以看到接下来要执行的两条语句分别是给r1,r2赋值:
在这里插入图片描述
第三条是进行比较r1,r2的大小。
我们使用nexti 2直接来到赋值之后的情况。
可以看到此时出现了分支:
在这里插入图片描述
分别是r1大于r2,和r1小于r2的情况,会把大的那个寄存器的值赋给r0。
继续nexti:
在这里插入图片描述
可以看到现在判断出来r2比较大,所以下一条指令会把r2的值赋给r0。
nexti后此时查看r0的值,确实和r2的值一样,为0x3。
在这里插入图片描述
我们再来看一个例子。
代码如下:

.global main
main:
mov    r0, #0     /* setting up initial variable a */
loop:
cmp    r0, #4     /* checking if a==4 */
beq    end        /* proceeding to the end if a==4*/
add    r0, r0, #1 /* increasing a by 1 if the jump to the end did not occur */
bloop             /*repeating the loop */
end:
bxlr              /* THE END */

代码逻辑用c伪代码表示出来为:

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

代码在test9.s。
编译链接后用gdb调试,在main下断点,单步调试:
在这里插入图片描述
在这里插入图片描述
run:
在这里插入图片描述
可以看到第一条是赋0给r0,然后比较r0和4,cmp指令会执行0-4,结果不等于0,所以会Z标志会置0,或者表示为!z。
我们使用nexti 2然后查看:
在这里插入图片描述
确实cmp的结果为!z,按照逻辑,r0会自增1,表示在汇编里就是add r0,r0,#1。
我们接下来同样nexti 2:
在这里插入图片描述
可以看到r0为0x1,后续的逻辑还是一样的,可以自行调试验证,此处不再演示。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-12 23:37:07  更:2021-10-12 23:38:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:59:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码