简体   繁体   English

在ARM内联汇编中修改sp

[英]Modifying sp in ARM inline assembly

I know there are rules governing the modifying of the stack pointer in x86: 我知道在x86中有一些规则来管理堆栈指针的修改:

All memory beyond the current address of RSP is considered volatile: The OS, or a debugger, may overwrite this memory during a user debug session, or an interrupt handler. RSP当前地址以外的所有内存均被视为易失性:OS或调试器可能会在用户调试会话或中断处理程序期间覆盖此内存。 Thus, RSP must always be set before attempting to read or write values to a stack frame. 因此,在尝试向堆栈帧读取或写入值之前,必须始终设置RSP。

My question is, what are the rules for ARM? 我的问题是,ARM的规则是什么? I'm looking at this code (see extract below), and it looks like it violates that x86 rule (modifies memory then changes the stack pointer), but is that a problem on 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

I've tried googling, but finding a spec that describes modifying the ARM stack in inline asm is... challenging. 我曾尝试使用谷歌搜索,但要找到一个规范来描述如何在嵌入式asm中修改ARM堆栈是一项挑战。 There are some docs regarding the ARM compiler and modifying the stack, but the rules for gcc appear to be different. 有一些关于ARM编译器和修改堆栈的文档,但是gcc的规则似乎有所不同。

Your "rule" as you call it is a bit detailed and specific. 您所说的“规则”有点详尽和具体。 But the "rule" applies to pretty much all processors that use one stack for everything. 但是“规则”适用于几乎所有使用一个堆栈进行所有处理的处理器。

You should as a general rule move your stack pointer first to "allocate" the stack space you want, which is how you keep the next thing from trashing it. 通常,您应该首先移动堆栈指针以“分配”所需的堆栈空间,这是防止下一件事物被破坏的方式。 And then move it back to de-allocate. 然后将其移回去分配。

In the case of ARM, likely the code you were linking. 对于ARM,可能是您链接的代码。 You have banked registers in the arm, one of the first chapters in the architectural reference manual (need to read that before analyzing or writing assembly language, esp the one picture on registers). 您已经将寄存器存放在架构参考手册中的第一章之一中(需要在分析或编写汇编语言之前阅读其中的内容,尤其是寄存器上的一幅图)。 The Exception modes as the picture describes all have their own stack pointer. 如图所示的异常模式都有各自的堆栈指针。 So when for example an interrupt occurs, some other stack pointer is used to save state, so your data wont be clobbered. 因此,例如在发生中断时,将使用其他一些堆栈指针来保存状态,因此不会破坏您的数据。

User and System share a stack pointer, but that is so that kernel, etc code can have access without getting trapped in user mode. 用户和系统共享一个堆栈指针,但这是为了使内核等代码可以访问而不会陷入用户模式。 System is not used for exceptions so your code isnt going to just stop and switch states and clobber the stack. 系统不用于异常,因此您的代码不会只是停止并切换状态并破坏堆栈。

Now ARM is like any other brand Ford for example. 现在,ARM与其他任何品牌的福特一样。 They make big trucks little trucks, SUV's, small cars, grandpa cars, etc. ARM has a wide array of processor cores. 他们使大型卡车变成小型卡车,SUV,小型车,爷爷车等。ARM拥有广泛的处理器内核。 The cortex-m is suited for microcontrollers and other small tight spaces. cortex-m适用于微控制器和其他狭小空间。 It has one stack, when an exception occurs it saves state on the stack for you, clobbering your data. 它只有一个堆栈,当发生异常时,它将为您保存堆栈中的状态,从而破坏您的数据。 So the code you pointed out would be bad, granted why would you be using printf on a cortex-m? 因此,您指出的代码会很糟糕,因为您为什么要在cortex-m上使用printf?

