- 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/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!