2

这学期我刚完成一门计算机体系结构课程,除其他外,我们一直在涉足 MIPS 汇编并在 MARS 模拟器中运行它。今天,出于好奇,我开始在我的 Ubuntu 机器上摆弄 NASM,基本上只是从教程中拼凑起来,感受 NASM 与 MIPS 的不同之处。这是我目前正在查看的代码片段:

global _start

_start:

    mov eax, 4
    mov ebx, 1
    pop ecx
    pop ecx
    pop ecx
    mov edx, 200
    int 0x80
    mov eax, 1
    mov ebx, 0
    int 0x80

这被保存为 test.asm,并用 .asm 组装nasm -f elf test.asm和链接ld -o test test.o。当我用 调用它时./test anArgument,它会按预期打印“anArgument”,然后是将该字符串填充到总共 200 个字符所需的字符数(由于该mov edx, 200语句)。然而,有趣的是,这些填充字符,我原以为是乱码,实际上是从我的环境变量的开头开始的,正如env命令所显示的那样。为什么这会打印出我的环境变量?

4

3 回答 3

7

在不知道实际答案或有时间查找的情况下,我猜测环境变量在命令行参数之后存储在内存中。您的代码只是缓冲区溢出到环境变量字符串中并打印它们。

这实际上是有道理的,因为命令行参数由系统/加载器处理,环境变量也是如此,因此它们彼此靠近存储是有意义的。要解决这个问题,您需要找到命令行参数的长度,并且只打印那么多字符。或者,因为我假设它们是空终止的字符串,所以打印直到达到零字节。

编辑:我假设命令行参数和环境变量都存储在初始化数据部分(NASM 中的 .data,我相信)

于 2008-12-03T16:55:07.973 回答
2

为了理解为什么要获取环境变量,您需要了解内核如何在进程启动时安排内存。是一个很好的图片解释(向下滚动到“堆栈布局”)。

于 2008-12-04T07:00:24.557 回答
1

只要您好奇,您可能想弄清楚如何打印字符串的地址(我认为它已经传入,然后您将其从堆栈中弹出)。另外,编写一个十六进制转储例程,这样您就可以查看您感兴趣的内存和其他地址。这可以帮助您发现有关程序空间的信息。

好奇心可能是程序员工具箱中最重要的东西。

我没有调查启动进程的细节,但我认为每次启动一个新的 shell 时,都会为它制作一个环境副本。您可能会看到由您运行的命令或您编写的脚本等启动的 shell 的剩余部分。

于 2008-12-03T17:17:22.703 回答