繁体   English   中英

在ARM内联汇编中修改sp

[英]Modifying sp in ARM inline assembly

我知道在x86中有一些规则来管理堆栈指针的修改:

RSP当前地址以外的所有内存均被视为易失性:OS或调试器可能会在用户调试会话或中断处理程序期间覆盖此内存。 因此,在尝试向堆栈帧读取或写入值之前,必须始终设置RSP。

我的问题是,ARM的规则是什么? 我正在看这段代码(请参见下面的摘录),看起来它违反了x86规则(修改内存然后更改了堆栈指针),但是在ARM上有问题吗?

mov r4, sp
sub r4, r4, #128

...

mov r3, #116
1: ldr r7, [r2]
add r2, r2, #4
str r7, [r4]
dd r4, r4, #4
sub r3, r3, #4
cmp r3, #0
ne 1b

sub sp, sp, #128

我曾尝试使用谷歌搜索,但要找到一个规范来描述如何在嵌入式asm中修改ARM堆栈是一项挑战。 有一些关于ARM编译器和修改堆栈的文档,但是gcc的规则似乎有所不同。

您所说的“规则”有点详尽和具体。 但是“规则”适用于几乎所有使用一个堆栈进行所有处理的处理器。

通常,您应该首先移动堆栈指针以“分配”所需的堆栈空间,这是防止下一件事物被破坏的方式。 然后将其移回去分配。

对于ARM,可能是您链接的代码。 您已经将寄存器存放在架构参考手册中的第一章之一中(需要在分析或编写汇编语言之前阅读其中的内容,尤其是寄存器上的一幅图)。 如图所示的异常模式都有各自的堆栈指针。 因此,例如在发生中断时,将使用其他一些堆栈指针来保存状态,因此不会破坏您的数据。

用户和系统共享一个堆栈指针,但这是为了使内核等代码可以访问而不会陷入用户模式。 系统不用于异常,因此您的代码不会只是停止并切换状态并破坏堆栈。

现在,ARM与其他任何品牌的福特一样。 他们使大型卡车变成小型卡车,SUV,小型车,爷爷车等。ARM拥有广泛的处理器内核。 cortex-m适用于微控制器和其他狭小空间。 它只有一个堆栈,当发生异常时,它将为您保存堆栈中的状态,从而破坏您的数据。 因此,您指出的代码会很糟糕,因为您为什么要在cortex-m上使用printf?

可以将编译器配置为使用第二个堆栈指针,也可以不使用第二个堆栈指针,x86世界已习惯于这种想法(sp和bsp),但这不是必需的。 为了使(数据)堆栈有用,需要有一个堆栈指针和用于引用堆栈指针相关寻址的已使用堆栈部分的指令。 在某些平台上,您可以访问堆栈指针,并使用另一个寄存器(进行复制)访问堆栈帧,从而使堆栈指针可以自由漫游。 通常,有或没有,在内联汇编中触摸堆栈指针都是一个非常糟糕的主意,您需要了解您的工具链,并且这样的代码将需要不断的维护,编译器的每个新版本或编译该代码的每个新系统然后,您必须手动检查产生的输出,以确保操作安全。 如果要达到这个水平,为什么要使用内联汇编并烧掉所有这些工时(工作安全性?),那么您会第一次使用汇编并制造安全可靠的东西。 如果只想为该函数提供更多数据,只需创建一个局部变量,它就会更改sp的减法,完成。 无需内联汇编。 如果您希望超越堆栈的末端,请使用汇编而不是内联汇编。 如果您要修改堆栈指针或出于某种原因快速分配而不使用局部变量,请再次使用汇编程序,并将堆栈指针移到必须避免此数据损坏的系统上。

除了使系统崩溃之外,在内联汇编中弄乱堆栈指针也没有多大意义。 与arm或x86无关,或填写空白。

他们在那里所做的就是使用内联汇编在汇编中编写整个功能。 这可能只是他们选择的构建系统的一种情况,您可以将程序集送入gnu C编译器(如果使用内联程序集,则无论如何都必须编写特定于编译器的代码,这样您就已经知道要使用的编译器)并产生一个对象,就像您可以使用C。他们还有其他方法可以做到这一点,但并不那么难看。 不幸的是,看到这种解决方案并不罕见。 如果在非cortex-m上运行,那么该代码是安全的,您不能在其中途添加函数调用,因为这将破坏数据,它们确实在调用之前而不是向上移动堆栈指针前面像一个正常的解决方案。 必须追踪作者,问“他们为什么这样做”的问题。

ARM没有这样的规则。 CPU(至少是Cortex-A / R CPU)不会在发生中断时自动堆栈寄存器,即使对于Cortex-M,也可以保证保持顺序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM