当前位置:首页 > CN2资讯 > 正文内容

支持arm架构windows 10

13小时前CN2资讯

文章目录

  • 一、GUN汇编语法
  • 1.1 语句结构:
  • 1.2 伪操作
  • 1.3 GUN函数
  • 二、 ARM的寻址方式
  • 2.1立即寻址
  • 2.2寄存器寻址
  • 2.3寄存器间接寻址
  • 2.4基址变址寻址
  • 2.5多寄存器寻址
  • 2.6相对寻址
  • 2.7堆栈寻址
  • 三、Cortex-A常用汇编指令
  • 3.1 处理器内部数据传输指令
  • 3.2 存储器访问指令
  • 3.3 压栈和出栈指令
  • 3.4 跳转指令
  • 3.5 算术运算指令
  • 3.6 逻辑运算指令

ARM裸机开发:ARM汇编基础

本期正文:

芯片在上电后,最开始并没有运行C语言的环境,需要通过汇编程序来运行配置,直到能够运行C语言后在开始切换到C语言运行环境,这段代码文件也叫启动文件,对学习驱动开发来说,汇编非常有必要学习一下!因为I.MAX是Cortex-A内核的芯片,所以主要了解Cortex-A的汇编指令

一、GUN汇编语法

因为我们编译器使用的是 GUN cc(GCC)交叉编译器,用来在当前平台上编译其他平台的代码,他有着自己的语法规范,所以我们编写Cortex-A的汇编代码时要符合GUN的语法规范!

1.1 语句结构:

GNU汇编语法适用于所有的架构,并不是 ARM 独享的,GNU 汇编由一系列的语句组成, 每行一条语句,每条语句有三个可选部分,如下:

label:instruction @ comment

语句组成:

组成

功能

label

标号,表示指令地址位置,有些指令前面可能会有标号,这样就可以通过这个标号得到指令的地址,标号也可以用来表示数据地址。注意 label 后面的“:”,任何以“:”结尾的标识 符都会被识别为一个标号。

instruction

指令,也就是汇编指令或伪指令

@comment

注释内容(@符号,表示后面的是注释)

示例

add: MOVS R0, #0X12 @设置 R0=0X12

add是标号,表示指令地址,后面可以通过标号进行跳转,MOV R0 ,#0x12将立即数赋值给R0寄存器

@设置 R0=0X12为注释,不参与编译

1.2 伪操作

除了指令之外,汇编还有伪操作和为指令,两者区别如下

伪操作,其操作对象是汇编编译器;而伪指令,其最终的操作对象是指令,也就是说,其对应的是用于CPU执行的指令。这就是他们之间简单但很微妙的区别。

伪指令最终面对的是CPU指令集的指令。伪操作是用来控制汇编器是如何来产生汇编指令的。

ARM 中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用小写,但是不能大小写混用!

用户可以使用.section(伪操作)来定义一个段,汇编系统预定义了一些段名如下:(部分)

每个段以段名开始,以下一段名或者文件结尾结束

伪操作

功能

.text

表示代码段。

.data

初始化的数据段。

.bss

未初始化的数据段。

.rodata

只读数据段。

.byte

定义单字节数据,比如.byte 0x12。

.short

定义双字节数据,比如.short 0x1234。

.long

定义一个 4 字节数据,比如.long 0x12345678。

.equ

赋值语句,格式为:.equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。

.align

数据字节对齐,比如:.align 4 表示 4 字节对齐。

.end

表示源文件结束。

.global

定义一个全局符号,格式为:.global symbol,比如:.global _start。

extern XXXX

说明xxxx为外部函数,调用的时候可以遍访所有文件找到该函数并且使用它。

我们可以在编写汇编中使用这些预定义的段,完成一些功能,比如汇编程序的默认入口标号是start,不过我们也可以在链接脚本中使用 ENTRY 来指明其它的入口点,下面的代码就是使用start 作为入口标号

.global _start _start: ldr r0, =0x12 @r0=0x12

.global个全局标号,类似 C 语言里面的全局变量一样,声明之后,.global _start 让start符号成为可见的标示符,这样链接器就知道跳转到程序中的什么地方并开始执行,linux寻找这个 _start标签作为程序的默认进入点

除此之外我们也可以自定义伪操作,使用.section来定义一个段,,例如

.section .testsection @定义一个 testsetcion 段

1.3 GUN函数

