使用ARM汇编常用指令指令实现在地址0x80006000 存储一个字符串(ABCD123)

ADC将把两个操作数加起来并把结果放置到目的寄存器中。它使用一个进位标志位这样就可以做比 32 位大的加法。下列例子将加两个 128 位的数
128
位结果: 寄存器 012、和 3第一个

洳果如果要做这样的加法,不要忘记设置 S 后缀来更改进位标志

ADD将把两个操作数加起来,把结果放置到目的寄存器中操作数 1 是一个寄存器,操作数 2 可以是一个寄存器被移位的寄存器,或一个立即值:

加法可以在有符号和无符号数上进行

AND将在两个操作数上进行逻辑与,把結果放置到目的寄存器中;对屏蔽你要在上面工作的位很有用操作数 1 是一个寄存器,操作数 2 可以是一个寄存器被移位的寄存器,或一個立即值:

BIC是在一个字中清除位的一种方法与 OR 位设置是相反的操作。操作数 2 是一个 32 位位掩码(mask)如果如果在掩码中设置了某一位,则清除这┅位未设置的掩码位指示此位保持不变。

EOR将在两个操作数上进行逻辑异或把结果放置到目的寄存器中;对反转特定的位有用。操作数 1 昰一个寄存器操作数 2 可以是一个寄存器,被移位的寄存器或一个立即值:

EOR 真值表(二者不同则结果为 1):

MOV从另一个寄存器、被移位的寄存器、戓一个立即值装载一个值到目的寄存器。你可以指定相同的寄存器来实现 NOP 指令的效果你还可以专门移位一个寄存器:

如果 R15 是目的寄存器,將修改程序计数器或标志这用于返回到调用代码,方法是把连接寄存器的内容传送到 R15:

MVN从另一个寄存器、被移位的寄存器、或一个立即值裝载一个值到目的寄存器不同之处是在传送之前位被反转了,所以把一个被取反的值传送到一个寄存器中这是逻辑非操作而不是算术操作,这个取反的值加 1 才是它的取负的值:

OR将在两个操作数上进行逻辑或把结果放置到目的寄存器中;对设置特定的位有用。操作数 1 是一個寄存器操作数 2 可以是一个寄存器,被移位的寄存器或一个立即值:

OR 真值表(二者中存在 1 则结果为 1):

SUB用操作数two 减去操作数one,把结果放置到目嘚寄存器中操作数 1 是一个寄存器,操作数 2 可以是一个寄存器被移位的寄存器,或一个立即值:

反向减法可以在有符号或无符号数上进行

RSC : 带借位的反向减法

同于SBC,但倒换了两个操作数的前后位置

SBC做两个操作数的减法,把结果放置到目的寄存器中它使用进位标志来表示借位,这样就可以做大于 32 位的减法SUBSBC生成进位标志的方式不同于常规,如果需要借位则清除进位标志所以,指令要对进位标志进行一個操作 - 在指令执行期间自动的反转此位

SUB用操作数one 减去操作数 two,把结果放置到目的寄存器中操作数 1 是一个寄存器,操作数 2 可以是一个寄存器被移位的寄存器,或一个立即值:

减法可以在有符号和无符号数上进行

shifter)。你还可以使用桶式移位器影响在 LDR/STR 操作中的变址值

译注:移位操作在 ARM 指令集中不作为单独的指令使用,它是指令格式中是一个字段在汇编常用指令语言中表示为指令中的选项。如果数据处理指令的第二个操作数或者单一数据传送指令中的变址是寄存器则可以对它进行各种移位操作。如果数据处理指令的第二个操作数是立即徝在指令中用 8 位立即值和 4 位循环移位来表示它,所以对大于 255 的立即值汇编常用指令器尝试通过在指令中设置循环移位数量来表示它,洳果不能表示则生成一个错误在逻辑类指令中,逻辑运算指令由指令中 S 位的设置或清除来确定是否影响进位标志而比较指令的 S 位总是設置的。在单一数据传送指令中指定移位的数量只能用立即值而不能用寄存器

下面是给不同的移位类型的六个助记符:

ASLLSL是等同的,可以洎由互换

你可以用一个立即值( 0 31)指定移位数量,或用包含在 0 31 之间的一个值的寄存器指定移位数量

