ARM体系结构(5)

您所在的位置:网站首页 学习汇编的软件 ARM体系结构(5)

ARM体系结构(5)

2023-04-14 23:41| 来源: 网络整理| 查看: 265

什么是ARM GNU汇编伪指令?

有一些特殊指令助记符,没有相对应的操作码,前面写的基本指令都是有操作码的。

它们完成的操作为伪操作,也即是仅仅在为完成汇编程序做各种准备工作,仅仅在汇编阶段起作用。

不是机器指令,只是用来控制(或指导)汇编器帮我们做一些事情。

如:

定义一个变量预处理声明数据定义伪指令

数据定义伪操作一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。常见的数据定义伪操作有如下几种:

@(unsigned)char ch = 0x11; 分配一个字节的内存,并且把0x11装入到内存

ch:

.byte 0x11

@(unsigned)short sh = 0x1234; 分配两个字节的内存,并且把0x1234装入到内存

sh:

.short 0x1234

@(unsigne)int it = 0x12345678; 分配四个字节的内存,并且把0x12345678装入到内存

it:

.word 0x12345678

@(unsigne)long lg = 0x12345678; 分配四个字节的内存,并且把0x12345678装入到内存

lg:

.long 0x12345678

@(unsigned) long long ll = 0x1234567812345678; 分配八个字节的内存,并且把0x1234567812345678装入到内存

ll:

.quad 0x1234567812345678

@float ft = 3.2f; 分配四个字节的内存,并且把3.2f装入到内存fq

ft:

.float 0f3.2

@char str[] = "abc"; 分配四个字节的内存,并且把"abc\0"装入到内存

str:

.string "abc"

@char asc[] = {'a', 'b', 'c'}; 分配三个字节的内存,并且把"abc"装入到内存

asc:

.ascii "abc\0" @需要手动添加’\0’

.equ/.set: 赋值语句, 格式如下: .equ(.set) 变量名,表达式 例如: .equ abc 3 @让abc=3

预处理伪指令

宏定义

.macro {$label} macroname {$parameter{,$parameter}…}

....

.endm

样例程序, 如下面c语言宏定义:

#define xchg(regs, regd) \do { \int tmp = (regs); \(regs) = (regd); \(regd) = (tmp); \} while (0)

用汇编macro表示如下:

.macro xchg regs,regdmov r0,\regs @如果宏使用参数,那么在宏体中使用该参数时添加前缀“\”。mov \regs,\regdmov \regd,r0.endm

使用的时候直接

xchg r1,r2

伪指令 ldr & adr

ldr(用于读取地址的时候是伪指令)

Ldr 寄存器,=const addr:ldr r0,=0x1234 @r0 = 0x1234Ldr 寄存器,=labeladdr:Ldr r0,=label @r0=label的地址Ldr 寄存器,labeladdr:Ldr r0,label @ label的地址处数据内容放入r0

Adr

Adr 寄存器, label @label的地址放入寄存器

演示代码:

ldr r0,add_func #add_func处指令值存入r0 不是伪指令nopnopadr r0,add_func #add_func地址存入r0nopnopldr r0,=add_func #add_func地址存入r0add_func: add r0,r0,r1mov pc,lr

反汇编出来:

40000018: e59f0014 ldr r0, [pc, #20] ; 40000034 处的数据4000001c: e1a00000 nop ; (mov r0, r0)40000020: e1a00000 nop ; (mov r0, r0)40000024: e28f0008 add r0, pc, #8 ;当前pc值+add_function label偏移值相对地址,#8 就是label偏移值40000028: e1a00000 nop ; (mov r0, r0)4000002c: e1a00000 nop ; (mov r0, r0)40000030: e59f0008 ldr r0, [pc, #8] ; pc + 8 等于 40000040,最后一行,40000040地址处值是40000034,R0 = 40000034 ,绝对地址40000034 :40000034: e0800001 add r0, r0, r140000038: e1a0f00e mov pc, lr

4000003c :4000003c: eafffffe b 4000003c 40000040: 40000034 .word 0x40000034

所以可以看到,adr是相对寻址,pc+偏移地址 ,adr伪指令编译后转换成add(pc+8+offset)或者sub(pc+8-offset)指令,立即数有个范围。Ldr是绝对寻址。

指定指令集.arm 这条伪指令开始的指令全部是arm指令.thumb 这条伪指令开始的指令全部是thumb指令定义段.section .text 定义代码段.section .data 定义数据段.section .bss 定义未初始化的数据段.section 段名 自定义段对齐

.align n 2^n对齐

例:

.align 2 4字节对齐.align 3 8字节对齐

.global/.globl

汇编文件中,没有.globl声明的标号为本文件内使用, 相当于C语言中加了static的全局变量

例:

glb: @static int glb = 0x12; .word 0x12

.globl glb glb: @int glb = 0x12; .word 0x12

.end

汇编文件结束符号

符号

代码行中的注释符号: ‘@’整行注释符号: ‘#’语句分离符号: ‘;’立即数前缀: ‘#’ 或 ‘$’

局部标号(段内使用)

主要在局部范围内使用而且局部标号可以重复出现。它由两部组成开头是一个0-99直接的数字局部标号 后面加“:”

f:front指示编译器只向前搜索

b:back指示编译器只向后搜索

例子:

1: ......

b 1b @向后找(向上找)label 1,调到label 1 b 2f @向前找(向下找)label 2,跳到label 22: .....

协处理器处理指令

在基于ARM的嵌入式应用系统中,存储系统通常是通过系统控制协处理器CP15完成的。CP15包含16个32位的寄存器,其编号为0~15。

访问CP15寄存器的指令

MCR ARM寄存器到协处理器寄存器的数据传送,如果协处理器不能成功地执行该操作,将产生未定义的指令异常中断。MRC 协处理器寄存器到ARM寄存器的数据传送

指令语法格式:

MCR{cond} p15,{opcode_1},,,{,opcode_2}

其中{cond} 就是可选的执行条件p15就是指定哪个协处理器,有两个协处理器,一个15一个14为协处理器将要执行的操作的操作码,对于CP15来说,永远为ob00,即0,如果不是,结果不同预知作为源寄存器的ARM寄存器目标寄存器的协处理器寄存器和两者组合决定对协处理器寄存器进行所需要的操作,如果没有指定,则将为为C0,opcode_2为0,否则可能导致不可预知的结果。

指令语法格式:

MRC{} p15,< opcode_1>,,,{,}

各参数解释同上MCR指令。

例子:

@告诉arm core异常向量表的位置在_sart label处,其实就是0x40008000 ldr r0,=_start mcr p15,0,r0,c12,c0,0



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3