arm 汇编 指令看不太懂,高手解释下

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了arm 汇编 指令看不太懂,高手解释下相关的知识,希望对你有一定的参考价值。

举例说明一下: LDR r0,=|Image $ $ RO $ $ Limit| LDR r1,=|Image $ $ RW $ $ Base| LDR r3,=|Image $ $ ZI $ $ Base| CMP r0,r1 BEQ %F1 CMP r1,r3 LDRCC r2,[r0],#4 STRCC r2,[r1],#4 BCC %B0 LDR r1,|Image $ $ ZI $ $Limit| MOV r2,#0 CMP r3,r1 STRCC r2,[r3],#4 BCC %B2 才刚学,这些代码看不大懂,希望高手指点一下 BEQ %F1 LDRCC r2,[r0],#4 STRCC r2,[r1],#4 BCC %B0 这些是什么意思?要是都能说说那就更好了。

参考技术A 的确,书本上都有!
BEQ
相等则跳转,B跳转,EQ相等(,前面有CMP)
LDRCC
小于则装载内存数据到寄存器,LDR装载,CC小于
STRCC
BCC类似
<助记符><执行条件>S
<Rd>,<Rn>,第2操作数
有S则表示影响CPSR寄存器的值
条件码助记符:
EQ
相等
NE
不相等
CS/HS
无符号数大于或等于
CC/LO
无符号数小于
MI
负数
PL
正数或零
VS
溢出
VC
没有溢出
HI
无符号数大于
LS
无符号数小于或等于
GE
有符号数大于或等于
LT
有符号数小于
GT
有符号数大于
LE
有符号数小于或等于
AL
无条件执行,跟不写一样
|Image$$RO$$Limit|:表示RO区末地址后面的地址,即RW数据源的起始地址
|Image$$RW$$Base|:RW区在RAM里的执行区起始地址,也就是编译器选项RW_Base指定的地址。
|Image$$ZI$$Base|:ZI区在RAM里面的起始地址
|Image$$ZI$$Limit|:ZI区在RAM里面的结束地址后面的一个地址

ARM汇编中LDR伪指令和LDR指令

ARM汇编语言是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/s tr 指令。

比如想把数据从内存中某处读取到寄存器中,只能使用ldr比如:

 

 ldr r0, 0x12345678

就是把 0x12345678这个地址中的值存放到r0中 。 而mov不能实现这个功能,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中, 这个和x86这种CISC 架构 的芯片区别最大的地方。x86中没有ldr这种指令,因为x86mov指令可以将数据从内存中移动到寄存器中。

 

另外还有一个就是ldr伪指令,虽然ldr伪指令和ARMldr指令很像,但是作用不太一样。 ldr伪指令可以在立即数前加上=,以表示把一个值(一般是一个地址)写到某寄存器中,比如:

 

 ldr r0, =0x12345678

这 样,就把0x12345678这个值写到r0中了 。所以,ldr伪指令和mov是比较相似的。只不过mov指令限制了立即数的长度为8位,也就是不能超过 512。而ldr伪指令没有这个限制。如果使用ldr伪指令时,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令是被转换为mov指令 的。                           其实ldr指令可以装载一个32bit立即数的说法并不确切,因为实际上并不是这一条语句装载了一个32bit立即数,真正的汇编代码是将某个地址的值传递给r1,就是说需要一个地址存放0x12345678这个立即数。而且如果这个立即数可以用mov指令的形式来表达,会被编译器实际用mov来代替比 如:

ldr r1,=0x10

会变成

mov r1,#0x10

         综述所述:ldr伪指令用于加载32位的立即数或一个地址值到指定寄存器 。在汇编编译源程序时,ldr伪指令被编译器替换成一条合适的指令。若加载的常数未超出mov或 mv n的范围,则使用movmvn指令代替该ldr伪指令,否则汇编器将常量放入文字池,并使用一条程序相对偏移的ldr指令从文字池读出常量。          ldr伪指令和ldr指令不是一个同东西。 http://www.linuxso.com/linuxrumen/16306.html

ADR这是一条小范围的地址读取 伪指令 ,它将基于PC的相对偏移的地址值读到目标寄存器中。

 

使用的格式:ADR register,exper。

 

在编译源程序时,汇编器首先计算出当前PC值(当前指令位置)到exper的距离,然后会用一条ADD或者SUB指令来替换这条伪指令,例如:ADD register,PC,#offset_to_exper

 

注意,标号exper与指令必须在同一代码段。

 

例子:adr     r0, _start  :将指定地址赋到r0

 

.........

 

_start:

 

b  _start

 

r0的值为 标号_start 与此指令的距离差 + PC值(当前指令位置)

 

ADRL:

 

这是一条中等范围的地址读取 伪指令 ,它将基于PC的相对偏移的地址值读到目标寄存器中。

 

使用的格式:ADRL register,exper。

 

在编译源程序时,汇编器会用两条合适的指令来替换这条伪指令。

 

例如:

 

ADD register,PC,offset1

 

ADD register,register,offset2

 

与ADR相比,它能读取更大范围的地址。

 

注意,标号exper与指令必须在同一代码段。

 

接下来是LDR,首先要说的是有两个家伙,他们都叫LDR

 

一个是LDR伪指令,一个是LDR指令,名字相同却不是一个东西。

 

区分的方法就是看第二个参数,如果有等号,就是伪指令。

 

LDR指令:

 

例子: ldr r0, 0x12345678 就是把0x12345678这个地址中的值存放到r0中。而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中。

 

LDR伪指令:

 

例1(立即数): ldr r0, =0x12345678

 

这样,就把0x12345678这个地址写到r0中了。所以,ldr伪指令和mov是比较相似的。只不过mov指令限制了立即数的长度为8位,也就是不能超过512。而ldr伪指令没有这个限制。如果使用ldr伪指令时,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令是被转换为mov指令的。

 

例2(标号): ldr     r0, =_start  :将指定标号的值赋给r0

 

这里取得的是标号 _start 的绝对地址,这个绝对地址(运行地址)是在链接的时候确定的。它要占用 个 32bit的空间,一条是指令,另一条是文字池中存放_start 的绝对地址。

 

这里对比一下,adr     r0, _start,和 ldr     r0, =_start

 

它们的目的是一样的,想把标签的地址给r0,区别是一个是相对地址,一个是绝对地址。目的一样,但是得到的结果 不一定 相同。结果是否相同,就要看这个PC的值,是否和链接地址相同了。

 

 

文章来源:ChinaUnix博客

以上是关于arm 汇编 指令看不太懂,高手解释下的主要内容,如果未能解决你的问题,请参考以下文章

ARM 常用汇编指令

ARM 汇编 简单介绍

ARM指令集——跳转指令

Android 图解逆向工程中ARM常用汇编指令

arm汇编—ldr加载指令,ldr伪指令

(转)关于汇编ARM指令DCD