从堆栈的角度来看,为什么 main 函数与其他函数不同

Why does main function differ from other function from stack point of view

我正在学习使用 gdb,我有点困惑。这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void g(char *password) {
}

int main(int argc, char *argv[]) {
if(argc > 1)
    {
        g(argv[1]);
    } 
}

所以对于常规函数(本例中的g()),如果我想检查函数参数,那就是 ebp+8, ebp+12.. etc. But inmainfunction when I'm trying to examine command line arguments (for exampleargv[1]` )在这种情况下,以前检查参数的方法似乎不起作用。所以我的问题是:

  1. argv 的内存是动态分配的吗(比如malloc)?
  2. 为什么不同大小的参数会改变 argv 本身的地址?("A" 是 0xbffff084 但 "A"x10 是 0xbffff074 )
  3. 为什么 argv 离 ebp 这么远?(在我的例子中,当我提供 "A" 作为命令时,ebp 出现在 0xbfffefe8argv 0xbffff084行参数)
  4. 命令行参数和 ebp 寄存器之间是什么?
  5. 最后一个问题(不是关于这个主题的,而是......) 如何查看文件的实际内容?我的意思是当程序在汇编开始之前是 运行 时,有一些指令是 运行。例如检查文件是否与您的操作系统兼容等...
    抱歉,如果问题听起来很愚蠢,我是 gdb 的新手。谢谢。
  1. 不,内存不是动态分配的。在main(_start)之前的函数中,argvargc被压入栈中,与main

    [=29=一起使用]
  2. 地址的变化与参数个数无关。可能是蝴蝶拍打翅膀的另一个过程导致了这个

  3. 这取决于实现。这很难说。但是你可以在GDB中运行这个命令自己看看:

    disass _start
    
  4. ^^^

函数参数是 argv,与任何其他具有类型 char** 的参数一样,它是一个普通参数。 argv[1] 不是函数参数,它是 argv 的偏移量和取消引用,您会在预期位置(取决于目标 ABI)找到 is .

也许这说明了一切。在使用 GCC 和 GAS 组装相同代码时发现了这一点:

# GCC
# Stack is:
#ESP -> ret addr
#       argc
#       argv -> argv[0] -> "program name"
#               argv[1] -> "Key"
#               argv[2] -> "Infile"
#               argv[3] -> "Outfile"

# GAS
# Stack is:
#ESP -> argc
#       argv[0] -> "program name"
#       argv[1] -> "Key"
#       argv[2] -> "Infile"
#       argv[3] -> "Outfile"

我记得 "argv-list" 是由 OS 构建的。