汇编基础知识

汇编基础知识

  • arm架构简介
  • APCS规则 (ARM Procedure Call Standard)
  • 一、指令集:
      • 1.1、 add(加法)
      • 1.2、sub(减法)
      • 1.3、sbc
      • 2.1、and (按位与)
      • 2.2、orr (按位或)
      • 2.3、bic (取反后按位与) (位清零指令)
      • 2.4、eor (异或)
      • 3.1、mov(数据传送指令)
      • 3.2、mvn(反向传输指令)
      • 4.1、 lsl (逻辑左移 logical shift left)(低位填0)
      • 4.2、asl(算术左移arithmetic shift right)(低位填0)
      • 4.2、lsr (逻辑右移 logical shift right)(高位填0)
      • 4.3、asr(算术右移 arithmetic shift right)(高位用第31位值填充)
      • 4.4、ror (循环右移 rotation right)
      • 5.1、ldr(加载指令)(读内存指令)
      • 5.2、str(存储指令)(存入内存指令)
      • 5.3、ldrh (load 16bit's value from memory into register. )
      • 5.4、strh: store 16bit's value of register into memory.
      • 5.5、ldrb: load 8bit's value from memory into register.
      • 5.6、strb: store 8bit's value of register into memory.
      • 5.7、 ldm / stm
      • 5.8
    • 7 异常产生指令
      • 7.1 软中断指令 SWI
      • 7.2 断点中断指令 BKPT
    • 8 协处理指令
      • 8.1 协处理器数据操作指令 CDP
      • 8.2 协处理器数据读取指令LDC
      • 8.3 协处理器数据写入指令STC
      • 8.4 ARM微处理器到协处理器的数据传送指令MCR
      • 8.5 协处理器到ARM寄存器的数据传送指令MRC
    • 9、不重要

arm架构简介

a. 架构及特点( p28 )

RISC(精简指令集架构)

b. 寻址及存储模式(p35)

4G //2^32=4G(寻址)
两种模式:little-endian, big-endian
默认:little-endian

c. 工作模式(p1139)

usr(用户模式)

特权模式:

sys(系统模式)

异常模式:

und(未定义指令模式)
svc(管理模式)
irq(外部中断模式)
fiq(快速中断模式)
abt(数据访问终止模式)
moni
hyp

(除了用户模式(usr),其他8种称为特权模式) (除了用户模式(usr),和系统模式(sys),其他的称为异常模式)
svc,unde,abt,fiq,irq,moni,hyp (7种)

Mode changes can be made under software control, or can be caused by
an external or internal exception. (这些工作模式可以由软件控制改变,或者硬件)

d. 工作状态(p1148)

ARM 指令集 (32bit)(默认状态) Thumb 指令集 (16bit)
// cpsr可以设置 (T位可以设置)

e.立即数:(arm-linux-objdump -d *.o进行反汇编。来看机器码)
机器码的最后三个机器码,的编码规则:

如果小于255的数则直接放在低8位,
如果大于255的数,则系统会把数,循环左移动2*n位后,如果可以变为小于255的数,
则放在低8位,然后把n放在高四位
例如:e… 2ff 0xf000000f
//左移4位就小于255了,所以,n为2,


操作数:直接操作内存和寄存器的值

  1. ARM寄存器

汇编基础知识_第1张图片

APCS规则 (ARM Procedure Call Standard)

a、寄存器的使用规则:
汇编基础知识_第2张图片

R15-PC的例子:

mov lr,pc //读pc寄存器中的值放到lk中,读到的事下下一天指令的地址。 ldr pc,=hello
//伪指令;前面放的=,表示吧这个立即数写入pc寄存器,实现跳转。然后跳到hello这个函数的地址去执行, mov r1,#23

b. arm汇编指令调用函数的时候,需要保存现场和回复现场
汇编基础知识_第3张图片

解读:

首先,我们要懂,arm的栈是满递减的

一、指令集:

1.1、 add(加法)

ADD{条件}{S} 目的寄存器, 操作数1<寄存器>, 操作数2
ADD 指令用于把两个操作数相加,并将结果存放到目的寄存器中。操作数1 应是一个寄存器,操作数2可以是一个寄存器、被移位的寄存器,或一个立即数。例如:
ADD R0,R1,R2 @ R0 = R1 + R2
ADD R0,R1,#256 @ R0 = R1 + 256
ADD R0,R2,R3,LSL#1 @ R0 = R2 + (R3 << 1)

1.2、sub(减法)

SUB{条件}{S} 目的寄存器, 操作数1<寄存器>, 操作数2
SUB 指令用于把操作数1 减去操作数2,并将结果存放到目的寄存器中。操作数1 应是一个寄存器,操作数2 可以是一个寄存器、被移位的寄存器或一个立即数。该指令可用于有符号数或无符号数的减法运算。例如:
SUB R0,R1,R2 @R0 = R1 - R2
SUB R0,R1,#256 @R0 = R1 - 256
SUB R0,R2,R3,LSL#1 @R0 = R2 - (R3 << 1)

1.3、sbc

SBC{条件}{S} 目的寄存器, 操作数1<寄存器>, 操作数2
SBC 指令用于把操作数1 减去操作数2,再减去CPSR 中的C 条件标志位的反码,并将结果存放到目的寄存器中。操作数1 应是一个寄存器,操作数2 可以是一个寄存器,被移位的寄存器,或一个立即数。该指令使用进位标志来表示借位,这样就可以做大于32 位的减法,注意不要忘记设置S 后缀来更改进位标志。该指令可用于有符号数或无符号数的减法运算。例如:
SUBS R0, R3, R6 @减最低位字节,不带进位
SBCS R1, R4, R7 @减第二个字,带进位
SBCS R2, R5, R8 @减第三个字,带进位

#三句话实现了96bit减法运算,由于ARM寄存器宽度只有32bit所以分三次相减

2.1、and (按位与)

AND{条件}{S} 目的寄存器, 操作数1<寄存器>, 操作数2
AND 指令用于在两个操作数上进行逻辑与运算,并把结果放置到目的寄存器中。操作数1 应是一个寄存器,操作数2 可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于屏蔽操作数1 的某些位,或者是清零某些位。示例如下:
AND R0,R0,#3 @该指令保持R0的0、1 位,其余位清零。

2.2、orr (按位或)

ORR{条件}{S} 目的寄存器, 操作数1<寄存器>, 操作数2
ORR 指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。操作数1 应是一个寄存器,操作数2 可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于设置操作数1 的某些位为1。示例如下:
ORR R0,R0,#3 @该指令设置R0 的0、1 位,其余位保持不变。

2.3、bic (取反后按位与) (位清零指令)

BIC{条件}{S} 目的寄存器, 操作数1<寄存器>, 操作数2
BIC 指令用于清除操作数1 的某些位,并把结果放置到目的寄存器中。操作数1 应是一个寄存器,操作数2 可以是一个寄存器,被移位的寄存器,或一个立即数。操作数2 为32 位的掩码,如果在掩码中设置了某一位,则清除这一位。未设置的掩码位保持不变。示例如下:
BIC R0,R0,#%1011 @该指令清除R0 中的位0、1、和3,其余的位保持不变

2.4、eor (异或)

EOR{条件}{S} 目的寄存器,操作数1,操作数2
EOR 指令用于在两个操作数上进行逻辑异或运算,并把结果放置到目的寄存器中。操作数1 应是一个寄存器,操作数2 可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于反转操作数1 的某些位。示例如下:

EOR R0,R0,#3 @该指令反转R0 的0、1 位,其余位保持不变。

3.1、mov(数据传送指令)

MOV{条件}{S} 目的寄存器, 源操作数
MOV 指令可完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。其中S选项决定指令的操作是否影响CPSR 中条件标志位的值,当没有S时指令不更新CPSR 中条件标志位的值。示例如下:

MOV R1,R0 @将寄存器R0 的值传送到寄存器R1
MOV PC,R14 @将寄存器R14 的值传送到PC,常用于子程序返回
MOV R1,R0,LSL#3 @将寄存器R0 的值左移3位后传送到R1

3.2、mvn(反向传输指令)

MVN{条件}{S} 目的寄存器, 源操作数

MVN 指令可完成从另一个寄存器、被移位的寄存器、或将一个立即数加载到目的寄存器。与MOV 指令不同之处是在传送之前按位被取反了,即把一个被取反的值传送到目的寄存器中。其中S 决定指令的操作是否影响CPSR 中条件标志位的值,当没有S 时指令不更新CPSR 中条件标志位的值。示例如下:

MVN R0,#0 @将立即数0 取反传送到寄存器R0 中,完成后R0=-1

4.1、 lsl (逻辑左移 logical shift left)(低位填0)

通用寄存器,LSL 操作数
LSL可完成对通用寄存器中的内容进行逻辑的左移操作,按操作数所指定的数量向左移位,低位用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。示例如下:
MOV R0, R1, LSL #2 ; @将R1 中的内容左移两位后传送到R0 中。

MOV R1, #0X01
MOV R0, R1, LSL #2
MOV R2, #2
MOV R0, R1, LSL R2

4.2、asl(算术左移arithmetic shift right)(低位填0)

通用寄存器, ASL 操作数
ASL可完成对通用寄存器中的内容进行算术的左移操作,按操作数所指定的数量向左移位,低位用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。
示例如下:

MOV R1, #0X01
MOV R0, R1, ASL #2

4.2、lsr (逻辑右移 logical shift right)(高位填0)

通用寄存器, LSR 操作数

LSR 可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。示例如下:
MOV R0, R1, LSR #2 @将R1 中的内容右移两位后传送到R0 中,左端用零来填充

4.3、asr(算术右移 arithmetic shift right)(高位用第31位值填充)

通用寄存器, ASR 操作数
ASR 可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用第31 位的值来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。
示例如下:

MOV R0, R1, ASR #2 @将R1 中的内容右移两位后传送到R0 中,左端用第31 位的值来填充。

(总结,逻辑和算术移位都是填充0,只不过当算术移动的时候要注意符号位,如果是负数,则第31位为1,所以算术移位的时候,左移不影响,右移,那么高位就填充31的值)

4.4、ror (循环右移 rotation right)

通用寄存器,ROR 操作数
ROR可完成对通用寄存器中的内容进行循环右移的操作,按操作数所指定的数量向右循环移位,左端用右端移出的位来填充。其中,操作数可以是通用寄存器,也可以是立即数(0~31)。显然,当进行32 位的循环右移操作时,通用寄存器中的值不改变。
示例如下:

MOV R0, R1, ROR#2 @将R1 中的内容循环右移两位后传送到R0 中。

/************** 重要***********************/

ARM 微处理器支持加载/存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。

5.1、ldr(加载指令)(读内存指令)

LDR{条件} 目的寄存器, <存储器地址>

LDR 指令用于从存储器中将一个32 位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32 位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC(写pc) 作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计中比较常用,且寻址方式灵活多样,请读者认真掌握。示例如下:

LDR R0,[R1] @将存储器地址为R1 的字数据读入寄存器R0。
LDR R0,[R1,R2] @将存储器地址为R1+R2 的字数据读入寄存器R0。
LDR R0,[R1,#8] @将存储器地址为R1+8 的字数据读入寄存器R0。
LDR R0,[R1,R2]! @将存储器地址为R1+R2 的字数据读入寄存器R0,并将新地址R1+R2 写入R1。
LDR R0,[R1,#8]! @将存储器地址为R1+8 的字数据读入寄存器R0,并将新地址R1+8 写入R1。
LDR R0,[R1],R2 @将存储器地址为R1 的字数据读入寄存器R0,并将新地址R1+R2 写入R1。
LDR R0,[R1,R2,LSL#2]! @将存储器地址为R1+R2×4 的字数据读入寄存器R0,并将新地址R1+R2×4 写入R1。
LDR R0,[R1],R2,LSL#2 @将存储器地址为R1 的字数据读入寄存器R0,并将新地址R1+R2×4 写入R1。

#注意:使用LDR指令时字节地址是4的倍数 , 指令后面跟s: 表示可以更新标记位

5.2、str(存储指令)(存入内存指令)

STR{条件} 源寄存器, <存储器地址>
STR 指令用于从源寄存器中将一个32 位的字数据传送到存储器中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。示例如下:

STR R0,[R1],#8 @将R0中的字数据写入以R1 为地址的存储器中,并将新地址R1+8 写入R1。
STR R0,[R1,#8] @将R0中的字数据写入以R1+8为地址的存储器中。

/*end/

5.3、ldrh (load 16bit’s value from memory into register. )

LDR{条件}H 源寄存器, <存储器地址>
LDRH 指令用于从存储器中将一个16 位的半字数据传送到目的寄存器中,同时将寄存器的高16 位清零。该指令通常用于从存储器中读取16位的半字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
示例如下:

LDRH R0,[R1] @将存储器地址为R1的半字数据读入寄存器R0,并将R0 的高16 位清零。
LDRH R0,[R1,#8] @将存储器地址为R1+8 的半字数据读入寄存器R0,并将R0 的高16 位清零。
LDRH R0,[R1,R2] @将存储器地址为R1+R2 的半字数据读入寄存器R0,并将R0 的高16 位清零。

5.4、strh: store 16bit’s value of register into memory.

STR{条件}H 源寄存器, <存储器地址>
STRH 指令用于从源寄存器中将一个16 位的半字数据传送到存储器中。该半字数据为源寄存器中的低16 位。示例如下:

STRH R0,[R1] @将寄存器R0中的半字数据写入以R1 为地址的存储器中。
STRH R0,[R1,#8] @将寄存器R0 中的半字数据写入以R1+8 为地址的存储器中。

5.5、ldrb: load 8bit’s value from memory into register.

LDR{条件}B 目的寄存器, <存储器地址>
LDRB 指令用于从存储器中将一个8 位的字节数据传送到目的寄存器中,同时将寄存器的高24 位清零。该指令通常用于从存储器中读取8位的字节数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。示例如下:

LDRB R0,[R1] @将存储器地址为R1的字节数据读入寄存器R0,并将R0的高24位清零。
LDRB R0,[R1,#8] @将存储器地址为R1+8 的字节数据读入寄存器R0,并将R0 的高24位清零。

5.6、strb: store 8bit’s value of register into memory.

STR{条件}B 源寄存器, <存储器地址>
STRB 指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。
示例如下:

STRB R0,[R1] @将寄存器R0 中的字节数据写入以R1 为地址的存储器中。
STRB R0,[R1,#8] @将寄存器R0 中的字节数据写入以R1+8 为地址的存储器中。

5.7、 ldm / stm

批量数据加载/存储指令ARM 微处理器所支持批量数据加载/存储指令可以一次在一片连续的存储器单元和多个寄存器之间传送数据,批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,批量数据存储指令则完成相反的操作。

在STM、LDM指令中,寄存器列表与内存单元的对应关系:编号低的寄存器对应于内存中低地址单元;编号高的寄存器对应于内存中高地址单元。

常用的加载存储指令如下:

LDM(或STM){条件}{类型} 基址寄存器{!},寄存器列表{^}
LDM(或STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈或出栈。其中,{类型}为以下几种情况(它表示:LDM/STM指令地址模式选择
):

IA 先传送数据,后基址加4;
IB 先基址加4,后传送数据;
DA 先传送数据,后基址减4;
DB 先基址减4,后传送数据;
FD 满递减堆栈(Full Descending, ATPCS使用此规则,sp指向最后一个压入的值,数据栈由高地址向低地址生长);
ED 空递减堆栈;
FA 满递增堆栈;
EA 空递增堆栈;

(I: Increase, D: Descend, A: After, B: Before, F: Full, E: Empty)

 {!}为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。


 基址寄存器不允许为R15,寄存器列表可以为R0~R15 的任意组合。{^}为可选后缀,当指令为LDM 且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR 复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。
示例如下:

STMFD R13!,{R0,R4-R12,LR} @将寄存器列表中的寄存器(R0,R4-R12,LR)存入堆栈。
LDMFD R13!,{R0,R4-R12,PC} @将堆栈内容恢复到寄存器(R0,R4-R12,PC)。

STMFD指令的寻址方式为事前递减方式(DB),
STMFD SP!, {R0-R7,LR} @把数据压栈
其伪代码如下:

SP = SP - 9 x 4;
address = SP;

for i = 0 to 7
Memory[address] = Ri;
address = address + 4;

Memory[address] = LR;

LDMFD指令的寻址方式为事后递增方式(IA)
LDMFD SP!, {R0-R7,PC}^ @恢复现场,异常处理返回
其伪代码如下:

address = SP;
for i = 0 to 7
Ri = Memory[address]
address = address + 4;

PC = Memory[address]
SP = address;

5.8

7 异常产生指令

7.1 软中断指令 SWI

SWI{条件} 24 位的立即数
SWI指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。操作系统在SWI 的异常处理程序中提供相应的系统服务,指令中24 位的立即数指定用户程序调用系统例程的类型,相关参数通过通用寄存器传递,当指令中24 位的立即数被忽略时,用户程序调用系统例程的类型由通用寄存器R0 的内容决定,同时,参数通过其他通用寄存器传递。
示例如下:

[cpp] view plain copy
SWI 0x02 @该指令调用操作系统编号为02 的系统例程。

7.2 断点中断指令 BKPT

BKPT 16 位的立即数
BKPT 指令产生软件断点中断,可用于程序的调试。

8 协处理指令

8.1 协处理器数据操作指令 CDP

CDP{条件} 协处理器编号,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2
CDP 指令用于ARM 处理器通知ARM 协处理器执行特定的操作,若协处理器不能成功完成特定的操作,则产生未定义指令异常。其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,目的寄存器和源寄存器均为协处理器的寄存器,指令不涉及ARM 处理器的寄存器和存储器。
示例如下:

[cpp] view plain copy
CDP P3,2,C12,C10,C3,4 @该指令完成协处理器P3的初始化

CDP P1, 1, C2, C3, C4 @指令要操作的协处理器为p1 ,1为协处理器p1的指令操作代码。
@c2、c3、c4 为协处理器p1的寄存器。CPD指令的使用并不影响
@ARM微处理器中CPSR寄存器的状态位。

8.2 协处理器数据读取指令LDC

LDC{条件}{L} 协处理器编号,目的寄存器,[源寄存器]
LDC 指令用于将源寄存器所指向的存储器中的字数据传送到目的寄存器中,若协处理器不能成功完成传送操作,则产生未定义指令异常。其中,{L}选项表示指令为长读取操作,如用于双精度数据的传输。
示例如下:

[cpp] view plain copy
LDC P3,C4,[R0] @将ARM 处理器的寄存器R0 所指向的存储器中的字数据传送到协处理器P3 的寄存器C4 中。
LDC p5, c2, [R0, #4] @将内存地址为R0+4处的数据送到协处理器p5的寄存器c2中。
LDC p5, c1, [R0,R1] @将内存地址为R0+R1处的数据送到协处理器p5的寄存器c1中。

8.3 协处理器数据写入指令STC

STC{条件}{L} 协处理器编号,源寄存器,[目的寄存器]
STC 指令用于将源寄存器中的字数据传送到目的寄存器所指向的存储器中,若协处理器不能成功完成传送操作,则产生未定义指令异常。其中,{L}选项表示指令为长读取操作,如用于双精度数据的传输。
示例如下:

[cpp] view plain copy
STC P3,C4,[R0] @将协处理器P3 的寄存器C4中的字数据传送到ARM 处理器的寄存器R0所指向的存储器中。

8.4 ARM微处理器到协处理器的数据传送指令MCR

MCR{条件} 协处理器编号,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处理器操作码2
MCR 指令用于将ARM 处理器寄存器中的数据传送到协处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,源寄存器为ARM 处理器的寄存器,目的寄存器1 和目的寄存器2 均为协处理器的寄存器。
示例如下:

[cpp] view plain copy
MCR P3,3,R0,C4,C5,6 @该指令将ARM 处理器寄存器R0 中的数据传送到协处理器P3 的寄存器C4 和C5 中。

8.5 协处理器到ARM寄存器的数据传送指令MRC

MRC{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2
MRC 指令用于将协处理器寄存器中的数据传送到ARM 处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,目的寄存器为ARM 处理器的寄存器,源寄存器1 和源寄存器2 均为协处理器的寄存器。
示例如下:

[cpp] view plain copy
MRC P3,3,R0,C4,C5,6 @该指令将协处理器P3的寄存器中的数据传送到ARM 处理器寄存器中。

ADC{条件}{S} 目的寄存器, 操作数1<寄存器>, 操作数2
ADC 指令用于把两个操作数相加,再加上CPSR 中的C 条件标志位的值,并将结果存放到目的寄存器中。它使用一个进位标志位,这样就可以做比32 位大的数的加法,注意不要忘记设置S 后缀来更改进位标志。操作数1 应是一个寄存器,操作数2 可以是一个寄存器,被移位的寄存器,或一个立即数。


9、不重要

CMP
:可以用sub替换

(p288)  条件柱记符


直接后面跟


movge       //表示大于等于


"cmp %[a],%[b]"
//表示a和b比较

操作都是从又向左做的

mrs    //mrs是将当前程序状态寄存器cpsr的值,写到寄存器或变量


msr    //msr是将寄存器或变量的值,写到当前程序状态寄存器cpsr中

这三个的作用?

tst //按位与操作

cmn //看是否有进位的时候用到他

teq // 测试俩个数是否相等,相等,则用teq后一定等于0


跳转指令


bl  :在跳之前会将下一条指令的地址保存到lr中,
b   :直接跳转


地址本身不占空间,放在内存中才有,
和标号一样,都不占空间
c语言的函数名就是汇编的标号

复合访问内存的指令:
地址的偏移:存完之后偏移after
存之前偏移before

                    increase
                    decrease

ldmia   ldmib   ldmda   ldmdb       ??
stmia   stmib   stmda   stmdb



"mov r0, %[array]\n\t"      //把数组array首地址放在了r0中
"mov r1, %[src]\n\t"


"ldmia r1!, {r2, r3, r4}\n\t"
//格式就是这样的,表示,将内存中中的值分别放到的寄存器中,存完一个后,然后地址偏移
"stmia r0!, {r2, r3, r4}\n\t"
//将寄存器中的值放会内存中

在寄存器后面加个!表示回写,更新 加不加都行


汇编定义字符串
.string
.asciz

.word       //定义字符串为4个字节
.short      //2
.byte       //1

以.开头的都是关键字


如果要将一个很大的数放在寄存器中:

用伪指令:(前面必须要加等于号)
ldr r0, =GPM4BASE

这个和mov的作用很像,但是,mov规定立即数的大小不能超过512,

如何拿到标号的地址:

ldr r0,=str      //(加等于号)取标号的地址            (伪指令)
ldr r1,str       //(不加等于号)取(标号)地址中的值


    给标号加=   //表示取标号的地址
    不加等号    //表示取标号地址中的首4个字节的值


编译器会在编译的时候,会把伪指令这一条换为多条arm指令来运行

在调用函数的时候:
mov lr, pc
ldr pc, =地址

在执行子函数的时候,应该先把下下一条的地址保存起来,在子函数遇到}的时候,
会跳回,跳回肯定是写pc了(反汇编可以看一下,编译器的确是这样做的)

为什么要保存下下一条的地址?
因为你要回来肯定是写pc,来实现跳转,写的地址也应该是我们现在这条的下下一跳,所以应该先保存下下一条的地址。


跳转 (b,bl跳转,前后最大可以跳32M字节)(p335)

  1. “bl fool\n\t”

  2. “mov lr, pc\n\t”
    “b fool\n\t”

  3. “mov lr, pc\n\t”
    “ldr pc, =fool\n\t”

  4. “mov lr, pc\n\t”
    “ldr pc, fool_\n\t”
    “b end\n\t”

    “fool_:\n\t”
    “.word fool”

    “end:\n\t”

你可能感兴趣的:(ARM汇编,linux,ARM)