GUN语法支持函数,函数格式如下:

函数名: 函数体 返回语句

比如Cortex-A7的中断服务函数

/* 未定义中断 */ Undefined_Handler: ldr r0, =Undefined_Handler bx r0 /* SVC 中断 */ SVC_Handler: ldr r0, =SVC_Handler bx r0 /* 预取终止中断 */ PrefAbort_Handler: ldr r0, =Pref bx r0

例如 “SVC_Handler” 就是函数名,“ldr r0, =SVC_Handler”是函数体,“bx r0”是函数 返回语句,“bx”指令是返回指令,函数返回语句不是必须的

二、 ARM的寻址方式

寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式,目前ARM指令系统支持以下几种寻址方式:立即数寻址、寄存器寻址、寄存器偏移寻址、寄存器间接寻址、基址变址寻址、多寄存器寻址、相对寻址、堆栈寻址和块拷贝寻址

2.1立即寻址

也称为立即数寻址,这种寻址方式指令中就已经给出了操作数。也就是在执行指令的过程中,处理器取得指令的同时也取得了操作数,因此称为立即数寻址。例如:

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

其中源操作数就是立即数,要求以“#”开始,对于十六进制的立即数,要求在“#”后面加“0x”或“&”。

2.2寄存器寻址

将寄存器中的数值作为操作数,是各类微处理器常用的寻址方式,也是效率较高的寻址方式。例如:

ADD R0, R1, R2 ;R1+R2->R0,将R1和R2的值相加,将结果存入R0

2.3寄存器间接寻址

寄存器间接寻址是以寄存器中的值作为操作数的地址,操作数本身存放在寄存器中。例如:

ADD R0, R1, [R2] ;R1+[R2]->R0 LDR R0, [R1] ;[R1]->R0 ;第一条指令,以寄存器R2的值作为操作数的地址,在寄存器中取得一个操作数后与R1相加,将结果存入寄存器R0。 ;第二条指令,将寄存器中以R1为地址的值赋给R0。

[R0]表示以R0寄存器的值为地址的值作为实际值

R0表示寄存器的值作为实际值

2.4基址变址寻址

基址变址寻址是把基址寄存器的内容与指令中给出的地址偏移量相加,从而得到一个操作数的有效地址。该方式常用于访问基地址附近的某些存储单元,一般有以下几种方式:

将寄存器R1的值加上4作为操作数的有效地址,取得操作数后存入R0中,代码如下

