寄存器
通用寄存器 | 别称 | 作用 |
R0-R3 | a1-a3 | 通用寄存器,随意更改 |
R4-R9 | v1-v7 | APCS规范要求,被调方必须保证这些寄存器调用前后一致 |
R10 | SL | |
R11 | FP | 在调用子过程开始时使用,为了恢复SP,FP固定指向SP存放完各寄存器后的真正栈起始位置 |
R12 | IP | 一般存放调用子过程前的栈位置,SP |
R13 | SP | 栈地址寄存器 |
R14 | LR | 存放使用PC寄存器跳转前,调用指令的地址 |
专用寄存器 | 别称 | 作用 |
R15 | PC | 指令寄存器,给它赋值就会去对应地址取指令运行 |
CPSR | 状态寄存器 | 指示ARM内核的状态,有控制状态,指示中断等有无使能,还有编码状态,指示上一个指令执行后是处于溢出、计算结果负数等。 |
SPSR | 待补充 |
CPSR寄存器
CPSR寄存器执行指令前,会根据上一条指令的状态,确定下一条指令执不执行。这个状态就通过CPSR的31-27位获取。
汇编指令
汇编器编译,编译成没有链接的汇编文件:
xx-as test.S -o test.o
反汇编,查看汇编后的信息:
xx-objdump -d test.o
1、将一个寄存器的值移到另一个寄存器当中,注意是将r1的值给r0
mov r0,r1
2、将一个数字移到一个寄存器当中。
mov r0,#5
3、将一个大数移到一个寄存器当中。因为MOV指令汇编生成的对应指令码是有限制的,所以使用伪指令LDR,伪指令(宏指令)编译后可能不止一条指令,会有很多指令生成,由汇编器自动处理。
ldr r0,=123456789
4、 加法指令,将r1的值与r0的值相加,存放再r3中。
add r3,r1,r0
5、减法指令,将r1的值与r0的值相减,存放再r3中。
sub r3,r1,r0
6、 将内存的地址给寄存器,从内存中取值。
ldr r1,=0x1234;将0x1234的地址给r1
ldr r0,[r1];从r1存放的地址中取值,此时的ldr非伪指令,同名而已。
7、将一个值,存到内存中去。
ldr r0,=0x1234;将0x1234这个地址给r0
mov r1,#88;将88这个数值给r1
str r1,[r0];将r1存放的数值,赋值给r0存放的地址中。
8、标签,类似c语言的symbol,或者是变量?标签不占用大小。
ldr r0,labal;给r0赋值label的值1234
ldr r0,=label;给r0赋label的地址,这个地址在链接时给出
label:
.word 1234;word4个字节
9、使用PC寄存器,跳转到内存地址中执行指令。
ldr pc,addr;到0x40007000执行程序
addr:
.word 0x40007000;word4个字节
10、执行完程序后返回,默认从R14也就是从LR寄存器取返回地址。
APCS,ARM过程调用规范:调用的过程中,调用方,要把PC寄存器的值存放在LR寄存器中。被调方,要从LR寄存器取回调用前保持的PC地址,并赋给PC,返回。
mov lr,pc;存放返回地址,即pc地址,流水线原理,pc指向的是后两条指令。
ldr pc,addr;到0x40007000执行程序
mov r0,r1;PC指向这里
addr:
.word 0x40007000;word4个字节
11、到地址+4的地方去取值
ldr r14,[sp,#4]
ldr r14,[sp,#-4]@到减四的地方取
12、汇编定义一个字符串
string:
.asciz "Helo \n"@ascii不会添加'\0',asciz会
13、c语言中,函数的栈使用过程,汇编
mov ip,sp @保存sp到ip中
stmfd sp!,{fp,ip,lr,pc} @从高编号寄存器存到高地址,先存pc,先减后存。sp后的!决定sp指针在存储完后是否移动。保存现场。
sub fp,ip,#4 @fp指向ip-4的地方,也就是刚开始调用子过程sp起始-4的地方,也就是栈还未存放寄存器时的起始地址。
@这里开始使用栈....
sub sp,fp,#12 @使用fp恢复sp,恢复的sp指向的是,存放了各寄存器后的起始位置。
ldmfd sp,{fp,sp,pc} @恢复寄存器把fp恢复到fp,ip恢复到sp,lr恢复到pc。恢复现场。
14、跳转标签指令b,跳转任意地址bl
mov lr,pc
b test @test是个标签,这个标签是一个子程序
bl test @bl含有将pc存储到lr的作用,一条指令即可跳转
15、位置无关码指令
adr r0,str @取str的地址。最终生成的指令,是根据PC寄存器指向的地址进行偏移。
str:
.word 12345678
16、再gcc编译器下,指定section
.section .text
@这里放带代码段
__start:
mov ip,sp
stmfd sp!,{fp,ip,lr,pc}
sub fp,ip,#4
@子过程
sub sp,fp,#12
ldmfd sp!,{fp,sp,pc}
.section .data
@这里放data段
str:
.word 12345678
17、通过gcc编译器,指定各段链接地址
arm-gcc-ld -Ttext=0x08000000 -Tdata=0x40007000 源文件.o -o 目标文件
arm-gcc-objdump -h 目标文件
arm-gcc-objdump -D 目标文件
arm-gcc-objcopy -j .text(-j .data)-I elf32-littlearm -O binary 原ELF文件 ELF去头后文件.bin
18、C语言内嵌汇编,GCC
int main()
{
unsigned long cpsr;
__asm__ __volatile__ (
"指令 目标%0,目标 \n"@关联cpsr变量
: "=r"
);
}