如果我将它作为参数传递,函数调用的结果保存在哪里?
Where the result of function call is kept if I pass it as parameter?
uint32_t sum_a_b(uint32_t a, uint32_t b) {
return a + b;
}
uint32_t mul_c_d(uint32_t c, uint32_t d) {
return c * d;
}
int main(uint16_t argc, char **argv) {
uint32_t e;
e = mul_c_d(116, sum_a_b(17, 992));
return 0;
}
问题是 运行 机器在将调用 sum_a_b(17, 992)
的结果作为第二个参数传递给 mul_c_d
之前存储在哪里?
堆栈中有一些“临时变量”?
处理器寄存器?堆?
我在哪里可以读到这篇文章?
与显式使用变量的任何区别,
int main(uint16_t argc, char **argv) {
uint32_t e, t;
t = sum_a_b(17, 992);
e = mul_c_d(116, t);
return 0;
}
??
不幸的是我没有足够的asm / disasm技能来直接检查它....
谢谢!!
C 标准没有指定变量和值的存储位置,因此结果将是系统特定的。
“堆栈中有一些“临时变量”?”有可能。
“处理器寄存器?”有可能。
“堆?”不。堆仅在显式调用 malloc 或等效函数时使用。没有已知的 C 编译器隐式使用堆。
Unfortunately I don't have enough asm / disasm skills to check it directly
您不需要了解很多汇编程序就可以做到这一点。只需将您的代码放入 https://godbolt.org/,禁用优化,这就是您得到的 (x86):
mov esi, 992
mov edi, 17
call sum_a_b
mov esi, eax
mov edi, 116
call mul_c_d
现在我们唯一需要知道的汇编程序是像mov
这样的指令将结果存储在左操作数中。这就是为什么 memcpy
、strcpy
等 C 函数也将其结果存储在左操作数中的基本原理。
那么我们要知道esi,edi,eax是x86上的寄存器。所以它将 992 和 17 存储在寄存器中,然后调用该函数。之后,它会从第三个寄存器 eax 中取出一些东西并将它放在 esi 中。因此 sum_a_b
中的 return 值存储在 eax 中。
现在,如果我启动优化,整个 mul_c_d
调用将被 mov eax, 117044
取代。因此,编译器不仅能够内联所有函数调用,还能够在编译时预先计算结果。所以我们可以看出,我们启用的优化越多,知道结果存储在哪里变得越来越无关紧要。
Where can I read about this?
所有汇编器都有些相似,因此通过学习任何汇编器的基础知识,您可以大致了解它们的工作原理。当您学习汇编程序时,您将了解函数调用约定如何“在引擎盖下”工作。一些资源可以在这里找到:https://whosebug.com/tags/assembly/info
uint32_t sum_a_b(uint32_t a, uint32_t b) {
return a + b;
}
uint32_t mul_c_d(uint32_t c, uint32_t d) {
return c * d;
}
int main(uint16_t argc, char **argv) {
uint32_t e;
e = mul_c_d(116, sum_a_b(17, 992));
return 0;
}
问题是 运行 机器在将调用 sum_a_b(17, 992)
的结果作为第二个参数传递给 mul_c_d
之前存储在哪里?
堆栈中有一些“临时变量”?
处理器寄存器?堆?
我在哪里可以读到这篇文章?
与显式使用变量的任何区别,
int main(uint16_t argc, char **argv) {
uint32_t e, t;
t = sum_a_b(17, 992);
e = mul_c_d(116, t);
return 0;
}
??
不幸的是我没有足够的asm / disasm技能来直接检查它....
谢谢!!
C 标准没有指定变量和值的存储位置,因此结果将是系统特定的。
“堆栈中有一些“临时变量”?”有可能。
“处理器寄存器?”有可能。
“堆?”不。堆仅在显式调用 malloc 或等效函数时使用。没有已知的 C 编译器隐式使用堆。
Unfortunately I don't have enough asm / disasm skills to check it directly
您不需要了解很多汇编程序就可以做到这一点。只需将您的代码放入 https://godbolt.org/,禁用优化,这就是您得到的 (x86):
mov esi, 992
mov edi, 17
call sum_a_b
mov esi, eax
mov edi, 116
call mul_c_d
现在我们唯一需要知道的汇编程序是像mov
这样的指令将结果存储在左操作数中。这就是为什么 memcpy
、strcpy
等 C 函数也将其结果存储在左操作数中的基本原理。
那么我们要知道esi,edi,eax是x86上的寄存器。所以它将 992 和 17 存储在寄存器中,然后调用该函数。之后,它会从第三个寄存器 eax 中取出一些东西并将它放在 esi 中。因此 sum_a_b
中的 return 值存储在 eax 中。
现在,如果我启动优化,整个 mul_c_d
调用将被 mov eax, 117044
取代。因此,编译器不仅能够内联所有函数调用,还能够在编译时预先计算结果。所以我们可以看出,我们启用的优化越多,知道结果存储在哪里变得越来越无关紧要。
Where can I read about this?
所有汇编器都有些相似,因此通过学习任何汇编器的基础知识,您可以大致了解它们的工作原理。当您学习汇编程序时,您将了解函数调用约定如何“在引擎盖下”工作。一些资源可以在这里找到:https://whosebug.com/tags/assembly/info