- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尽力了解有关调用堆栈以及ARM Cortex-M0中堆栈帧的结构,事实证明这有些困难,但我正在耐心地学习。在这一个问题中,我有几个问题,希望大家可以在所有领域为我提供帮助。在本说明中,我的问题将以粗体突出显示。
我正在使用带有GDB的ARM Cortex-M0和一个简单的程序来调试。这是我的程序:
int main(void) {
static uint16_t myBits;
myBits = 0x70;
halInit();
return 0;
}
halInit()
上设置了一个断点。然后,我在GDB终端上执行命令
info frame
以获得以下输出:
Stack level 0, frame at 0x20000400:
pc = 0x80000d8 in main (src/main.c:63); saved pc 0x8002dd2
source language c.
Arglist at 0x200003e8, args:
Locals at 0x200003e8, Previous frame's sp is 0x20000400
Saved registers:
r0 at 0x200003e8, r1 at 0x200003ec, r4 at 0x200003f0, r5 at 0x200003f4, r6 at 0x200003f8, lr at 0x200003fc
Stack level 0
:堆栈帧的当前级别。
0
将始终代表堆栈的顶部,换句话说,当前正在使用的堆栈帧。
frame at 0x20000400
:这表示堆栈帧在闪存中的位置。
pc = 0x80000d8 in main (src/main.c:63);
:这表示要执行的下一个执行,即程序计数器值。由于程序计数器始终代表要执行的下一条指令。
saved pc 0x8002dd2
:这让我有些困惑,但是我认为这意味着返回地址,本质上是从执行
halInit()
函数返回时要执行的指令。但是,如果我在GDB终端中键入命令
info reg
,我会看到链接寄存器不是此值,而是下一个地址:
lr 0x8002dd3
。这是为什么?
source language c.
:这表示所使用的语言。
Arglist at 0x200003e8, args:
:这表示传递给堆栈框架的参数的起始地址。由于
args:
为空白,这意味着未传递任何参数。这有两个原因:这是调用堆栈中的第一个堆栈帧,而我的函数没有任何参数
int main(void)
。
Locals at 0x200003e8
:这是我的局部变量的起始地址。如您在原始代码段中所见,我应该有一个局部变量
myBits
。我们待会儿再讲。
Previous frame's sp is 0x20000400
:这是指向调用者堆栈框架顶部的堆栈指针。由于这是第一个堆栈帧,因此我希望该值应等于当前帧的地址。
Saved registers:
r0 at 0x200003e8
r1 at 0x200003ec
r4 at 0x200003f0
r5 at 0x200003f4
r6 at 0x200003f8
lr at 0x200003fc
info reg
,将得到以下输出:
r0 0x20000428 0x20000428
r1 0x0 0x0
r2 0x0 0x0
r3 0x70 0x70
r4 0x80000c4 0x80000c4
r5 0x20000700 0x20000700
r6 0xffffffff 0xffffffff
r7 0xffffffff 0xffffffff
r8 0xffffffff 0xffffffff
r9 0xffffffff 0xffffffff
r10 0xffffffff 0xffffffff
r11 0xffffffff 0xffffffff
r12 0xffffffff 0xffffffff
sp 0x200003e8 0x200003e8
lr 0x8002dd3 0x8002dd3
pc 0x80000d8 0x80000d8 <main+8>
xPSR 0x21000000 0x21000000
p/x *(register)
检查存储在已保存寄存器的每个存储器地址中的值,则该值应等于上面输出中显示的值。
Saved registers:
r0 at 0x200003e8 -> 0x20000428
r1 at 0x200003ec -> 0x0
r4 at 0x200003f0 -> 0x80000c4
r5 at 0x200003f4 -> 0xffffffff
r6 at 0x200003f8 -> 0xffffffff
lr at 0x200003fc -> 0x8002dd3
info reg
命令显示的值。但是,我注意到一件事。我有一个值为
myBits
的局部变量
0x70
,它似乎存储在
r3
中。但是,
r3
不会被压入堆栈进行保存。
halInit()
创建一个新的堆栈框架。这是通过在终端上执行命令
bt
来显示的。它生成以下输出:
#0 halInit () at src/hal/src/hal.c:70
#1 0x080000dc in main () at src/main.c:63
info frame
,则会得到以下输出:
Stack level 0, frame at 0x200003e8:
pc = 0x8001842 in halInit (src/hal/src/hal.c:70); saved pc 0x80000dc
called by frame at 0x20000400
source language c.
Arglist at 0x200003e0, args:
Locals at 0x200003e0, Previous frame's sp is 0x200003e8
Saved registers:
r3 at 0x200003e0, lr at 0x200003e4
r3
被压入该堆栈帧。该寄存器保存变量
myBits
的值。如果调用方堆栈帧需要此寄存器,为什么将
r3
压入此堆栈帧?
r3
被推入被调用者堆栈而不是推入调用者堆栈,即使调用者是需要此值的人也是如此。
halInit()
将修改
r3
中的值吗?
r3
,然后在弹出堆栈框架时会将被压入堆栈帧的值
0x70
恢复回
r3
供调用者再次使用。这是正确的吗?如果是这样,被调用方堆栈框架如何知道调用方堆栈框架将需要此值?
最佳答案
我正在努力学习有关调用堆栈以及堆栈帧的方式
在ARM Cortex-M0中构建
因此,基于该报价,首先,cortex-m0没有堆栈框架,处理器确实是愚蠢的逻辑。编译器生成的堆栈帧是编译器对象,而不是指令集对象。函数的概念是编译器,不是更低的东西。编译器使用调用约定或设计的一些基本规则,以便对于该语言,调用者和被调用者函数可以准确知道参数的位置,返回值,并且没有人浪费其他数据。
编译器作者可以自由地做他们想做的任何事情,只要它可以工作并符合指令集的规则即可,就像逻辑而不是汇编语言一样。 (只要机器代码符合逻辑规则,汇编作者就可以自由地编写他们想要的任何汇编语言,助记符)。而且他们曾经这样做,处理器供应商已经开始提出建议,可以这样说,编译器也符合它们。它不是关于在编译器之间尽可能多地共享对象1)我不必提出自己的想法2)我们信任IP供应商及其处理器,并希望它们的调用约定是为性能和我们期望的其他原因而设计的。
到目前为止,随着gcc的发展和gcc的发展,gcc一直试图与ARM ABI保持一致。
当您有“许多”寄存器时,有很多方法是个问题,但是您会看到约定将首先使用寄存器,然后使用堆栈传递参数。您还将看到在功能中某些寄存器将被指定为易失性,以提高性能,而不必过多地使用内存(堆栈)。
通过使用调试器和断点,您在错误的位置查找语句,是要了解有关调用堆栈和堆栈帧的信息,这是编译器,而不是逻辑中如何处理异常。除非您的问题确实不够准确,否则您无法理解。
像GCC这样的编译器都有优化器,尽管它们对从优化版本学习死代码造成了混乱,但比未优化版本容易。让我们潜入
extern unsigned int more_fun ( unsigned int, unsigned int );
unsigned int fun ( unsigned int a, unsigned int b )
{
return(a+b);
}
<fun>:
0: 1840 adds r0, r0, r1
2: 4770 bx lr
00000000 <fun>:
0: b580 push {r7, lr}
2: b082 sub sp, #8
4: af00 add r7, sp, #0
6: 6078 str r0, [r7, #4]
8: 6039 str r1, [r7, #0]
a: 687a ldr r2, [r7, #4]
c: 683b ldr r3, [r7, #0]
e: 18d3 adds r3, r2, r3
10: 0018 movs r0, r3
12: 46bd mov sp, r7
14: b002 add sp, #8
16: bd80 pop {r7, pc}
00000000 <fun>:
0: b082 sub sp, #8
2: 9001 str r0, [sp, #4]
4: 9100 str r1, [sp, #0]
6: 9a01 ldr r2, [sp, #4]
8: 9b00 ldr r3, [sp, #0]
a: 18d3 adds r3, r2, r3
c: 0018 movs r0, r3
e: b002 add sp, #8
10: 4770 bx lr
00000000 <fun>:
0: b580 push {r7, lr}
2: b082 sub sp, #8
4: af00 add r7, sp, #0
6: 6078 str r0, [r7, #4]
8: 6039 str r1, [r7, #0]
a: 687a ldr r2, [r7, #4]
c: 683b ldr r3, [r7, #0]
e: 18d3 adds r3, r2, r3
10: 0018 movs r0, r3
12: 46bd mov sp, r7
14: b002 add sp, #8
16: bc80 pop {r7}
18: bc02 pop {r1}
1a: 4708 bx r1
00000000 <fun>:
0: b580 push {r7, lr}
2: b082 sub sp, #8
4: af00 add r7, sp, #0
6: 6078 str r0, [r7, #4]
8: 6039 str r1, [r7, #0]
a: 687a ldr r2, [r7, #4]
c: 683b ldr r3, [r7, #0]
e: 18d3 adds r3, r2, r3
10: 0018 movs r0, r3
12: 46bd mov sp, r7
14: b002 add sp, #8
16: bd80 pop {r7, pc}
00000000 <fun>:
0: 1840 adds r0, r0, r1
2: 4770 bx lr
extern unsigned int more_fun ( unsigned int, unsigned int );
unsigned int fun ( unsigned int a, unsigned int b )
{
return(more_fun(a,b));
}
00000000 <fun>:
0: b510 push {r4, lr}
2: f7ff fffe bl 0 <more_fun>
6: bd10 pop {r4, pc}
fun:
b more_fun
extern unsigned int more_fun ( unsigned int, unsigned int );
unsigned int fun ( unsigned int a, unsigned int b )
{
more_fun(a,b);
return(a);
}
00000000 <fun>:
0: b510 push {r4, lr}
2: 0004 movs r4, r0
4: f7ff fffe bl 0 <more_fun>
8: 0020 movs r0, r4
a: bd10 pop {r4, pc}
extern unsigned int more_fun ( unsigned int, unsigned int );
unsigned int fun ( unsigned int a, unsigned int b )
{
b<<=more_fun(a,b);
return(a+b);
}
00000000 <fun>:
0: b570 push {r4, r5, r6, lr}
2: 0005 movs r5, r0
4: 000c movs r4, r1
6: f7ff fffe bl 0 <more_fun>
a: 4084 lsls r4, r0
c: 1960 adds r0, r4, r5
e: bd70 pop {r4, r5, r6, pc}
extern unsigned int more_fun ( unsigned int, unsigned int );
unsigned int fun ( unsigned int a, unsigned int b, unsigned int c, unsigned int d )
{
b<<=more_fun(b,c);
c<<=more_fun(c,d);
d<<=more_fun(b,d);
return(a+b+c+d);
}
0: b5f8 push {r3, r4, r5, r6, r7, lr}
2: 000c movs r4, r1
4: 0007 movs r7, r0
6: 0011 movs r1, r2
8: 0020 movs r0, r4
a: 001d movs r5, r3
c: 0016 movs r6, r2
e: f7ff fffe bl 0 <more_fun>
12: 0029 movs r1, r5
14: 4084 lsls r4, r0
16: 0030 movs r0, r6
18: f7ff fffe bl 0 <more_fun>
1c: 0029 movs r1, r5
1e: 4086 lsls r6, r0
20: 0020 movs r0, r4
22: f7ff fffe bl 0 <more_fun>
26: 4085 lsls r5, r0
28: 19a4 adds r4, r4, r6
2a: 19e4 adds r4, r4, r7
2c: 1960 adds r0, r4, r5
2e: bdf8 pop {r3, r4, r5, r6, r7, pc}
extern unsigned int more_fun ( unsigned int, unsigned int );
unsigned int fun ( unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e, unsigned int f )
{
b<<=more_fun(b,c);
c<<=more_fun(c,d);
d<<=more_fun(b,d);
e<<=more_fun(e,d);
f<<=more_fun(e,f);
return(a+b+c+d+e+f);
}
00000000 <fun>:
0: b5f0 push {r4, r5, r6, r7, lr}
2: 46c6 mov lr, r8
4: 000c movs r4, r1
6: b500 push {lr}
8: 0011 movs r1, r2
a: 0007 movs r7, r0
c: 0020 movs r0, r4
e: 0016 movs r6, r2
10: 001d movs r5, r3
12: f7ff fffe bl 0 <more_fun>
16: 0029 movs r1, r5
18: 4084 lsls r4, r0
1a: 0030 movs r0, r6
1c: f7ff fffe bl 0 <more_fun>
20: 0029 movs r1, r5
22: 4086 lsls r6, r0
24: 0020 movs r0, r4
26: f7ff fffe bl 0 <more_fun>
2a: 4085 lsls r5, r0
2c: 9806 ldr r0, [sp, #24]
2e: 0029 movs r1, r5
30: f7ff fffe bl 0 <more_fun>
34: 9b06 ldr r3, [sp, #24]
36: 9907 ldr r1, [sp, #28]
38: 4083 lsls r3, r0
3a: 0018 movs r0, r3
3c: 4698 mov r8, r3
3e: f7ff fffe bl 0 <more_fun>
42: 9b07 ldr r3, [sp, #28]
44: 19a4 adds r4, r4, r6
46: 4083 lsls r3, r0
48: 19e4 adds r4, r4, r7
4a: 1964 adds r4, r4, r5
4c: 4444 add r4, r8
4e: 18e0 adds r0, r4, r3
50: bc04 pop {r2}
52: 4690 mov r8, r2
54: bdf0 pop {r4, r5, r6, r7, pc}
56: 46c0 nop ; (mov r8, r8)
extern unsigned int more_fun ( unsigned int, unsigned int );
extern void not_dead ( unsigned int *);
unsigned int fun ( unsigned int a, unsigned int b )
{
unsigned int x[16];
unsigned int ra;
for(ra=0;ra<16;ra++)
{
x[ra]=more_fun(a+ra,b);
}
not_dead(x);
return(ra);
}
00000000 <fun>:
0: b5f0 push {r4, r5, r6, r7, lr}
2: 0006 movs r6, r0
4: b091 sub sp, #68 ; 0x44
6: 0004 movs r4, r0
8: 000f movs r7, r1
a: 466d mov r5, sp
c: 3610 adds r6, #16
e: 0020 movs r0, r4
10: 0039 movs r1, r7
12: f7ff fffe bl 0 <more_fun>
16: 3401 adds r4, #1
18: c501 stmia r5!, {r0}
1a: 42b4 cmp r4, r6
1c: d1f7 bne.n e <fun+0xe>
1e: 4668 mov r0, sp
20: f7ff fffe bl 0 <not_dead>
24: 2010 movs r0, #16
26: b011 add sp, #68 ; 0x44
28: bdf0 pop {r4, r5, r6, r7, pc}
2a: 46c0 nop ; (mov r8, r8)
00000000 <fun>:
0: b5b0 push {r4, r5, r7, lr}
2: af02 add r7, sp, #8
4: b090 sub sp, #64 ; 0x40
6: 460c mov r4, r1
8: 4605 mov r5, r0
a: f7ff fffe bl 0 <more_fun>
e: 9000 str r0, [sp, #0]
10: 1c68 adds r0, r5, #1
12: 4621 mov r1, r4
14: f7ff fffe bl 0 <more_fun>
18: 9001 str r0, [sp, #4]
1a: 1ca8 adds r0, r5, #2
1c: 4621 mov r1, r4
1e: f7ff fffe bl 0 <more_fun>
22: 9002 str r0, [sp, #8]
24: 1ce8 adds r0, r5, #3
26: 4621 mov r1, r4
28: f7ff fffe bl 0 <more_fun>
2c: 9003 str r0, [sp, #12]
2e: 1d28 adds r0, r5, #4
30: 4621 mov r1, r4
32: f7ff fffe bl 0 <more_fun>
36: 9004 str r0, [sp, #16]
38: 1d68 adds r0, r5, #5
3a: 4621 mov r1, r4
3c: f7ff fffe bl 0 <more_fun>
40: 9005 str r0, [sp, #20]
42: 1da8 adds r0, r5, #6
44: 4621 mov r1, r4
46: f7ff fffe bl 0 <more_fun>
4a: 9006 str r0, [sp, #24]
4c: 1de8 adds r0, r5, #7
4e: 4621 mov r1, r4
50: f7ff fffe bl 0 <more_fun>
54: 9007 str r0, [sp, #28]
56: 4628 mov r0, r5
58: 3008 adds r0, #8
5a: 4621 mov r1, r4
5c: f7ff fffe bl 0 <more_fun>
60: 9008 str r0, [sp, #32]
62: 4628 mov r0, r5
64: 3009 adds r0, #9
66: 4621 mov r1, r4
68: f7ff fffe bl 0 <more_fun>
6c: 9009 str r0, [sp, #36] ; 0x24
6e: 4628 mov r0, r5
70: 300a adds r0, #10
72: 4621 mov r1, r4
74: f7ff fffe bl 0 <more_fun>
78: 900a str r0, [sp, #40] ; 0x28
7a: 4628 mov r0, r5
7c: 300b adds r0, #11
7e: 4621 mov r1, r4
80: f7ff fffe bl 0 <more_fun>
84: 900b str r0, [sp, #44] ; 0x2c
86: 4628 mov r0, r5
88: 300c adds r0, #12
8a: 4621 mov r1, r4
8c: f7ff fffe bl 0 <more_fun>
90: 900c str r0, [sp, #48] ; 0x30
92: 4628 mov r0, r5
94: 300d adds r0, #13
96: 4621 mov r1, r4
98: f7ff fffe bl 0 <more_fun>
9c: 900d str r0, [sp, #52] ; 0x34
9e: 4628 mov r0, r5
a0: 300e adds r0, #14
a2: 4621 mov r1, r4
a4: f7ff fffe bl 0 <more_fun>
a8: 900e str r0, [sp, #56] ; 0x38
aa: 350f adds r5, #15
ac: 4628 mov r0, r5
ae: 4621 mov r1, r4
b0: f7ff fffe bl 0 <more_fun>
b4: 900f str r0, [sp, #60] ; 0x3c
b6: 4668 mov r0, sp
b8: f7ff fffe bl 0 <not_dead>
bc: 2010 movs r0, #16
be: b010 add sp, #64 ; 0x40
c0: bdb0 pop {r4, r5, r7, pc}
unsigned int fun ( unsigned int a, unsigned int b, unsigned int c, unsigned int d, unsigned int e )
{
return(a+b+c+d+e);
}
00000000 <fun>:
0: b510 push {r4, lr}
2: 9c02 ldr r4, [sp, #8]
4: 46a4 mov r12, r4
6: 4463 add r3, r12
8: 189b adds r3, r3, r2
a: 185b adds r3, r3, r1
c: 1818 adds r0, r3, r0
e: bd10 pop {r4, pc}
00000000 <_fun>:
0: 1d80 0008 mov 10(sp), r0
4: 6d80 000a add 12(sp), r0
8: 6d80 0006 add 6(sp), r0
c: 6d80 0004 add 4(sp), r0
10: 6d80 0002 add 2(sp), r0
14: 0087 rts pc
关于c - 为什么将调用者堆栈的局部变量保存在被调用者堆栈的寄存器中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52067217/
有人可以解释一下为什么我得到: "use of unassigned local variable number_of_column" for: if (i f.LastWriteTime).Fir
我正在尝试为查询定义和初始化 MySQL 变量。 我有以下几点: declare @countTotal int; SET @countTotal = select COUNT(*) from nG
局部变量由小写字母或下划线(_)开头.局部变量不像全局和实变量一样在初始化前含nil值. ruby>$foo nil ruby>@foo nil ruby>foo ER
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
当我单击 Login 类上的注册按钮时,出现 nullpointerException,它给出了该错误。我尝试修改本地和全局变量,但似乎没有任何方法可以修复该错误,我可能在 onClickListen
我之前看过一些关于此的帖子,但我一直无法找到有关 actionListeners 的帖子。我正在尝试使用 JButton 数组创建井字棋。如果可能的话,如何在使用 for 循环临时变量的同时向它们添加
我试图找出一种将 getView() 方法中的位置变量传递给内部类的方法。但是,这不能是最终变量,因为 ListView 中的每个项目都会调用 getView() ,因此它会发生变化。有没有办法访问该
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
这对你们中的某些人来说似乎微不足道,但我对下面的这两个示例感到困惑。 int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int i
这个问题在这里已经有了答案: How do JavaScript closures work? (86 个答案) 关闭 7 年前。 所以我正在复习我的 vanilla Javascript,专门用于
我正在将mockito与spring(java 1.8)一起使用,并且我尝试在我的Answer对象中使用局部变量: public IProductDTO productForMock = null;
是否可以在java中为静态方法注入(inject)局部变量,比如 @Inject public void someMethod() { @MyInjectQualifier MyObjectC
我有一个函数,每 2 秒被重复调用一次,每次从屏幕顶部带来一个具有随机纹理的球。我希望能够在 touchesBegan 中使用这个球,但我不能,因为它是一个局部变量。我试过将它设为全局变量,但这给了我
这是(我假设)一个基本问题,但我似乎无法弄清楚。 给定以下代码: from src.Globals import * import pygame # Used to manage how fast t
这就是我在循环中引用全局变量的方法。 _.forEach(myTableName.detailsObjects, function (o, key) { if
我已经创建了一些代码: import numpy as np Length=(2.7)*10**-3 Nx=4 x = np.linspace(0, Length, Nx+1) # mes
如何获取局部变量? 我有这个代码 if (ctrl is Control) { Control c = (Control)ctrl; foreach (object innerCtrl
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Difference between class variables and class instance
我正在学习 Python 3,我有一个关于 Python 中面向对象编程的非常基本的问题。这是我的代码。 class pet: number_of_legs = 0 def count
我有以下代码块: class Student{ int age; //instance variable String name; //instance varia
我是一名优秀的程序员,十分优秀!