接受 Rx 的内容并按用‘n’或在寄存器 Rn 中指定的数量向高有效位方向移位。最低有效位用零来填充除了概念上的第 33 (就是被移出的最小的那位)之外丢弃移出最左端的高位,洳果逻辑类指令中 S 位被设置了则此位将成为从桶式移位器退出时进位标志的值。

它在概念上与左移相对把所有位向更低有效位方向移動。如果逻辑类指令中 S 位被设置了则把最后被移出最右端的那位放置到进位标志中。它同于 BASIC register = value >>>

类似于 LSR但使用要被移位的寄存器(Rx)的第 31 位嘚值来填充高位,用来保护补码表示中的符号如果逻辑类指令中 S

循环右移类似于逻辑右移,但是把从右侧移出去的位放置到左侧如果邏辑类指令中 S 位被设置了,则同时放置到进位标志中这就是位的循环。一个移位量为 32 的操作将导致输出与输入完全一致因为所有位都被移位了 32 个位置,又回到了开始时的位置!

这是一个 ROR#0 操作它向右移动一个位置 - 不同之处是,它使用处理器的进位标志来提供一个要被迻位的 33 位的数量

这两个指令与普通指令在对操作数的限制上有所不同:

1.  给出的所有操作数、和目的寄存器必须为简单的寄存器。

2.  你不能对操作数 2 使用立即值或被移位的寄存器

3.  目的寄存器和操作数 1 必须是不同的寄存器。

4.  最后你不能指定 R15 为目的寄存器。

MLA的行为同于MUL但它把操作数 3 的值加到结果上。这在求总和时有用

MUL提供 32 位整数乘法。如果操作数是有符号的可以假定结果也是有符号的。

译注:CMP CMP 是算术指囹TEQ TST 是逻辑指令。把它们归入一类的原因是它们的 S 位总是设置的就是说,它们总是影响标志位

CMN同于CMP,但它允许你与小负值(操作数 2 的取负的值)进行比较比如难于用其他方法实现的用于结束列表的 -1。这样与 -1 比较将使用:

CMP允许把一个寄存器的内容如另一个寄存器的内容或立即值进行比较更改状态标志来允许进行条件执行。它进行一次减法但不存储结果,而是正确的更改标志标志表示的是操作数 1 比操作數 2 如何(大小等)。如果操作数 1 大于操作操作数 2则此后的有 GT 后缀的指令将可以执行。明显的你不需要显式的指定S后缀来更改状态标志... 如果伱指定了它则被忽略。

TEQ类似于TST区别是这里的概念上的计算是 EOR 而不是 AND。这提供了一种查看两个操作数是否相同而又不影响进位标志(不象CMP那樣)的方法加上P后缀的TEQ还可用于改变

TST类似于CMP,不产生放置到目的寄存器中的结果而是在给出的两个操作数上进行操作并把结果反映到状態标志上。使用TST来检查是否设置了特定的位操作数 1 是要测试的数据字而操作数 2 是一个位掩码。经过测试后如果匹配则设置 Zero 标志,否则清除它象CMP 那样,你不需要指定S后缀

B是最简单的分支。一旦遇到一个 B指令ARM 处理器将立即跳转到给定的地址,从那里继续执行

注意存儲在分支指令中的实际的值是相对当前的 R15 的值的一个偏移量;而不是一个绝对地址。

它的值由汇编常用指令器来计算它是 24 位有符号数,咗移两位后有符号扩展为 32 位表示的有效偏移为 26 位(+/- 32 M)。

在其他处理器上你可能经常见到这样的指令:

在 ARM 处理器上,它们将变成下面这些东西:

這不是一个很好的例子但你可以构想如何更好的去条件执行而不是分支。另一方面如果你有大段的代码或者你的代码使用状态标志,那么你可以使用条件执行来实现各类分支: 这样一个单一的简单条件执行指令可以替代在其他处理器中存在的所有这些分支和跳转指令

BL : 带連接的分支

BL是另一个分支指令。就在分支之前在寄存器 14 中装载上 R15 的内容。你可以重新装载 R14 到 R15 中来返回到在这个分支之后的那个指令

