在ARM汇编编程中如何指定某段程序的存储地址
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在ARM汇编编程中如何指定某段程序的存储地址相关的知识,希望对你有一定的参考价值。
我需要把某一段程序编译后存储在指定地址的程序存储器中,但是不知道在编程中怎么来指定存储地址?
在要指定代码的存储空间不是一件特别简单的事情,尤其是你想为某个或某几个函数指定具体的地址。1,编译器只有在最终的Link阶段才会为代码和数据分配内存地址,因此指定代码段的地址一般是通过写一个link脚本来进行的。Link阶段时,编译器的Linker会读取你写的Link脚本,并且按照脚本的规定给代码分配地址。
2,根据ARM开发工具的不同,link脚本的语法和形式也有所不同。ARM MDK,ARM ADS,Eclips+GCC,Linux GCC, ARM Realview等开发工具都支持Link脚本。
如果你英文还可以,建议你直接找到开发工具的Help手册去研究。如果你英语实在不行,也可以把开发工具名称和你代码的具体情况告诉我,我帮你看看。 参考技术A 在要指定代码的存储空间不是一件特别简单的事情,尤其是你想为某个或某几个函数指定具体的地址。
1,编译器只有在最终的Link阶段才会为代码和数据分配内存地址,因此指定代码段的地址一般是通过写一个link脚本来进行的。Link阶段时,编译器的Linker会读取你写的Link脚本,并且按照脚本的规定给代码分配地址。
2,根据ARM开发工具的不同,link脚本的语法和形式也有所不同。ARM MDK,ARM ADS,Eclips+GCC,Linux GCC, ARM Realview等开发工具都支持Link脚本。
如果你英文还可以,建议你直接找到开发工具的Help手册去研究。如果你英语实在不行,也可以把开发工具名称和你代码的具体情况告诉我,我帮你看看。 参考技术B C语言与汇编语言混合编程应遵守的规则
ARM编程中使用的C语言是标准C语言,ARM的开发环境实际上就是嵌入了一个C语言的集成开发环境,只不过这个开发环境与ARM的硬件紧密相关。
在使用C语言时,要用到和汇编语言的混合编程。若汇编代码较为简洁,则可使用直接内嵌汇编的方法;否则要将汇编程序以文件的形式加入到项目中,按照ATPCS(ARM/Thumb过程调用标准,ARM/Thumb Procedure Call Standard)的规定与C程序相互调用与访问。
在C程序和ARM汇编程序之间相互调用时必须遵守ATPCS规则。ATPCS规定了一些子程序间调用的基本规则,哪寄存器的使用规则,堆栈的使用规则和参数的传递规则等。
1)寄存器的使用规则
子程序之间通过寄存器r0~r3来传递参数,当参数个数多于4个时,使用堆栈来传递参数。此时r0~r3可记作A1~A4。
在子程序中,使用寄存器r4~r11保存局部变量。因此当进行子程序调用时要注意对这些寄存器的保存和恢复。此时r4~r11可记作V1~V8。
寄存器r12用于保存堆栈指针SP,当子程序返回时使用该寄存器出栈,记作IP。
寄存器r13用作堆栈指针,记作SP。寄存器r14称为链接寄存器,记作LR。该寄存器用于保存子程序的返回地址。
寄存器r15称为程序计数器,记作PC。
2)堆栈的使用规则
ATPCS规定堆栈采用满递减类型(FD,Full Descending),即堆栈通过减小存储器地址而向下增长,堆栈指针指向内含有效数据项的最低地址。
3)参数的传递规则
整数参数的前4个使用r0~r3传递,其他参数使用堆栈传递;浮点参数使用编号最小且能够满足需要的一组连续的FP寄存器传递参数。
子程序的返回结果为一个32位整数时,通过r0返回;返回结果为一个64位整数时,通过r0和r1返回;依此类推。结果为浮点数时,通过浮点运算部件的寄存器F0、D0或者S0返回。
2、汇编程序调用C程序的方法
汇编程序的书写要遵循ATPCS规则,以保证程序调用时参数正确传递。在汇编程序中调用C程序的方法为:首先在汇编程序中使用IMPORT伪指令事先声明将要调用的C语言函数;然后通过BL指令来调用C函数。
例如在一个C源文件中定义了如下求和函数:
int add(int x,int y)
return(x+y);
调用add()函数的汇编程序结构如下:
IMPORT add ;声明要调用的C函数
……
MOV r0,1
MOV r1,2
BL add ;调用C函数add
……
当进行函数调用时,使用r0和r1实现参数传递,返回结果由r0带回。函数调用结束后,r0的值变成3。
3、C程序调用汇编程序的方法
C程序调用汇编程序时,汇编程序的书写也要遵循ATPCS规则,以保证程序调用时参数正确传递。在C程序中调用汇编子程序的方法为:首先在汇编程序中使用EXPORT伪指令声明被调用的子程序,表示该子程序将在其他文件中被调用;然后在C程序中使用extern关键字声明要调用的汇编子程序为外部函数。
例如在一个汇编源文件中定义了如下求和函数:
EXPORT add ;声明add子程序将被外部函数调用
……
add ;求和子程序add
ADD r0,r0,r1
MOV pc,lr
……
在一个C程序的main()函数中对add汇编子程序进行了调用:
extern int add (int x,int y); //声明add为外部函数
void main()
int a=1,b=2,c;
c=add(a,b); //调用add子程序
……
当main()函数调用add汇编子程序时,变量a、b的值会给了r0和r1,返回结果由r0带回,并赋值给变量c。函数调用结束后,变量c的值变成3。
4、C程序中内嵌汇编语句
在C语言中内嵌汇编语句可以实现一些高级语言不能实现或者不容易实现的功能。对于时间紧迫的功能也可以通过在C语言中内嵌汇编语句来实现。内嵌的汇编器支持大部分ARM指令和Thumb指令,但是不支持诸如直接修改PC实现跳转的底层功能,也不能直接引用C语言中的变量。
嵌入式汇编语句在形式上独立定义的函数体,其语法格式为:
__asm
指令[;指令]
……
[指令]
其中“__asm”为内嵌汇编语句的关键字,需要特别注意的是前面有两个下划线。指令之间用分号分隔,如果一条指令占据多行,除最后一行外都要使用连字符“\”。
5、基于ARM的C语言与汇编语言混合编程举例
下面给出了一个向串口不断发送0x55的例子:
该工程的启动代码使用汇编语言编写,向串口发送数据使用C语言实现,下面是启动代码的整体框架:
……
IMPORT Main
AREA Init,CODE,READONLY;
ENTRY
……
BL Main ;跳转到Main()函数处的C/C++程序
……
END ;标识汇编程序结束
下面是使用C语言编写的主函数:
#include "..\inc\config.h" //将有关硬件定义的头文件包含进来
unsigned char data; //定义全局变量
void main(void)
Target_Init(); //对目标板的硬件初始化
Delay(10); //延时
data=0x55; //给全局变量赋值
while(1)
Uart_Printf("%x",data); //向串口送数
Delay(10);
arm如何对ddr分区存储
adrp指令1)创建项目在mian 文件中写个方法然后执行此方法在汇编模式调试断点。详细操作
将debug -> Debug Overflow -> Always Show DisAssembly 选中运行查看混编代码。如果想恢复再点下就可以了.
2) 得到以下界面
3)原理 adrp操作步骤adrp x0, 1
1. 将1的值,左移12位 1 0000 0000 0000 == 0x1000
2.将PC寄存器的低12位清零 0x1045228b0 ==> 0x104522000
3.将将1 和 2 的结果相加 给 X0 寄存器!!
注:地址为pc寄存器左边的地址,adrp是找出要获取参数的地址范围,然后下个pc寄存器执行的代码会定位到准确的物理地址。
指令区域
由于adrp的为范围寻址并不会精确到具体地址所以地址的最后三位,即12bit位为0是需要系统下一步执行的时候补上的。
根据cpu总线的计算规则12bit相当于12根总线器地址范围为2的12次方即4KB。
点击阅读全文
打开CSDN APP,看更多技术内容
ARM64基础8:A64其他常用指令_科学边界的博客_arm64 svc...
ADRP: 加载PC相对地址,label地址,并且4KB对齐,范围+/- 4GB; /* others inst */ .align 3 .global my_test_data my_test_data: .dword 0x12345678abcdeeff .global adrp_test adrp_test: adr x0, my_test_data adrp x1, ...
继续访问
arm64 linux 中断,ARM64 中断处理流程_论智的博客
adrp x1, handle_arch_irq ldr x1, [x1, #:lo12:handle_arch_irq] mov x0, sp blr x1 .endm 继续往下追踪,在文件 arch/arm64/kernel/irq.c 中,handle_arch_irq 是一个全局函数变量,通过函数 set_handle_irq 将该变量设...
继续访问
最新发布 ARM64体系结构编程4-比较指令和其他指令
判断 cond 是否为真,如果为真,就返回 Xn,否则,返回 Xm,把结果写入 Xd 寄存器中,
继续访问
ARM64体系结构编程3-算数和移位指令
b 指令的操作由后缀 cs 决定,cs 表示判断是否发生无符号溢出,3 + not(2) + 1 , not(2) = 0xfffffffffffffffd , 3 + 0xfffffffffffffffd + 1 = 1, ,这个过程发生了溢出,C 标志位置为 1, 所以 b.cs 的判断条件成立,跳转到标签 1 处,继续执行。BFI 指令把 X1 寄存器中的 Bit[3,0] 设置为 X0 寄存器中的 Bit[7,4], X0 寄存器中的 Bit[7,4] ,X0 寄存器的值是 0x50。
继续访问
ARM64启动过程分析_内核新视界的博客
不过adrp是page对齐的(adrp中的p就是page的意思),boot_args这个符号当然不会是page size对齐的,因此不能直接使用adrp,而是使用adr_l这个宏进行处理。 这里使用dmb sy指令,在armv8手册中说明:除了dc zva外,所有指定地址的数据缓存指令...
继续访问
ARM 64指令小记_FarmGuo的博客_arm64 指令
call 为x86的跳转指令 bl 为arm的跳转指令 其他 adrp 指令,将pc低12位清零,然后将立即数左移12位进行相加 adrp x8, 10,此时pc 0x00000001026c4478 x8 = 0x00000001026c4000 + 0xa000 = 0x00000001026ce000 在第一次由adrp取得页...
继续访问
arm64 寄存器
arm64 寄存器
继续访问
Linux内存管理:知识点总结(ARM64)
https://mp.weixin.qq.com/s/7zFrBuJUK9JMQP4TmymGjA 目录 Linux内存管理之CPU访问内存的过程 虚拟地址转换为物理地址的本质 Linux内存初始化 创建启动页表 Linux是如何组织物理内存的? Linux分区页框分配器 Linux页框分配器之伙伴算法 Buddy 分配算法 Buddy 分配函数 Linux分区页框分配器之水位 水位初始化 Linux页框分配器之内存碎片化整理 什么是内存碎片化 碎片化整理算法 碎片化整理的三
继续访问
arm32位和arm64位架构、寄存器和指令差异分析总结_yebanguhe的博客-CSDN...
ARM32位neon寄存器和ARM64位neon寄存器差异: 32位下 NEON寄存器: 包括: 32个S寄存器,S0~S31,(单字,32bit) 32个D寄存器,D0~D31,(双字,64bit) 16个Q寄存器,Q0~Q15,(四字,128bit) ...
继续访问
[register]-ARM64重要寄存器介绍_代码改变世界ctw的博客_sctl...
ENTRY(idmap_cpu_replace_ttbr1) mrs x2, daif //将DAIF寄存器的值,保存在X2寄存器中 msr daifset, #0xf //对DAIF寄存器的值的bit0-3位置1 adrp x1, empty_zero_page msr ttbr1_el1, x1 isb tlbi vmalle1 dsb nsh ...
继续访问
万字整理,肝翻Linux内存管理所有知识点
Linux的内存管理可谓是学好Linux的必经之路,也是Linux的关键知识点,有人说打通了内存管理的知识,也就打通了Linux的任督二脉,这一点不夸张。有人问网上有很多Linux内存管理...
继续访问
arm64汇编adrp指令作用和使用举例
文章目录adrp作用举例1举例2 adrp作用 adrp 寄存器,立即数,作用是把pc寄存器跟立即数按照一定规则计算后赋值给寄存器. 举例1 adrp x8,1 adrp指令是给寄存器赋值.赋值的规则是: 先把pc寄存器里的数值先按照16进制表示,后3位清零,再把adrp 右边的立即数,左移3位,也就是在末尾+3个0 .然后让2个结果相加. 例如上面的例子 pc = 0x0000000104ff6754 然后把pc后3位清零 得到0x0000000104ff6000 adrp x8,1 右边的立即数
继续访问
arm64 架构之入栈/出栈操作_maimang09的博客_arm64 stp
arm64 架构之入栈/出栈操作 - 掘金31 个R0 ~ R30,每个寄存器可以存取一个 64 位大小的数。 当使用 x0 - x30访问时,是一个 64位的数;当使用 w0 - w30访问时,是一个 32 位的数,访问的是寄存器的 低 32 位,如图: (也...
继续访问
ARM64基础7:A64的比较和跳转指令
pstate的nzcv标志位 条件标志位 描述 N 负数标志(上次运算结果为负值,则N=1,否则N=0) Z 上次运算结果为0 C 对于加法运算,无符号溢出,C=1, 其他不变 V 有符号溢出 条件码 后缀助记符 标志位 定义 0000 EQ Z=1 相等 0001 NE Z=0 不相等 0010 CS/HS C=1 无符号大于或者等于 0011 CC/LO C=0 无符号小于 0100 MI N=1 负值 0101 PL N=0 正值或0
继续访问
ARMv8汇编指令-adrp、adr、adr_l
1.概述 在阅读Linux内核代码时,经常能碰到汇编代码,网上能查的资料千篇一律,大多都描述的很模糊。俗话说,实践是检验真理的唯一标准,我们就参考官方文档,自己写汇编代码并反汇编,探寻其中的奥妙。 2.adrp 在Linux内核启动代码primary_entry中,使用adrp指令获取Linux内核在内存中的起始页地址,页大小为4KB,由于内核启动的时候MMU还未打开,此时获取的Linux内核在内存中的起始页地址为物理地址。adrp通过当前PC地址的偏移地址计算目标地址,和实际的物理无关,因此属于位置无关码
继续访问
ARM64汇编入门
现在iOS设备几乎已经都是ARM64架构,此外,Mac M1芯片的电脑也是基于ARM64架构,本文首先对ARM64汇编做一个简单的介绍,然后通过一个Swift枚举的汇编代码窥探枚举的底层实现逻辑,发现了一个超出意料之外的结果。
继续访问
ARM指令解析之ADRP
先反汇编 $ aarch64-linux-gnu-objdump -d -S vmlinux > vmlinux.txt 然后再分析5.0内核的相关指令 8068709 ffff000011c30040 <__create_page_tables>: 8068710 mov x28, lr 8068711 ffff000011c30040: aa1e03fc mov x28, x30 8068712 adrp ...
继续访问
arm64汇编ldr和ldur和ldp指令在xcode中传入地址调用方法
文章目录ldr指令的作用arm.h文件中的声明oc文件中的调用 ldr指令的作用 ldr作用是把 中括号[]中的地址里存的值存入到前面的寄存器中 有下面几种格式: LDR R0, [R1] ; R0←[R1] LDR R0,[R1,#4] ;R0←[R1+4] LDR R0,[R1,#4]! ;R0←[R1+4]、R1←R1+4 LDR R0,[R1] ,#4 ;R0←[R1]、R1←R1+4 LDR R0,[R1,R2] ;R0←[R1+R2] arm.h文件中的声明 #ifndef arm_h #def
继续访问
adrp指令
转自: adrp x0, 1 其实做了下面的步骤 1. 将1的值,左移12位 1 0000 0000 0000 == 0x1000 2.将PC寄存器的低12位清零0x104bee870 ==> 0x104bee000,这里的PC寄存器的值是到adrp x0 1的那里的PC寄存器里面的值 3.将1 和 2 的结果相加给X0 寄存器!! ...
继续访问
ARM64内联汇编
ARM64内联汇编简单介绍
继续访问
ARM64-memcpy.S 汇编源码分析
汇编源代码文件: 内存拷贝优先级: 数据块地址: 源码分析: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
继续访问
热门推荐 ARM指令浅析2(adrp、b)
其实这篇文章的初衷是分析alpha架构下和arm架构下,为什么相同的用例arm生成的汇编指令会少一些,由于工作的保密性,暂时不介绍alpha生成的指令,因此先来主要分析一下,arm架构之所以少生成汇编指令的原因——adrp指令。 环境依然是ARM架构下的gcc编译器,编译选项为 -O2。 4.Adrp指令 再来看一下arm编译器中的adrp指令 在了解adrp...
继续访问
ARM v8指令集(手册)
1、Conditional Branch - B.cond labelBranch: conditionally jumps to program-relative label if cond is true. - CBNZ Wn, labelCompare and Branch Not Zero: conditionally jumps to program-relative label i
继续访问
arm64汇编篇-常用指令篇
本篇主要记载汇编语言中常用的指令及其代表的含义,实时不断跟新。 CMP w0 , w1 CMP (compare)的意思是比较的意思 相当于将w0减去w1但是不会改变两个寄存器的值即两个寄存器不会变化,但是其结果会影响cpsr状态寄存器的标记值(nzcv)。(把一个寄存器的内容和另一个寄存器的内容或立即数进行比较。但不存储结果,只是正确的更改标志。) BL 跳转到标号处执行 B...
继续访问
ARMv8架构下程序运行时栈帧布局
结合ARM相关文档和在飞腾机器上使用gdb调试实际程序来研究ARM的指令和运行时栈帧布局。主要参考了三篇文档。 1. Procedure Call Standard for the ARM 64-bit Architecture。参考其中的过程调用标准和运行时栈帧布局。 2. ARMv8 Instruction Set Overview。参考其中的指令概述。 3. ARM Com
继续访问
ARM64汇编(一)
CPU概述 CPU的内部部件有寄存器、运算器和控制器。其中运算器负责信息处理,由CPU硬编码指令完成;控制器负责协调控制计算机的其他器件进行工作;寄存器进行数据的临时存储,程序员只需关心寄存器的数据存取即可改变运行CPU运行结果。它们之间由总线连接。 高速缓存 CPU每执行一条指令前都需要从内存中将指令读取到CPU内并执行。而寄存器的运行速度相比内存读写要快很多,为了性能,CPU还集成了一个高速缓...
继续访问
arm64汇编篇-03寄存器
寄存器CPU由控制器、运算器还有寄存器构成,其中寄存器作用就是进行数据的临时存储。CPU的运算速度是非常快的,为了性能CPU在内部开辟一小块临时存储区域,并在进行运算时先将数据从内存复制到这一小块临时存储区域中,运算时就在这一小快临时存储区域内进行。我们称这一小块临时存储区域为寄存器。iPhoneX上搭载的ARM处理器A11它的1级缓存的容量是64KB,2级缓存的容量8M.CPU每执行一条指令前都...
继续访问
adrp arm64
ios
内存 参考技术A ARM的内存看是哪一种类型了。ARM7TDMI的核一般都是片内集成的,连续地址,只要进行设置后就可以使用了;ARM720T及以上的CPU集成了MMU和内存控制器的,可以将内存映射进入4GB的连续地址空间内,再由MMU进行映射,实现虚地址给操作系统使用。 参考技术B 分区是对硬盘的操作,分成不同的区域,赋予不同的盘符。内存的话,其实插槽也算是有“区域”的吧,你会发现有的主板上四个插槽有两种颜色。两条大小、频率等参数相同的内存条,插入颜色相同的两个插槽里,可以组成双通道,同时利用CPU的两个内存控制器,大幅提升内存读写速率。
以上是关于在ARM汇编编程中如何指定某段程序的存储地址的主要内容,如果未能解决你的问题,请参考以下文章