Compilers can be configured to use or not use a second stack pointer, the x86 world is used to this idea (sp and bsp), but it is not required. 可以将编译器配置为使用第二个堆栈指针,也可以不使用第二个堆栈指针,x86世界已习惯于这种想法(sp和bsp),但这不是必需的。 For a (data) stack to be useful there needs to be a stack pointer and instructions for referencing into the used part of the stack, stack pointer relative addressing. 为了使(数据)堆栈有用,需要有一个堆栈指针和用于引用堆栈指针相关寻址的已使用堆栈部分的指令。 On some platforms you can access the stack pointer and use another register (make a copy) to access the stack frame leaving the stack pointer free to roam about. 在某些平台上,您可以访问堆栈指针,并使用另一个寄存器(进行复制)访问堆栈帧,从而使堆栈指针可以自由漫游。 With or without it is an incredibly bad idea to touch a stack pointer in inline assembly in general, you need to know your toolchain well and code like that would require constant maintenance, every new release of the compiler or every new system you compile that code on, you have to hand examine the produced output to insure your manipulation is safe. 通常,有或没有,在内联汇编中触摸堆栈指针都是一个非常糟糕的主意,您需要了解您的工具链,并且这样的代码将需要不断的维护,编译器的每个新版本或编译该代码的每个新系统然后,您必须手动检查产生的输出,以确保操作安全。 If you are going to that level why use inline asm and burn all those man hours (job security?) you would use asm and make something safe and reliable the first time. 如果要达到这个水平,为什么要使用内联汇编并烧掉所有这些工时(工作安全性?),那么您会第一次使用汇编并制造安全可靠的东西。 If you just want some more data for that function, just make a local variable, it changes the subtraction on the sp, done. 如果只想为该函数提供更多数据,只需创建一个局部变量,它就会更改sp的减法,完成。 No inline assembly required. 无需内联汇编。 If you have this desire to look past the end of the stack, use assembly not inline assembly. 如果您希望超越堆栈的末端,请使用汇编而不是内联汇编。 If you want to modify past the stack pointer or quickly allocate for some reason without using local variables then again use assembly and move the stack pointer on systems where you have to to avoid corruption of this data you are playing with. 如果您要修改堆栈指针或出于某种原因快速分配而不使用局部变量,请再次使用汇编程序,并将堆栈指针移到必须避免此数据损坏的系统上。

Other than crashing the system it doesnt make much sense to mess with the stack pointer in inline assembly. 除了使系统崩溃之外,在内联汇编中弄乱堆栈指针也没有多大意义。 Has nothing to do with arm or x86 or fill in the blank. 与arm或x86无关,或填写空白。

What they have done there is write the entire function in assembly using inline assembly. 他们在那里所做的就是使用内联汇编在汇编中编写整个功能。 And that may just a case of their build system choices, you can feed assembly into the gnu C compiler (if using inline assembly you have to write compiler specific code anyway so you already know what compiler you are using) and produce an object just like you can with C. There are other ways they could have done that is the point that are not as ugly. 这可能只是他们选择的构建系统的一种情况,您可以将程序集送入gnu C编译器(如果使用内联程序集,则无论如何都必须编写特定于编译器的代码,这样您就已经知道要使用的编译器)并产生一个对象,就像您可以使用C。他们还有其他方法可以做到这一点,但并不那么难看。 Unfortunately it is not an uncommon sight to see that solution. 不幸的是,看到这种解决方案并不罕见。 If running on a not-cortex-m, that code is safe-ish as is, you cant add a function call in the middle of it as you will trash your data, they do move the stack pointer just before the call rather than up front like a normal solution. 如果在非cortex-m上运行,那么该代码是安全的,您不能在其中途添加函数调用,因为这将破坏数据,它们确实在调用之前而不是向上移动堆栈指针前面像一个正常的解决方案。 Would have to track down the author to ask the "why did they do that" question. 必须追踪作者,问“他们为什么这样做”的问题。

There is no such rule for ARM. ARM没有这样的规则。 The CPU (At least Cortex-A/R CPUs) does not automatically stack registers in case of interrupt, and even for Cortex-M, it is guaranteed to keep the order. CPU(至少是Cortex-A / R CPU)不会在发生中断时自动堆栈寄存器,即使对于Cortex-M,也可以保证保持顺序。

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

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