linux 汇编 preserve8,为什么ARM汇编程序前要加PRESERVE8

PRESERVE8是ARM汇编指令,用于确保8字节堆栈对齐。当代码包含与堆栈交互的LDRD或STRD指令时,需要使用它。链接器会检查要求8字节对齐的代码只被同样保持8字节对齐的代码调用。REQUIRE8则指示链接器确保代码从堆栈八字节对齐的对象中调用。这两个伪指令并不实际完成对齐,对齐操作由ALIGN指令完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这是字节对齐关键词,以前用ADS编译器的时候可以不用,但是后来的keil编译器时需要加上(譬如用周立功模板时,将ADS工程转到keil工程时就必须加上)。

require8和preserve8

c和汇编有8位对齐的要求,这两个伪指令可以满足此要求,存在REQUIRE8 PRESERVE8的对应关系,但不是说有一个REQUIRE8就要有一个 PRESERVE8,如果是一个c文件和一个汇编文件的调用,也就涉及一个PRESERVE8或者是一个REQUIRE8,   以下剪自ADS1.2中 PDF,就很清楚,由此可见,最好不要使用LDRD 或 STRD。

LDRD and STRD instructions (double-word transfers) only work correctly if the address they access is 8-byte aligned.

If your code includes LDRD or STRD transfers to or from the stack, use REQUIRE8 to instruct the linker to ensure that your code is only called from objects that preserve 8-byte alignment of the stack.

If your code preserves 8-byte alignment of the stack, use PRESERVE8 to inform the linker.

The linker ensures that any code that requires 8-byte alignment of the stack is only called, directly or indirectly, by code that preserves 8-byte alignment of the stack.

另外,REQUIRE8和PRESERVE8并不完成8 byte 对齐的操作,对齐由ALIGN完成。

RealView? 编译工具 汇编程序指南

3.1 版

Home > 指令参考 > 其他指令 > REQUIRE8 和 PRESERVE8

7.8.14. REQUIRE8 和 PRESERVE8

REQUIRE8

指令指定当前文件要求堆栈八字节对齐。 它设置 REQ8 编译属性以通知链接器。

PRESERVE8

指令指定当前文件保持堆栈八字节对齐。 它设置 PRES8 编译属性以通知链接器。

链接器检查要求堆栈八字节对齐的任何代码是否仅由保持堆栈八字节对齐的代码直接或间接地调用。

语法

REQUIRE8 {

bool

}

PRESERVE8 {

bool

}

其中:

bool

是一个可选布尔常数,取值为

{TRUE}

{FALSE}

用法

如果您的代码保持堆栈八字节对齐,在需要时,可使用

PRESERVE8

设置文件的 PRES8 编译属性。 如果您的代码不保持堆栈八字节对齐,则可使用

PRESERVE8 {FALSE}

确保不设置 PRES8 编译属性。

Note

如果您省略

PRESERVE8

PRESERVE8 {FALSE}

,汇编程序会检查修改 sp 的指令,以决定是否设置 PRES8 编译属性。 ARM 建议明确指定

PRESERVE8

您可以通过以下形式启用警告:

armasm --diag_warning 1546

有关详细信息,请参阅命令语法。

您将会收到类似以下警告:

"test.s", line 37: Warning: A1546W: Stack pointer update potentially                                 breaks 8 byte stack alignment        37 00000044         STMFD    sp!,{r2,r3,lr}

示例

REQUIRE8 REQUIRE8 {TRUE} ; equivalent to REQUIRE8 REQUIRE8 {FALSE} ; equivalent to absence of REQUIRE8 PRESERVE8 {TRUE} ; equivalent to PRESERVE8 PRESERVE8 {FALSE} ; NOT exactly equivalent to absence of PRESERVE8

Copyright ? 2002-2007 ARM Limited. All rights reserved.

ARM DUI 0204HC

Non-Confidential

### Linux ARM64 架构下的启动过程 #### 汇编代码解析 对于Linux ARM64架构,在`arch/arm64/kernel/head.S`文件中定义了内核的启动流程[^1]。该文件包含了多个重要的函数和宏,用于完成从引导载程序到操作系统内核的过渡。 在最开始的部分,通过`.head.text`段声明了一系列入口点以及初始化指令[^5]: ```assembly .section .head.text, "ax" .global __primary_switched __primary_switched: adr_x0, . bl primary_entry ``` 上述代码片段展示了如何定位并跳转至主要入口函数`primary_entry()`。这里利用相对寻址方式(`adr`)来获取当PC寄存器值,并将其传递给参数x0;随后调用子程序分支命令(bl),执行实际的目标位置处的功能逻辑。 接着是几个关键步骤描述如下: - **保存启动参数**:为了确保后续能够访问到来自BootLoader传入的信息(如内存布局),会有一个名为`preserve_boot_args`的过程负责这项工作[^2]。 ```assembly preserve_boot_args: stp x0, x1, [sp, #-16]! // Save arguments on stack ... ``` - **配置CPU状态**:根据具体硬件平台的需求调整异常级别(EL)和其他必要的设置项,这通常由`el2_setup`和`set_cpu_boot_mode_flag`等处理单元承担。 - **创建初始页表结构**:这是为了让MMU可以正常运作而构建的基础数据结构之一,它允许虚拟地址空间映射物理资源。 - **使能MMU (Memory Management Unit)** :一旦完成了面提到的各项准备工作之后,则可以通过特定序列激活存储管理部件,从而启用分页机制和支持更复杂的内存保护特性。 最后当一切准备就绪后,控制流将会转向C语言写的`start_kernel()`函数继续剩余部分的操作系统初始化任务。 #### 关于汇编与C交互的技术细节 由于ARM64体系结构不支持类似于ARM32中的某些伪指令形式,所以在编写涉及跨语言接口的地方时需要注意差异性[^4]。例如,在ARM32中有`ldr reg, =label`这样的语法可以直接引用符号地址,但在ARM64环境下则需采用其他方法间接达成相同效果,像使用ADR/ADRP组合上ADD指令的方式计算偏移量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值