它昰子例程的一个基本但强力的实现。它的作用在屏幕装载器 2 (例子 4)中得以很好的展现...

...在这里我们见到在装载器循环之前调用了三个子例程接着,一旦满足了条件执行就在循环中调用了 read_byte 子例程

ARM 处理器的一个非常特殊的特征是它的条件执行。我们指的不是基本的如果进位则分支ARM 使这个逻辑阶段进一步深化为如果进位则 XXX- 这里的 XXX 是任何东西。

为了举例下面是 Intel 8086 处理器分支指令的一个列表:

作为对比,ARM 处理器只提供叻:

但 ARM 提供了条件执行你可以不受这个表面上不灵活的方式的限制:

当你发现所有 Bxx 指令实际上是同一个指令的时候,紧要关头就到了

接着伱会想,如果你可以在一个分支指令上加上所有这些条件那么对一个寄存器装载指令能否加上它们? 答案是可以。

下面是可获得的条件代碼的列表:

如果一次比较之后设置了 Z 标志

如果一次比较之后清除了 Z 标志。

如果在一次算术操作之后设置了 V 标志计算的结果不适合放入一個 32bit 目标寄存器中。

如果清除了 V 标志与 VS 相反。

如果一次比较之后设置了 C 标志清除了 Z 标志

LS : 低于或同于(无符号)

如果一次比较操作之后清除叻 C 标志设置了 Z 标志。

如果一次算术操作之后清除了 N出于定义‘正号’的目的,零是正数的原因是它不是负数...

如果一次算术操作之后设置了 N 标志

如果一次算术操作或移位操作之后设置了 C 标志,操作的结果不能表示为 32bit你可以把 C 标志当作结果的第 33 位。

GE : 大于或等于(有符号)

如果一次比较之后...设置了 N 标志设置了 V 标志
清除了 N 标志清除了 V 标志

如果一次比较之后...设置了 N 标志设置了 V 标志
清除了 N 标志清除了 V 标志
並且...清除了 Z 标志。

LE : 小于或等于(有符号)

如果一次比较之后...设置了 N 标志清除了 V 标志
清除了 N 标志设置了 V 标志
并且...设置了 Z 标志

如果一次比较の后...设置了 N 标志清除了 V 标志。
清除了 N 标志设置了 V 标志

缺省条件,所以不用明显声明

不是特别有用,它表示应当永远不执行这个指囹是穷人的 NOP
包含 NV 是为了完整性(与 AL 相对)你不应该在你的代码中使用它。

有一个在最后的条件代码 S它以相反的方式工作。当用于一个指令的时候导致更改状态标志。这不是自动发生的 - 除非这些指令的目的是设置状态例如:

第一个例子是一个基本的加法(把 R1 的值增加到 R0),咜不影响状态寄存器

第二个例子是同一个加法,只不过它导致更改状态寄存器

最后一个例子是同一个加法,更改状态寄存器不同在於它是一个有条件的指令。只有前一个操作的结果是 EQ (如果设置了 Z 标志)的时候它才执行

下面是条件执行的一个工作中的例子。你把寄存器 0 與存储在寄存器 10 中内容相比较

如果不等于 R10,则调用一个软件中断增加它并分支回来再次做这些。否则清除 R10 并返回到调用它的那部分代碼(它的地址存储在 R14)

\ 条件执行的一个例子

Econet_DoImmediate的编号。不要字面的接受它这只是一个例子!

R14。关于寄存器装载和存储的更多信息请参阅

·         最後,这些寄存器很有可能被一个 SWI 调用所占用(依赖于在调用期间执行的代码)所以你最好把你的重要的寄存器压入栈中,以后在恢复它们

這是一个简单的设施,但可能是最常用的多数操作系统设施是用 SWI 提供的。没有 SWI 的 RISC OS 是不可想象的

SWI 表示 Software Interrupt。在 RISC OS  中使用 SWI 来访问操作系统例程或苐三方生产的模块许多应用使用模块来给其他应用提供低层外部访问。

在以这种方式使用的时候SWI 允许操作系统拥有一个模块结构,这意味着用来建立完整的操作系统的所需的代码可以被分割成许多小的部分(模块)和一个模块处理程序(handler)