LDR R0, [R1, #4] ;[R1+4]->R0

将寄存器R1的值加上4作为操作数的有效地址,取得操作数后存入R0中,然后寄存器R1的值加上4个字节,代码如下

LDR R0, [R1, #4]! ;[R1+4]->R0、R1+4->R1

将寄存器R1的值作为操作数的有效地址,取得操作数后存入R0中,然后寄存器R1的值加上4个字节,代码如下

LDR R0, [R1], #4 ;[R1]->R0、R1+4->R1

将寄存器R1和R2的值相加作为操作数的有效地址,取得操作数后存入R0中,代码如下

LDR R0, [R1, R2] ;[R1+R2]->R0

2.5多寄存器寻址

使用多寄存器寻址,一条指令可以完成多个寄存器值的传送,一条指令最多可以传送16个通用寄存器的值。例如:

LDMIA R0, {R1,R2,R3,R4,} ;[R0]->R1,[R0+4]->R2,[R0+8]->R3,[R0+12]->R4

该指令后缀IA表示每次执行完读取/存储操作后,R0按字长增加,因此,指令可以将连续存储单元的值传送到R1~R4。

2.6相对寻址

与基址变址寻址类似,相对寻址以程序计数器PC的当前值作为基地址,指令中的地址标号作为偏移量,将两者相加后得到操作数的有效地址。以下程序完成子程序的调用和返回,跳转指令BL采用了相对寻址方式:

BL NEXT ;跳转到子程序NEXT处执行指令 ...... NEXT ...... MV PC, LR ;从子程序返回

2.7堆栈寻址

堆栈是一种数据结构,按先进后出的方式工作,使用一个称为堆栈指针的专用寄存器指示当前的操作,堆栈指针总是指向堆栈顶端。

  • 当堆栈指针指向最后压入的数据时,称为满堆栈;
  • 当堆栈指针指向下一个将要压入的位置时,称为空堆栈。
  • 根据堆栈的生成方式,可分为递增堆栈和递减堆栈。当堆栈由低地址向高地址生成时,称为递增堆栈,反之称为递减堆栈。排列组合后可得到4中类型的堆栈工作方式,ARM微处理器支持全部4种类型的堆栈工作方式,如下:

    • 满递增堆栈:堆栈指针指向最后压入的数据,由低地址向高地址生成。
    • 满递减堆栈:堆栈指针指向最后压入的数据,由高地址向低地址生成。
    • 空递增堆栈:堆栈指针指向下一个将要压入数据的空位置,由低地址向高地址生成。
    • 空递减堆栈:堆栈指针指向下一个将要压入数据的空位置,由高地址向低地址生成

    三、Cortex-A常用汇编指令

    3.1 处理器内部数据传输指令

    处理器内部数据传输主要有以下三个操作:

  • 将数据从一个寄存器传递到另外一个寄存器
  • 将数据从一个寄存器传递到特殊寄存器,如 CPSR 和 SPSR 寄存器
  • 将立即数传递到寄存器
  • 常用指令有:

    指令

    目标


    功能

    MOV

    R0

    R1

    将 R1 里面的数据复制到 R0 中

    MRS

    R0

    CPSR

    将特殊寄存器 CPSR 里面的数据复制到 R0 中。

    MSR

    CPSR

    R1

    将 R1 里面的数据复制到特殊寄存器 CPSR 里中

    • MOV指令

    MOV 指令用于将数据从一个寄存器拷贝到另外一个寄存器,或者将一个立即数传递到寄存器里面

    MOV R0,R1 @将寄存器 R1 中的数据传递给 R0,即 R0=R1 MOV R0, #0X12 @将立即数 0X12 传递给 R0 寄存器,即 R0=0X12
    • MRS指令

    MRS 指令用于将特殊寄存器(如 CPSR 和 SPSR)中的数据传递给通用寄存器,要读取特殊寄存器的数据只能使用 MRS 指令

    MRS R0, CPSR @将特殊寄存器 CPSR 里面的数据传递给 R0,即 R0=CPSR
    • MSR 指令

    MSR 指令用来将普通寄存器的数据传递给特殊寄存器,也就 是写特殊寄存器,写特殊寄存器只能使用 MSR

    MSR CPSR, R0 @将 R0 中的数据复制到 CPSR 中,即 CPSR=R0

    3.2 存储器访问指令

    ARM 不能直接访问存储器,比如 RAM 中的数据,配置寄存器的时候需要借助存储器访问指令,一般先将要配置的值 写入到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器中。读取 I.MX6UL 寄存器也是一样的,只是过程相反。常用的存储器访问指令有两种:LDR 和 STR,用法如表

    指令

    描述

    LDR Rd, [Rn , #offset]

    从存储器 Rn+offset 的位置读取数据存放到 Rd 中。

    STR Rd, [Rn, #offset]

    将 Rd 中的数据写入到存储器中的 Rn+offset 位置。

    • LDR指令

    LDR 主要用于从存储器加载数据到寄存器 Rx 中,LDR 也可以将一个立即数加载到寄存器 Rx 中LDR 加载立即数的时候要使用“=”,而不是“#”。在嵌入式开发中,LDR 最常用的就是读 取 CPU 的寄存器值,比如 I.MX6UL 有个寄存器 GPIO1_GDIR,其地址为 0X0209C004,要读取这个寄存器中的数据,代码如下

    1 LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004 2 LDR R1, [R0] @读取地址 0X0209C004 中的数据到 R1 寄存器中
    • STR 指令

    STR 就是将数据写入到存储器中,同样以 I.MX6UL 寄存器 GPIO1_GDIR 为例,现在我们要配置寄存器 GPIO1_GDIR 的值为 0X20000002,示例代码如下

    1 LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004 2 LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002 3 STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址对应的内存中

    LDR 和 STR 都是按照字进行读取和写入的,也就是操作的 32 位数据,如果要按照字节、 半字进行操作的话可以在指令“LDR”后面加上 B 或 H,比如按字节操作的指令就是 LDRB 和 STRB,按半字操作的指令就是 LDRH 和 STRH

    3.3 压栈和出栈指令

    函数在运行时,临时存储数据的寄存器是R0-R15,函数运行结束或者切换的时候,需要保存当前运行的参数(保护现场),即把当前寄存器的数据通过SP指针压入到堆栈里面,进行保存,当函数继续运行时,则将原先保存在堆栈的数据弹出到当前R0-R15中(恢复现场)继续运行;。压栈 的指令为 PUSH,出栈的指令为 POP,PUSH 和 POP 是一种多存储和多加载指令(就是实际上执行多条指令),即可以一次 操作多个寄存器数据,他们利用当前的栈指针 SP 来生成地址,PUSH 和 POP 的用法如表:

    指令

    描述

    PUSH

    将寄存器列表存入栈中

    POP

    从栈中恢复寄存器列表

    假如我们现在要将 R0~R3 和 R12 这 5 个寄存器压栈,当前的 SP 指针指向 0X80000000,处理器的堆栈是向下增长的,使用的汇编代码如下:

    PUSH {R0~R3, R12} @将 R0~R3 和 R12 压栈

    压栈后的堆栈SP指针如下:

    如果我们要出栈的话 就是使用如下代码:

    POP {R0~R3,R12} @恢复 R0~R3,R12

    出栈的就是从栈顶,也就是 SP 当前执行的位置开始,地址依次减小来提取堆栈中的数据 到要恢复的寄存器列表中,PUSH 和 POP 的另外一种写法是“STMFD SP!”和“LDMFD SP!”,功能和上面的相同

    3.4 跳转指令

    跳转一般有两种操作:

  • 直接使用跳转指令 B、BL、BX 等
  • 直接向 PC 寄存器里面写入数据
  • 指令跳转:

    指令

    描述

    B

    跳转到 label,如果跳转范围超过了+/-2KB,可以指定 B.W 使用 32 位版本的跳转指令, 这样可以得到较大范围的 跳转 BX 间接跳转,跳转到存放于 Rm 中的地址处,并且切换指令集

    BL

    跳转到标号地址,并将返回地址保存在 LR 中。

    BLX

    结合 BX 和 BL 的特点,跳转到 Rm 指定的地址,并将返回地 址保存在 LR 中,切换指令集

    • B指令

    B 指令会将 PC 寄存器的值设置为跳转目标地址, 一旦执行 B 指 令,ARM 处理器就会立即跳转到指定的目标地址,一般用于不会返回的跳转,如下为启动程序完成后最后跳转到main函数开始执行C语言程序!

    1 _start: 2 3 ldr sp,=0X80200000 @设置栈指针 4 b main @跳转到 main 函数
    • BL指令

    BL 指令相比 B 指令,在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以 通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行,一般用于需要返回的跳转,比如子程序调用,或者进入中断的情况,如下就是进入中断跳转

    1 push {r0, r1} @保存 r0,r1 2 cps #0x13 @进入 SVC 模式,允许其他中断再次进去 3 5 bl system_irqhandler @加载 C 语言中断处理函数到 r2 寄存器中 6 7 cps #0x12 @进入 IRQ 模式 8 pop {r0, r1} 9 str r0, [r1, #0X10] @中断执行完成,写 EOIR

    3.5 算术运算指令

    汇编中也可以进行加减乘除算术运算,指令如下:

    指令

    计算公式

    备注

    ADD Rd, Rn, Rm

    Rd = Rn + Rm

    加法运算,指令为 ADD

    ADD Rd, Rn, #立即数

    Rd = Rn + #立即数

    加法运算,指令为 ADD

    ADC Rd, Rn, Rm

    Rd = Rn + Rm + 进位

    带进位的加法运算,指令为 ADC

    ADC Rd, Rn, #立即数

    Rd = Rn + #立即数+进位

    进位的加法运算,指令为 ADC

    SUB Rd, Rn, Rm

    Rd = Rn – Rm

    减法

    SUB Rd, #立即数

    Rd = Rd - #立即数

    减法

    SUB Rd, Rn, #立即数

    Rd = Rn - #立即数

    减法

    SBC Rd, Rn, #立即数

    Rd = Rn - #立即数– 借位

    带借位的减法

    SBC Rd, Rn ,Rm

    Rd = Rn – Rm – 借位

    带借位的减法

    MUL Rd, Rn, Rm

    Rd = Rn * Rm

    乘法(32 位)

    UDIV Rd, Rn, Rm

    Rd = Rn / Rm

    无符号除法

    SDIV Rd, Rn, Rm

    Rd = Rn / Rm

    有符号除法

    3.6 逻辑运算指令

    汇编中也有C语言中的逻辑运算,比如与运算或运算等等,具体如下表

    指令

    计算公式

    备注

    AND Rd, Rn

    Rd = Rd &Rn

    按位与

    AND Rd, Rn, #立即数

    Rd = Rn & #立即数

    按位与

    AND Rd, Rn, Rm

    Rd = Rn & Rm

    按位与

    ORR Rd, Rn

    Rd = Rd |Rn

    按位或

    ORR Rd, Rn, #立即数

    Rd = Rn |#立即数

    按位或

    ORR Rd, Rn, Rm

    Rd = Rn |Rm

    按位或

    BIC Rd, Rn

    Rd = Rd & (~Rn)

    位清除

    BIC Rd, Rn, #立即数

    Rd = Rn & (~#立即数)

    位清除

    BIC Rd, Rn , Rm

    Rd = Rn & (~Rm)

    位清除

    ORN Rd, Rn, #立即数

    Rd = Rn |(#立即数)

    按位或非

    ORN Rd, Rn, Rm

    Rd = Rn |(Rm)

    按位或非

    EOR Rd, Rn

    Rd = Rd ^ Rn

    按位异或

    EOR Rd, Rn, #立即数

    Rd = Rn ^ #立即数

    按位异或

    &为与,|为或,~为按位取反,^为异或,! 为取反



      你可能想看:

      扫描二维码推送至手机访问。

      版权声明:本文由皇冠云发布,如需转载请注明出处。

      本文链接:https://www.idchg.com/info/26887.html

      分享给朋友:

      “支持arm架构windows 10” 的相关文章

      台湾VPS:高效、稳定且安全的虚拟专用服务器解决方案

      台湾VPS,即虚拟专用服务器,是一种通过虚拟化技术将物理服务器划分为多个独立服务器的解决方案。这种服务不仅为用户提供独享的资源和灵活的管理权限,还能够提升性能和效率。在我使用台湾VPS的过程中,它让我深刻体会到这一技术的便利与强大。 台湾VPS的独特之处在于其地理位置和网络基础设施。位于东亚的台湾,...

      提升国际数据传输质量的9929线路分析与应用

      谈到9929线路,首先让我给大家介绍一下AS9929线路的基本情况。这条线路是中国联通为了满足国际市场的需求而推出的一种IP传输服务专线。它的起点在香港,通过海底光缆将中国与亚太及北美地区紧密连接。同时,这条线路还在欧洲和非洲设立了多个重要的网络节点(POP点),这就为跨国数据传输提供了坚实的基础。...

      如何利用VPS优惠码省钱并提升服务体验

      在互联网上,虚拟专用服务器(VPS)已经成为许多个人和企业的首选方案之一。VPS允许用户拥有一个独立的、完全可控的服务器环境,同时又节省了许多硬件投资成本。对于那些刚开始接触VPS的朋友来说,了解VPS的定义及其用途是非常重要的。在这里,VPS不仅仅是一个存储空间,它能为你的业务提供强大的运算能力和...

      跑步的全面指南:基础知识、路线选择与心理技巧

      跑步的基础知识 跑步,这项简单又有效的运动,拥有着悠久的历史和丰富的文化背景。追溯到古代,跑步不仅是人类生存的必要技能,更是一项重要的竞技活动。历史上,古希腊的奥林匹克运动会中,长跑是最受欢迎的项目之一。而在中国,长跑也早在古代就已经成为士兵训练和民间竞技的一部分。随着时代发展,跑步逐渐演变为一种大...

      如何使用 Linode Backups 保障数据安全与恢复

      在现代数字世界中,数据的安全性与可恢复性至关重要。Linode Backups 正是为此而生的一项服务。Linode Backups 是 Linode 提供的一项付费服务,旨在自动化用户数据的备份过程,能够让用户更加轻松地管理和恢复数据。对我来说,这项服务让人感到安心,尤其是在处理重要项目时,存在这...

      /16子网掩码的配置与应用指南 | 实现高效网络管理

      为什么选择/16的子网掩码 选择/16的子网掩码常常让人感到有些陌生。对我来说,这个数字不仅仅是一个技术参数,它蕴含着网络设计的深刻意义。首先,子网掩码的基本概念就如同我们在城市中划分区域,/16实际上表示有65536个可用IP地址。这么广阔的空间对于需要大量设备联网的环境,如企业或大型组织,尤其重...