- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我试图了解链接寄存器和帧指针在ARM中的工作方式。我去过几个站点,我想确认自己的理解。
假设我有以下代码:
int foo(void)
{
// ..
bar();
// (A)
// ..
}
int bar(void)
{
// (B)
int b1;
// ..
// (C)
baz();
// (D)
}
int baz(void)
{
// (E)
int a;
int b;
// (F)
}
最佳答案
某些寄存器调用约定取决于ABI(应用程序二进制接口(interface))。 APCS 标准中需要FP
,而不是较新的 AAPCS (2003)中需要。对于 AAPCS (GCC 5.0+),FP
没有使用,但可以使用。带有堆栈和帧指针的debug info is annotated用于与 AAPCS 一起进行堆栈跟踪和展开代码。如果函数是static
,则编译器实际上不必遵守任何约定。
通常,所有ARM寄存器都是通用的。 lr
(链接寄存器,也为R14)和pc
(程序计数器也为R15)是特殊的,并包含在指令集中。您是正确的,lr
将指向 A 。 pc
和lr
是相关的。一个是“你在哪里”,另一个是“你在哪里”。它们是函数的代码方面。
通常,我们有sp
(堆栈指针R13)和fp
(frame pointer R11)。这两个也是相关的。这个
Microsoft layout很好地描述了事物。堆栈用于存储函数中的临时数据或本地数据。 foo()
和bar()
中的任何变量都存储在此处,堆栈中或可用的寄存器中。 fp
跟踪函数之间的变量。它是该功能在堆栈上的框架或图片窗口。 ABI定义了此框架的布局。通常,编译器会将lr
和其他寄存器以及fp
的先前值保存在幕后。这将形成堆栈框架的链接列表,如果需要,可以一直追溯到main()
。根是fp
,它指向一个堆栈帧(如struct
),struct
中的一个变量是前一个fp
。您可以遍历列表,直到最终的fp
(通常为NULL
)。
因此,sp
是堆栈所在的位置,fp
是堆栈所在的位置,非常类似于pc
和lr
。每个旧的lr
(链接寄存器)都存储在旧的fp
(帧指针)中。 sp
和fp
是函数的数据方面。
您的点 B 是 Activity 的pc
和sp
。点 实际上是fp
和lr
;除非调用另一个函数,否则编译器可能已准备就绪,可以设置fp
指向 B 中的数据。
以下是一些ARM汇编程序,可能会演示这一切如何工作。取决于编译器的优化方式,这会有所不同,但是应该给出一个主意,
; Prologue - setup
mov ip, sp ; get a copy of sp.
stmdb sp!, {fp, ip, lr, pc} ; Save the frame on the stack. See Addendum
sub fp, ip, #4 ; Set the new frame pointer.
...
; Maybe other functions called here.
; Older caller return lr
stored in stack frame.
bl baz
...
; Epilogue - return
ldm sp, {fp, sp, lr} ; restore stack, frame pointer and old link.
... ; maybe more stuff here.
bx lr ; return.
这就是
foo()
的样子。如果您不调用
bar()
,那么编译器将进行叶优化,并且不需要保存框架;只需要
bx lr
。这很可能就是为什么您对网络示例感到困惑的原因。它并不总是相同的。
pc
和lr
是相关的代码寄存器。一个是“您在哪里”,另一个是“您在哪里”。 sp
和fp
是相关的本地数据寄存器。一个是“本地数据在哪里”,另一个是“最后一个本地数据在哪里”。 pc
,我们将其存储在此处。 lr
,此函数的返回地址。 sp
,此函数占用堆栈之前。 fp
,最后一个堆栈帧。 关于c - ARM:链接寄存器和帧指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15752188/
我无法理解如何使用一些旧的 VGA 代码在这个示例中设置序列 Controller 寄存器: mov dx,SC_INDEX mov ax,0604h out dx,ax
我希望对 zmm 0-31 寄存器集的四字元素执行整数算术运算并保留这些运算产生的进位位。看来这只有在通用寄存器集中处理数据时才有可能。 因此,我想将信息从 zmm 0-31 寄存器之一复制到通用寄存
ARM 64中包含多种寄存器,下面介绍一些常见的寄存器。 1 通用寄存器 ARM 64包含31个64bit寄存器,记为X0~X30。 每一个通用寄存器,它的低32bit都可以被访问,记为W0~W
1.寄存器 组合逻辑存在一个最大的缺点就是存在竞争与冒险,系统会产生不定态;使用时序逻辑电路就会极大的改善这种情况 寄存器具有存储功能,一般是由D触发器构成,由时钟脉冲控制,每个D触发器能够
使用 $gp 是否存在危险?注册以存储值?我想我的问题是 $gp 的真正功能是什么?它是否以某种方式在幕后调用,以便如果我使用它,事情可能会变得非常非常错误? 最佳答案 那么,$gp register
我遇到了这段代码的问题,我无法弄清楚问题出在哪里。所以当我运行这段代码时:if $row["count"] > 0 else块运行和 $_SESSION["error"]设置。 当$row["coun
所以我正在做二进制炸弹的变体。这就是阶段 0x0000000000401205 : sub $0x8,%rsp 0x0000000000401209 : cmp $0x3,
我在一个名为 (EmployeeDetailKey - varchar(10)) 的字段中获得了一个值,其中包含顺序值,例如 00001, 00002, 00003.... 它位于 Employeed
我有一个要求,应该为每个调用的线程分配一个计数器变量。但我没有得到预期的结果,实际上计数器在线程中重复。我创建了一个虚拟表和一个过程来将计数器值插入到表中。无论如何,是否可以更改代码以便线程获得递增的
预期输出:需要打印第4季度的wage_amt +--------------+--------------+--------------+--------------+ | wages_amt_q1
如何匹配模式 abc_[someArbitaryStringHere]_xyz? 为了澄清,我希望正则表达式能够匹配以下性质的字符串: abc_xyz、abc_asdfsdf_xyz、abc_32rw
从下拉列表(自定义)中选择一个值而不是常规下拉列表,它有很多下拉值 我可以用代码选择第一个值 find('.selected', :text=>arg1,exact: false).click 但无法
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我有 .csv 文件中的数据,它包含 2 列 x 轴和 y 轴。从 .csv 文件读取轴,然后使用拉伸(stretch)指数函数拟合数据,但显示错误。 这里我给出示例数据以方便理解。 我的函数是f(x
我正在尝试使用以下汇编代码将磁盘扇区加载到内存中,但正如我在终端中使用一些 int 0x10 时发现的那样,它不起作用的原因是它陷入了无限循环。我以为循环会自动为我递减 cx 寄存器。下面是代码,其中
我正在尝试编写一个脚本,该脚本将在 vim 中打开一个文件并将其中的特定行复制到 vim 的寄存器之一中。当脚本再次运行时,它会决定再次打开文件,然后将 vim 寄存器中的值粘贴回。实际上,脚本应该在
我目前正在尝试弄清楚如何将指针寄存器 SI 指向的内存中的第一个字节添加到 AX 寄存器的当前内容中。 因此,如果 SI 包含某个地址,并且该地址在内存中的值是:00 和 01,我希望将 00 添加到
我试图将两个 16 位数字与以下 NASM 代码相乘: mov ax, [input1] mov bx, [input2] mul bx 前面代码的结果存储在 DX:AX 我试图使用来自单独库“pri
我正在尝试修改 rip 寄存器(只是为了好玩)。 buffer 应该是内存地址,所以不知道为什么会得到Error: operand type mismatch for 'movq' #include
我可以告诉gcc-style inline assembly把我的__m512i变量到特定 zmm注册,如 zmm31 ? 最佳答案 就像在根本没有特定寄存器约束的目标(如 ARM)上一样,使用 lo
我是一名优秀的程序员,十分优秀!