当 SWI 处理程序得到对特定的例程编号的┅个请求的时候,它找到这个例程的位置并执行它并传递(有关的)任何数据。

首先查看一下如何使用它一个 SWI 指令(汇编常用指令语言)看起來如下:

这些指令实际上是相同的,将被汇编常用指令成相同的指令唯一的不同是第二个指令使用一个字符串来表示 SWI 编号 &02。

在使用采用了芓符串编号的程序的时候在执行之前首先查找这个字符串。

在这里我们不想处理字符串因为它不能给出它要进行什么的一个真实表示。它们通常用于增进一个程序的清晰程度但不是实际执行的指令。

让我们再次看一下第一个指令:

这是什么意思? 字面的意思是进入 SWI 处理程序并传递值 &02在 RISC OS 中这意味着执行编号是 &02 的例程。

它是如何这么作的? 它如何传递 SWI 编号和进入 SWI 处理程序?

如果你查看内存的开始 32 字节(位于 0-&1C)并反汇編常用指令它们(查开实际的 ARM 指令)你将见到如下:

除了第一个和最后一个指令之外(它们是特殊情况)你见到的都是把一个新值装载到 PC (程序计数器)嘚指令它们告诉计算机到哪里去执行下一个指令。

还展示了这个值是从内存中的一个地址接受来的(你可以在 !Zap 主菜单上使用“Read Memory”选项去洎己查看一下。)

这看起来好象与 SWI 没多少关系下面做进一步的说明。

一个 SWI 所做的一切就是把模式改变成超级用户并设置 PC 来执行在地址 &08 处的丅一个指令!

把处理器转换到超级用户模式会切换掉两个寄存器 r13 和 r14 并用 r13_svc 和 r14_svc 替换它们

在进入超级用户模式的时候,还把 r14_svc 设置为在这个 SWI 指令之後的地址

这个实际上就象一个连接到地址 &08 的分支指令(BL &08),但带有用于一些数据(SWI 编号)的空间

象我说过的那样,地址 &08 包含跳转到另一个地址嘚一个指令就是实际的 SWI 程序的地址!

此时你可能会想“稍等一会! 还有 SWI 编号呢?”。实际上处理器忽略这个值本身SWI 处理程序使用传递来的 r14_svc 的徝来获取它。

下面是完成它的步骤(在存储寄存器 r0-r12 之后):

2.  把这个指令装载到一个寄存器

4.  使用这个值来找到要被执行的代码的例程的地址(使用查找表等)。

6.  使处理器离开超级用户模式

7.  跳转到这个例程的地址。

; SWI 包含需要的例程在位 8-23 中和数据(如果有的话)在位 0-7 中

 ; 保存工作寄存器和返囙地址。

 ; 恢复工作空间并返回、恢复处理器模式和标志。

这就是 SWI 指令的基本处理步骤

}

数据加载与存储指令实验

寻址方式并能自己动手写一些简单小程序。

、能够运行程序并进行简单分析

——用于字和无符号字节

加载指定地址的字数据到

中的字数据到指萣的地址单元中

加载指定地址的字节数据到

中的最低字节数据到指定的地址单元中。

即使处理器是在特权模式下存储系统也将访问看荿处理器是在用户模式下,

式下无效不能与前索引偏移一起使用

。地址部分可用的形式有

的值作为传送数据的地址如:

中。其结果作為传送数据的存储器地址若使用后缀“

程序相对偏移是前索引形式的另一种版本。

前索引指令不能使用后缀“

。在数据传送后将偏迻量

)分析单寄存器操作,并学会简化给出的代码同时实现相同的效果;

)使用多寄存器操作指令:

实验上面单寄存器操作所实现的功能;

)给出实验所提供的堆栈操作的代码执行过程的详细分析;

写成的数码管显示用相应的汇编常用指令实现同样功能。

)单寄存器操作玳码如下:

}

嵌入式系统从大的方面分为(嵌叺式系统硬件平台)和(嵌入式

嵌入式系统核心是嵌入式处理器

处理器支持的数据类型中,字节为(

指令用于从(存储器)中将一个

位嘚字数据传送到(目的

指出下面各条指令的寻址方式

}

我要回帖

更多关于 汇编常用指令 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信