ARM

    xiaoxiao2024-12-28  16

    ARM_Linux NOTE_2

    Vine Farer

    2016.08.09


    1、ARM裸板汇编

    1)立即数

    一条指令是32位,最后一个操作数只剩下12位,高四位放幂,后8位放有效位

    当一个数的有效位(第1个1到最后一个1 总间隔)小于8位( 256 ),则是立即数

    当一个数的有效位大于8位,则不是立即数

    当一个数的有效位等于8:

    1)最后一个1在奇数位上,不是立即数

    2)最后一个1在偶数位上,是立即数

    若一个数按位取反是立即数,称之为有效数,只能用于mov后面。

    如:mov r0,#0xff00ffff 其反汇编生成 mvn r0, #0x00ff0000


    2)相关指令

    数据处理指令

    算数指令:ADD、ADC、SUB、SBC、RSB、RSC

    逻辑指令:BIC、AND、ORR、EOR

    比较指令:CMP、CMN、TST、TEQ

    数据搬移:MOV、MVN (mov用来访问CPU内部寄存器,str、ldr用来访问片外资源,如内存或片上外设寄存器)

    此类指令只能对寄存器操作,不针对存储器

    SWP

    寄存器和存储器间,由一次存储器读、一次存储器写组成原子操作。完成一个字节或字的交换

    不会被中断异常打断

    软中断SWI

    32位:4位条件码、4位指令码、24位数据(包括 SWI 号)

    产生异常陷阱,跳转到SWI硬件向量

    SWI处理程序课检测SWI号,再采取对应操作 ldr r0,[lr,#-4] bic r0,r0,#0xff000000

    进入 SVC 模式,进行特权操作

    PSR传送指令

    专门用来访问 CPSR

    MRS 读取 CPSR 值,改变后,由 MSR 写回 CPSR


    3)ARM处理器寻址方式

    立即数:有一个数据是通过立即数获得

    mov r0,#34 add r0,r1,#56

    寄存器寻址:所有操作数都是通过寄存器直接获得

    mov r0,r1 add r0,r1,r2 sub r0,r1,r4

    寄存器移位寻址:有一个操作数是通过寄存器移位计算获得

    mov r0,r1,lsl #4 add r0,r1,r2,lsl #12

    寄存器间接寻址:把一个寄存器的值当做指针,来读写内存值

    ldr r0,[ r1 ] <=> r0 = *( r1 ) str r0,[ r1 ] <=> *( r1 ) = r0 (*往往会同时用到伪指令:ldr r0, = 0xffff0000. 让r0存一个值或地址 )

    ldrb strb ldrsb ldrh strh ldrsh

    基址变址寻址:把一个寄存器值当做基地址,然后做地址偏移,访问内存

    前索引:ldr r0,[ r1,#4 ] a = *( p + 1 )

    后索引:ldr r0,[ r1 ],#4 a = *( p ++ )

    自动索引: ldr r0,[ r1,#4 ]! a = *( ++p )

    多寄存器寻址:一次赋值或拷贝多个寄存器

    ldmxx r0!,{r1-r6,r9} stmxx r0!,{r1-r6,r9}

    i:增,指针增加 a:后,先取值后累加 d:减,指针减小 b:前,先累加后取值

    堆栈寻址:专项用于 堆栈的 多寄存器寻址

    ldm、stm

    f:满、a:增、e:空、d:减

    ldmfd sp!,{r0-r12,lr} pop stmfd sp!,{r0-r12,lr} push

    相对寻址:相对于当前pc值得跳转

    b、bl bx、blx 带指令集切换跳转


    2、ARM汇编代码

    LED实验

    通过查找芯片手册与原理图找到需要配置的管脚

    配置相应管脚的寄存器

    源码(程序单步运行验证结果)

    安全代码:不影响其他寄存器中原有状态,只改变待操作的寄存器状态

    .text .globl _start _start: ldr r0,=0x114001e0 #读取GPF3CON寄存器地址到r0 ldr r1,[r0] #让r1存放r0指向的地址内的值,即待配置的寄存器值 bic r1,r1,#0xf00000 #清零相应位 orr r1,r1,#0x100000 #相应位置一 str r1,[r0] #将修改后的r1内的值回写到对应寄存器中 #管脚呈输出态 ldr r0,=0x114001e4 ldr r1,[r0] orr r1,r1,#0b100000 #将对应数据寄存器置1,管脚输出高电平 str r1,[r0] #灯亮 ldr r0,=0x114001e4 ldr r1,[r0] bic r1,r1,#0b100000 #将对应数据寄存器清0,管脚输出低电平 str r1,[r0] #灯灭 _stop: b _stop

    不安全代码:直接赋值给寄存器,会改变其他位的状态,不推荐

    ldr r1,=0x114001e0 ldr r0,=0x00110000 #改变两个引脚状态为输出态 str r0,[r1] ldr r1,=0x114001e4 ldr r0,=0x30 #直接让led5、led4亮 str r0,[r1]

    Makefile

    SHELL=C:\WINDOWS\system32\cmd.exe all: arm-none-eabi-gcc -c -g asm.s -o asm.o arm-none-eabi-ld -Ttext 0x40008000 asm.o -o asm.elf arm-none-eabi-objdump -D asm.elf > asm.dis #生成反汇编文件 clean: rm -rf *.elf *.o


    转载请注明原文地址: https://ju.6miu.com/read-1295071.html
    最新回复(0)