汇编指令详解

1 汇编程序概述

1.1 为什么使用汇编

(1)bootloader和Linux内核的初始化代码都需要汇编进行编写
(2)在对效率有特殊要求的地方需要使用汇编程序编写

1.2 ARM汇编分类

(1)ARM汇编标准:使用于ARM公司的汇编器,适合在Windows平台下使用,如ADS中使用
(2)GNU汇编:适用于GNU交叉编译工具链中的汇编器,适用于Linux开发平台
(3)ARM指令集手册链接:https://pan.baidu.com/s/1brav0Mb 密码:tm5g

1.3 汇编程序框架

.section .data
    <初始化的数据>
.section .bss
    <未初始化的数据>
.section .text
.global _start
_start:
    <汇编代码>

1.4 汇编程序

start.S

.text
.global _start
_start:
    mov r1, #1
    mov r2, #2
    mov r3, #3

Makefile

all:start.o
    arm-linux-ld -Ttext 0x30000000 -o start.elf $^
%.o:%.S
    arm-linux-gcc -g -o $@ $^ -c
clean:
    rm *.o *.elf

2 指令分类学习

2.1算术逻辑指令

(1)mov:传送
将另一个寄存器、被移位的寄存器、或一个立即值装载一个值到目的寄存器

mov r1, #8
mov r2, r2
mov r3, #10

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

mvn r1, #0b10
mvn r2, #5
mvn r3, r1

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

mov r2, #4
sub r1, r2, #2
mov r0, #1
sub r3, r1, r0

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

add r1, r2, #3

(5)and:逻辑与
将两个操作数进行逻辑与,把结果放置到目的寄存器中。操作数1是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器或一个立即值

mov r1, #5
and r2, r1, #0
mov r1, #5
and r2, r1, #1

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

mov r0, #5
bic r0, r0, #0b1011

2.2比较指令

(1)cmp:比较
允许把一个寄存器的内容如另一个寄存器的内容或立即值进行比较,更改状态标识允许进行条件执行。它进行一次减法,但不存储结果,而是正确的更改标志。标志表示操作数1bi操作数2如何(大、小、等)。如果操作数1大于操作数2,则此后的有GT后缀的指令可以执行

mov r1, #2
cmp r1, #3

(2)test:测试位
类似于cmp,不产生放置到目的寄存器的结果。而是将两个操作数的操作结果反映到状态标志上。使用TST来检查是否设置了特定的位。操作数1是要测试的数据字,而操作数2是一位掩码。经过测试后,如果匹配则设置Zero标志,否则清除它。

mov r1, #0b101
tst r1, #0b001
mov r1, #0b101
tst r1, #0b10

2.3跳转指令

(1)b:分支
b是最简单的分支。一旦遇到一个b指令,ARM处理器将立即跳转到指定的地址,从那里继续执行。注意存储在分支指令中的实际值是相对于R15的值的一个偏移量;而不是一个绝对地址。它的值由汇编器来计算,它是24位有符号数,左移两位后有符号扩展为32位,表示的有效偏移为26位(+/-32M)。

    mov r1, #6
    mov r2, #5
    cmp r1, r2
    bgt branch1
    add r3, r1, r2
    b end
branch1:
    sub r3, r1, r2
end:
    nop

(2)bl:带连接的分支
bl是另一个分支指令。这就是分支之前,在寄存器R14中转载R15的内容。你可以重新装载R14到R15中来返回到在这个分支之后的那个指令,它是子例程的一个基本但强力的实现。

    mov r1, #2
    cmp r1, #1
    bl func1
    mov r1, #2
    cmp r1, #3
func1:
    mov r1, #2
    mov r2, #3
    mov pc, lr

2.4移位指令

(1)lsl:逻辑或算术左移

mov r1, #0b1
mov r1, r1, lsl #2

(2)ror:循环右移

mov r1, #0b11
mov r1, r1, ror #1

2.5程序状态字访问

(1)msr

msr cpsr, r0        ;复制r0到cpsr中
msr spsr, r0        ;复制r0到spsr中
msr cpsr_flg, r0    ;复制r0的标志位到cpsr中
msr cpsr_flg, #1 << 28  ;复制立即值标志位到cpsr中

(2)mrs

mrs r0, cpsr    ;复制cpsr到r0中
mrs r0, spsr    ;复制spsr到r0中

2.6存储器访问指令

(1)ldr

mov r1, #0x30000000
ldr r0, [r1]    ;从0x30000000加载数值到r0

(2)str

mov r0, #0xff
mov r1, #0x30000000
str r0, [r1]    ;将r0中的数据保存到0x30000000中

3 伪指令

3.1ARM机器码

3.2定义类伪指令

伪指令本身并没有所对应的机器码,它只是在编译的时候起作用,或者转化为其他的实际指令来运行
(1)global(定义全局变量)
(2)ascii(字符数据)
(3)byte(byte类型数据)
(4)word(word类型数据)
(5)data(定义数据)
(6)equ(定义宏)
(7)align(内存对齐)

    .data
    .align 4
    hello:
    .ascii "hello world"
    bh:
    .byte 0x1
    ADD:
    .word 0xff
    .equ DA, 0x89

3.3操作类伪指令

mov操作符的立即数不能大于八位

ldr r0, =0x1ff

nop:空操作

4 协处理访问指令

4.1什么是协处理器

协处理器用于执行特定的处理任务,如:数学协处理器可以控制数字处理,以减轻处理器的负担。ARM可支持多达16个协处理器,其中CP15是非常重要的一个协处理器
CP15:系统控制协处理器

4.2协处理器的访问

(1)mcr

mcr{cond} P15, <Opcode>, <Rd>, <CRn>, <CRm>, {<Opcode2>}    (L=0)

(2)mrc

mcr{cond} P15, <Opcode>, <Rd>, <CRn>, <CRm>, {<Opcode2>}    (L=1)
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值