ARM(GNU)指令集

一、ARM汇编介绍

1、框架

Start.S

.section .data    @数据段(可省略),.section可省略
    <初始化的数据>
.section .bss     @bss段(可省略),.section可省略
    <未初始化的数据>
.section .text    @代码段,.section可省略
.golbal _start
_start:           @程序入口
    <汇编代码>

2、链接器(ld/arm-linux-ld)

(1)选项

-T 指定链接脚本
-o 输出最终可执行二进制文件
-Ttext 指定代码段的起始地址
-Tdata 指定数据段的起始地址
-Tbss 指定未初始化数据段的起始地址

Makefile:
all:start.o
    arm-linux-ld -Text 0x30000000 -o start_elf $^
#	arm-linux-ld -Tleds.lds  -o start_elf $^
%.0:%.S
    arm-linux-gcc -g -o $@ $^ -c
clean:
    rm *.o *.elf

(2)链接器脚本

SECTIONS{
    . = 0x30000000;    #指出起始地址

    . = ALIGN(4);    #指出该地址四字节对其
    .text :
    {
    main.o (.text)
    *(.text)
    }
    
    . = ALIGN(4);
    .data :
    {
    *(.data)
    }

    . = ALIGN(4);
    bss_start = .;
    .bss :
    {
    *(.bss)
    }
    bss_end = .;
}
SECTIONS { 
  firtst    0x00000000 : { head.o init.o }
  #0xB0004000为程序执行(虚拟)地址(程序需要被拷贝到该地址才可以被正常执行),2048为存储地址
  second    0xB0004000 : AT(2048) { leds.o }  
} 

 3、拷贝工具(objcopy/arm-linux-objcopy)

-O binary    //输出格式
-S           //不拷贝符号信息

4、反编译(objdump/arm-linux-objcopy) 

-D        //反汇编,包括所有section
-m arm    //指出指令集架构为arm

二、ARM指令集

1、算数和逻辑指令

(1)mov:赋值

mov R0, R1    @R0=R1

(2)mvn:赋取反值

mvn R0, #4    @R0=~4 -> R0=-5

(3)sub:减法

sub R0, R1, R2    @R0=R1-R2

 (4)add:加法

add R0, R1, R2    @R0=R1+R2

(5)and:逻辑与

and R0, R0, #3    @R0=R0&&3

(6)orr:逻辑或

orr R0, R0, #3    @R0=R0||3

(7)bic:位清除

bic R0, R0, #%1011    @1111 -> 0100

(8)ldmia:批量拷贝知道地址到寄存器

stmia r1!, {r3-r10} // 将r1指向的地址开始8个单元(8*4byte) 到r3-r10 寄存器

 (9)strmia:批量将指定范围寄存器拷贝到指定地址

stmia	r1!, {r3-r10} // 将r3-r10寄存器数据拷贝致 r1指定地址

2、比较指令

(1)cmp:比较

cmp R0, R1
    @  R0>R1    CPSR B=0 Z=0
    @  R0=R1    CPSR B=1 Z=0
    @  R0<R1    CPSR B=0 Z=1

(2)tst:按位与 

tst R0, #%1001
    @  (R0 & %1001)=0  -> CPSR Z=1
    @  (R0 & %1001)!=0 -> CPSR Z=0

 3、跳转指令

(1)b:(相对)跳转;相对跳转,位置无关的跳转(PCnew=PC+偏移)

b [条件] addr

(2)bl:(相对)跳转,带返回地址;相对跳转,位置无关的跳转(PCnew=PC+偏移)

bl fun    @将返回地址存于lr

使用场景:
fun:
...
mov pc, lr    @lr赋值给pc,实现函数返回

4、移位指令 

(1)lsl:逻辑左移

mov R0, R1, ror#2    @R0=R1<<3

(2)ror:循环右移

mov R0, R1, ror#2    @R0=R1循环右移2位

5、程序状态字访问指令

(1)msr:通过寄存器赋值给程序状态寄存器

msr cpsr, r0    @cpsr=r0

(2)mrs:程序状态寄存器拷贝至通用寄存器

mrs r0, cpsr    @r0=cpsr

6、 存储器访问指令

(1)ldr:将内存拷贝至寄存器

ldr r2, [r1]    @r2=[r1] -> r2=*r1

(2)adr:相对(PC寄存器)赋值

adr r0,_start

(3)str:将寄存器拷贝至内存

str r0, [r1]        @[r1]=r2 -> *r1=r2
str r0, [r1], #4    
                    @[r1]=r0; -> *r1=r0
                    @r1+=4;

三、伪指令

1、(32位)机器码组成,一条arm汇编指令的机器码

(1)数据处理机器码(以mov为例)

28-31 (cond)条件
26-27 保留
25    (I)源操作数(0-11位)保存为立即数,则该位为1
31-24 (opcond)指令编码
20    (S)是否影响标志位(CPSR)
16-19 (Rn)第一个源操作数,如果有多个源操作数
12-15 (Rd)目的寄存器
0-11  (shifter_operand)源操作数,mov等指令仅可以赋值8位数据

2、定义类伪指令

(1)global:全局标号
(2)ascii:字符串数据

.data
hello:
.ascii "hello world"
.align 4    @保证bdata地址为4字节对齐
bdata:
.byte 0x1
wdata:
.word 0xff
.golbal _start
_start:

(3)byte:字节数据
(4)word:双字节数据
(5)data:定义数据段
(6)equ:宏定义

3、操作类伪指令

(1)ldr:给寄存器赋值,可以赋值大于8位的数(mov只可以赋值8位以内的数值)

mov r0, #0xff
ldr r0, =x1ff       @可以赋值8位以上立即数数据,立即数表现格式不同
ldr r0, [r1], #4    @ r0=[r1]; r1+=4;

(2)nop:空操作,可以用来延时

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值