ARM 汇编

本文介绍了ARM汇编语言的基本指令,包括比较、算术运算、逻辑运算、寄存器操作以及堆栈和跳转指令。此外,还讲解了不同类型的寻址模式,如单寄存器、多寄存器寻址以及堆栈操作。示例代码展示了如何使用这些指令进行数据处理和流程控制。
摘要由CSDN通过智能技术生成
; 还未更新完...

;--------作者:时空自由民
;
;-----------ARM 汇编语言 例子


;-------常见指令后缀 
    EQ      ;相等
    NE      ;不相等
    CS/HS   ;无符号数大于或等于
    ......

    ADD R0,R0,#1    ; R0+1 -> R0

    MOV R0,#0X00FF  ; R0=0X00FF

    MOVS R0,R1,LSL #3 ;将寄存器R1值 左移3位后传送到R0 并影响标志位

    MVN R0,R1 ;将寄存器R1值按位求反后送入R0

    MVN R0,#0XFF ;将立即数0XFF 按位取反后装入R0 然后R0=0xffffff00

    ADD R0,R1,R2    ; R1+R2 ->R0

    MOV R0,R1       ; R1->R0

    LDR R0,[R1]     ; [R1]->R0 假设 R1存储的是0x3FE是内存地址  则是将00X3FE内存地址中的数据存入R0
   
    MOV R0,R1,LSL #2 ; R1<<2 ->R0, LSL 左移命令  LSR右移命令 ASR算数右移  ROR循环右移 RRX带扩展的循环右移
   
    ADD R0,R1,R2,LSR #3 ;R1 + R2>>3 ->R0
    
    SUB R0,R0,#1 ; R0=R0-1
    
    SUB R0,R1,R2 ; R0=R1-R2
   
    SUB R0,R1,R2,LSL #3 ;R0=R1-(R2<<3)
    
    LDR R0,[R1,#2]  ; [R1+2] ->R0 R1中的值+2 当作内存地址 然后将内存地址中的值 赋值到R0

    STR R1,[R0,#0X12]   ; R1 ->R0+0X12地址内存中去 
    STR R1,[R0],#0X12   ; R1 ->R0+0X12地址内存中去  R0=R0+0X12
    
    RSB R0,R0,#0XFFFF   ;R0=0XFFFF - R0
    RSB R0,R1,R2        ;R0=R2-R1

    AND R0,R1,R2    ; R0= R1 & R2
    AND R0,R0,#3    ; R0=R0&3

    ORR R0,R0,#3    ; R0=R0|3

    EOR R0,R0,#0F   ; R0=R0 异或 0F

    BIC R0,R0,#0F   ; 将R0的低4位 清0 

    CMP R1,R0       ; R1-R0 并改变CPSR的标志位

    CMN R1,R0       ; R1+R0 并改变CPSR的标志位
    CMN R1,#0x200   ; 将R1值和立即数0X200相加 并根据结果改变CPSR标志位

    TST R1,#0XF     ; 检测R1的低4位是否为0

    TEQ R1,R2       ; 将R1的值 和R2的值 进行异或运算 然后改变CPSR的标志位

    ;程序状态寄存器处理指令
    MRS R0,CPSR  ;将CPSR->R0
    ORR R0,R0,#C0 ;R0=R0|C0 ,即屏蔽外部中断 和快速外部中断

    MSR CPSR,R0 ;R0->CPSR



    ;多寄存器寻址
    ;从左赋值到右  用于存储器读取数据 比单字读取操作方便
    ;IA:每次传送后地址加4
    ;IB:每次传送前地址加4
    ;DA:每次传送后地址减4
    ;DB:每次传送前地址减4
    ;FD:满递减堆栈
    ;ED:空递减堆栈
    ;FA:满递增堆栈
    ;EA:空递增堆栈
    LDMIA R0!,{ R1-R3,R5}   ; [R0] ->R1  假设R0=0XF1 将内存地址0XF1中的数据赋值到 R1
                            ; [R0+4] ->R2 R0=0XF1+4 将内存地址0XF1+4 中的数据赋值到R2
                            ; [R0+8] ->R3 
                            ; [R0+12] ->R5
    
    STMIA R1!,{R3-R9}       ;将R3~R9 数据存储到R1 R1更新值
                            ;R3->[R1]
                            ;R4->[R1+4]
                            ;R5->[R1+8]
                            ;R6->[R1+12]

    SWP R1,R1,[R0]  ;将R1的内容和R0指向的存储单元内容进行交换
    

    ;异常产生指令
    SWI     0x02  ;软中断 调用操作系统编号为0X02的系统例程
    BKPT    0XFF32 ; 

    ;堆栈寻址  栈会向上增长 递增堆栈,也会向下增长 递减堆栈
    ;后缀 IB 先增加堆栈地址值 SP+4,然后再出栈 入栈 SP->XX
    ;后缀 IA 先完成操作在增加地址 SP->XX  SP+4
    ;后缀 DB 先减少堆栈地址值 SP-4,然后再出栈 入栈 SP->XX
    ;后缀 DA 先完成操作在减少地址值 SP->XX  SP-4
    STMFD SP!,{R1-R3,LR}   ; 将寄存器R1~R3 LR 入栈,满递减堆栈 R1->SP SP++ R2->SP SP++....
    LDMFD SP!,{R1-R3,LR}   ; 将栈中数据 出栈 存入R1~R3 LR,SP->R1 SP--, SP->R2 SP--


    ;跳转指令
    LDR PC,[PC,#+0X00FF] ; [PC+8+0X00FF] ->PC  修改程序指针 PC值 实现跳转
    B task1 ;无条件 跳转到task1处执行
    B 0x1234 ;跳转到绝对地址 0X1234处

    BL task1 ;先将当前执行指令的下一条指令的地址值 存储到链接寄存器R14(LR)(以便再返回来) 在跳转到task1标号执行

    BLX task1 ;先将当前执行指令的下一条指令的地址值 存储到链接寄存器R14(LR)(以便再返回来) 并从ARM状态切换到Thumb状态 在跳转到task1标号执行
    BLX R0 ;先将当前执行指令的下一条指令的地址值 存储到链接寄存器R14(LR)(以便再返回来) 并从ARM状态切换到Thumb状态 在跳转到R0中的地址处执行

    BX R0 ; 跳转到R0处执行 如果R0[0]=1 则切换到Thumb状态


    ;ARM 常见伪指令 
    DCB ;分配一段字节的内存单元 并用指定的数据初始化
    DCD DCDU ;分配一段字的内存单元 ,并用指定的数据初始化

    DCQ DCQU ;分配一段双字的内存单元 并用64位整型数据初始化

    DCW DCWU ;分配一段半字的内存单元 并用指定的数据初始化

    ALIGN ; 边界对齐 
    AREA  ; data段 rom段定义 
    END ; 汇编结束
    ENTRY ; 程序入口
    EQU ;常量定义 类似C宏定义 
    EXPORT , GLORBAL ;声明一个符号可以被 其他文件引用
    IMPORT EXYERN ;声明一个外部符号
    
    NOP ; 延时空操作

;---------ARM asm Example -------

    AREA BUF,DATA,READWRITE ;声明一个数据段 BUF in RAM , BUF 可读可写
    count DCB 30  ; 定义一个字节单元count 
    AREA EXAMPLE1 ,CODE,READONLY ; 声明代码段 EXAMPLE1 in ROM , 只读
    ENTRY ; 程序入口
    CODE32  ;声明32位ARM指令
    START
        LDRB R0,count   ;R0=count
        MOV  R1,#10     ;R1=0X10
        ADD R0,R0,R1    ;R0=R0+R1
        B START ;跳转到START处执行

    END ;程序结束
	
;----------------STM32启动文件.s 代码分析---------------
	
	;Reset_Handler 类似于子函数的函数名
	Reset_Handler	PROC	;PROC 定义的子程序的开始 类似C语言函数的{ }的开头{
	
	EXPORT Reset_Handler  [WEAK] ; WEAK 意思若定义 就是或者函数定义的作用很弱 就小领导的说话没啥用 这个也是在这里定义了权威作用不太大,在其他地方还可以再定义这个子函数,其他地方如果在定义了这个子函数,那这里的定义就无效了
	
	;EXPORT 类似于C语言的extern关键字 声明外部可调用的全局属性
	
	IMPORT __main ; __main是外部的文件 	IMPORT在这里 就是引入外部变量 类似于extern pwm; 这个PWM是其他.c文件定义的全局变量 然后在本文件中引用
	
	ENDP ;子函数结束的标志 类似函数{}的末尾}

源代码文件的链接

链接:https://pan.baidu.com/s/12kvtT8djz1hL0X3KFBbK-A?pwd=y4gp
提取码:y4gp

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值