ARM学习笔记(汇编篇)



前言

使用不同的编译器,指导编译器编译链接的文件lds稍许不一样,现在分arm-linux-gnueabi-gcc、IAR、Keil分开记录


提示:以下是本篇文章正文内容,下面案例可供参考

一、GCC

语法

marco

macro为定义一个宏,.macro为首,.endm为尾,。
在其他文件调用此宏定义,即可用定义的代码段替换宏。下面是一个宏定义示例。

.macro CPWAIT reg
	mrc	p15, 0, \reg, c2, c0, 0
	mov	\reg, \reg
	sub	pc, pc, #4
.endm

rept

在汇编语言中,reptendr 通常是用于创建重复的代码块(重复宏)。rept 指令用于开始一个重复块,然后可以在其中重复执行一段代码,直到遇到 endr 指令为止。这样可以方便地生成重复的汇编代码。

例如,以下是一个使用 reptendr 的示例:


.section .mmutable, "a"
mmutable:
	.align	14
	/* 0x00000000 - 0xffe00000 : 1:1, uncached mapping */
	.set	__base, 0
	.rept	0xfff
	.word	(__base << 20) | 0xc12
	.set	__base, __base + 1
	.endr

	/* 0xfff00000 : 1:1, cached mapping */
	.word	(0xfff << 20) | 0x1c1e

在上面的示例中,rept 0xfff 表示下面的代码块将被重复执行 0xfff 次,然后 endr 表示重复块的结束。因此,其中的代码会被复制和粘贴 0xfff 次,作用就是建立了一张mmu表。

section

.section 是汇编语言中的一个指令,通常用于将汇编代码分组为不同的节(sections)。在汇编器中,节是指代码或数据的逻辑分区,用于将不同类型的内容分开存放。每个节可以包含代码、数据、常量等不同类型的信息。

在大多数汇编语言中,.section 指令用于创建不同类型的节,并且可以指定节的属性和名称。具体的语法和属性取决于所使用的汇编器和体系结构。

以下是一个示例,展示了在某些汇编语言中使用 .section 的方式:

.section .data
    data_value: .word 42

.section .text
    .global main
main:
    mov r0, r1
    bx lr

在这个示例中,.section .data 表示接下来的代码将位于名为 .data 的节中,这通常用于存放数据。.section .text 表示接下来的代码将位于名为 .text 的节中,这通常用于存放指令代码。结合lds文件,便可以把section存放在指定区域了。

.extern

.extern用于在汇编文件中声明外部变量

.set

