C 为什么'main'以'ret'结尾而不是'ret 4'?
考虑以下空C程序(标准保证编译器执行隐式C 为什么'main'以'ret'结尾而不是'ret 4'?,c,disassembly,calling-convention,C,Disassembly,Calling Convention,考虑以下空C程序(标准保证编译器执行隐式返回0): 您可以在此函数中添加任何操作argc和argv的逻辑。然而,当main完成时,它的汇编代码将只执行一个简单的ret,而不是ret4。我希望看到一个ret4,因为在我看来main是其他函数的被调用方,因此必须从堆栈中清除它的两个参数:和int以及指向char数组的指针。为什么不这样做呢?大多数编译器选择让调用者清除堆栈中的参数;这一传统可以追溯到早期的C编译器和处理大量参数。在调用站点,编译器知道它推送了多少,因此调整堆栈对它来说很简单 另外,请
返回0
):
您可以在此函数中添加任何操作
argc
和argv
的逻辑。然而,当main
完成时,它的汇编代码将只执行一个简单的ret
,而不是ret4
。我希望看到一个ret4
,因为在我看来main
是其他函数的被调用方,因此必须从堆栈中清除它的两个参数:和int以及指向char数组的指针。为什么不这样做呢?大多数编译器选择让调用者清除堆栈中的参数;这一传统可以追溯到早期的C编译器和处理大量参数。在调用站点,编译器知道它推送了多少,因此调整堆栈对它来说很简单
另外,请注意,可以使用0-3(arge)参数指定历史上的main。同样,调用者(例如_start)可以只提供3,并让实现者选择。大多数编译器选择让调用者清除堆栈中的参数;这一传统可以追溯到早期的C编译器和处理大量参数。在调用站点,编译器知道它推送了多少,因此调整堆栈对它来说很简单
另外,请注意,可以使用0-3(arge)参数指定历史上的main。同样,调用者(例如_start)可以只提供3,并让实现者选择。main是u cdecl-因此堆栈必须调整调用者。必须是
ret
。即使是\uu stdcall
也将是ret2*(sizeof(void*)
-soret 8
或ret 16
但决不ret 4
吹毛求疵:argv
是指向指针的指针,而不是指向数组的指针。main是uuu cdecl-所以堆栈必须调整调用者。必须是ret
。即使是\uu stdcall
也将是ret 2*(sizeof(void*)
-soret 8
或ret 16
但决不ret 4
挑剔:argv
是指向指针的指针,而不是指向数组的指针。
int main(int argc, char* argv[]) {}