在GCC中,.set 汇编伪指令用于为汇编代码中的符号(如标签或变量)分配一个特定的数值。这通常用于在汇编代码中定义常数或指定地址。(ps:相当于c语言中的宏定义#define)

.set BUFFER_SIZE, 100

以上是一个示例,假设你要在汇编代码中定义一个名为 BUFFER_SIZE 的常数,其大小为 100。然后,在你的汇编代码中,你可以使用 BUFFER_SIZE 而不必在每个地方使用数字 100。

.align

//.align 指令的一般形式是
.align <alignment>

// 对齐到4字节边界
.align 2

// 对齐到8字节边界
.align 3

// 对齐到16字节边界
.align 4

其中, 表示要对齐的边界,通常是2的幂。例如,.align 4 将当前位置对齐到4字节边界,.align 8 将当前位置对齐到8字节边界,以此类推。

.org

.org 是一种汇编伪指令,通常用于设置程序计数器(PC)或地址计数器(AC),以指示汇编器生成的代码或数据应该放置在特定的内存地址或位置。这在编写汇编程序时非常有用,因为它允许你控制生成的二进制代码的位置。

例如,假设你正在编写一个汇编程序,想要将一段代码放置在内存的地址0x1000处,你可以使用以下指令:

.org 0x1000
//后续跟随代码块,即生成在0x1000位置

专业名词

Post-index

Post-index 是一种内存地址计算方式,它表示在访问内存后,将索引添加到基地址。这是在ARM汇编语言中的一种寻址模式,通常与加载(Load)和存储(Store)指令一起使用。

以下是一个示例,使用 Post-indexing 进行加载操作的 ARM 汇编代码:

ldr x0, [x1], #4

在这个例子中:

ldr 是 Load 指令,用于从内存中加载数据到寄存器。
x0 是目标寄存器,用于存储加载的数据。
[x1], #4Post-index 寻址模式。它表示从存储器地址 x1 处加载数据到 x0,然后将 x1 的值增加 4 个字节(32位)。
这个指令的效果是,首先加载 x1 指向的内存位置的数据到 x0,然后将 x1 的值增加 4,使其指向下一个数据元素。(ps :类似于c语言中的i++中的++)

Pre-Index

Pre-indexing 是一种内存地址计算方式,与 Post-indexing 相对,它表示在访问内存之前将索引添加到基地址。在ARM汇编语言中,Pre-indexing通常与加载(Load)和存储(Store)指令一起使用。

以下是一个使用 Pre-indexing 进行加载操作的 ARM 汇编代码示例:

ldr x0, [x1, #4]!

在这个例子中:

ldr 是 Load 指令,用于从内存中加载数据到寄存器。
x0 是目标寄存器,用于存储加载的数据。
[x1, #4]! 是 Pre-indexing 寻址模式。它表示将 x1 的值增加 4 个字节(32位)后,再从存储器地址 x1 处加载数据到 x0。
这个指令的效果是,在访问内存之前,将 x1 的值增加 4,然后加载这个新地址处的数据到 x0。


二、IAR

汇编

关键字详解
sectionsection关键字一般放在s文件首部,它的一般形式如下SECTION .vectors:CODE:NOROOT(2),section代表一个段的开始,.vector代表段名,后面跟的是属性,具体含义要参考文档
PUBLIC在这里插入图片描述将本文件的函数做外部声明,声明之后可在c函数中调用,如Assembly_causeUndefine函数即可在c文件中调用
EXTERN声明一个外部函数,然后可在本文件中调用,如在c文件中实现了一个PrintHello,可在本文件中调用

扩展内联汇编

//内敛汇编基本格式
asm ( assembler template
        : output operands                /*在MOV R0,R1中,R1->R0,R1为output*/
        : input operands                 /*在MOV R0,R1中,R1->R0,R0为input*/
        : list of clobbered registers   /* optional */
);

output operandsinput operands分别代表输入输出函数
clobbered registers指明修改的寄存器或者内存,如果某个指令改变了某个寄存器的值,我们就必须在asm中第三个冒号后的Clobber List中标示出该寄存器。为的是通知GCC,让其不再假定之前存入这些寄存器中的值依然合法。输入输出寄存器不用放Clobber List中,因为GCC能知道asm将使用这些寄存器。(因为它们已经显式被指定输入输出标出在输入输出部分) 。其他使用到的寄存器,无论是显示还是隐式的使用,必须在clobbered list中标明。

//具体代码
void print_r0r1(int r0, int r1,int r2,int r3)
{
    int value,addr;
    fmsh_print("r0 0x%x r1 0x%x\n",r0,r1);
    asm(
        "MOV %[op1], SP\n"
        "LDR %[op2], [SP]\n"
        :
        :[op1]"r"(addr),[op2]"r"(value)
        :
    );
    fmsh_print("SP addr 0x%x value 0x%x\n",addr,value);
}

// 32 位写操作
void write32(uint32_t value, volatile uint32_t *address) {
    __asm__ __volatile__(
        "str %w[value], [%[addr]]"
        : : [value] "r" (value), [addr] "r" (address)
        : "memory"
    );
}

// 32 位读操作
uint32_t read32(volatile uint32_t *address) {
    uint32_t result;
    __asm__ __volatile__(
        "ldr %w[result], [%[addr]]"
        : [result] "=r" (result)
        : [addr] "r" (address)
        : "memory"
    );
    return result;
}

IAR汇编帮助文档

在IAR IDE内,如下图操作,可获得IAR提供汇编指导文档
在这里插入图片描述


三、KEIL


四、链接脚本

https://sourceware.org/binutils/docs/ld/Scripts.html#Scripts

相关参考资料:
https://www.jianshu.com/p/1782e14a0766

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值