我刚刚完成了这个学期的计算机体系结构课程,除此之外,我们一直在涉足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,并与nasm -f elf test.asm
汇总并与ld -o test test.o
关联。当我使用./test anArgument
调用它时,它按预期打印'anArgument',然后填充该字符串所需的许多字符总数为200个字符(因为mov edx, 200
语句)。但有趣的是,这些填充字符,我本来应该是胡言乱语,实际上来自我的环境变量的开头,如env
命令所示。为什么打印出我的环境变量?
答案 0 :(得分:6)
在不知道实际答案或有时间查找的情况下,我猜测环境变量在命令行参数之后存储在内存中。您的代码只是缓冲区溢出到环境变量字符串中并打印它们。
这实际上是有道理的,因为命令行参数由系统/加载器处理,环境变量也是如此,因此将它们存储在彼此附近是有意义的。要解决此问题,您需要找到命令行参数的长度,并且只打印那么多字符。或者,因为我假设它们是空终止字符串,所以打印直到达到零字节。
编辑: 我假设命令行参数和环境变量都存储在初始化数据部分(我相信NASM中的.data)
答案 1 :(得分:3)
为了理解为什么要获取环境变量,您需要了解内核如何在进程启动时排列内存。 Here是对图片的一个很好的解释(向下滚动到“堆栈布局”)。
答案 2 :(得分:1)
只要你好奇,你可能想知道如何打印你的字符串的地址(我认为它是传入的,你把它从堆栈中弹出)。另外,写一个十六进制转储例程,这样你就可以查看那个你很好奇的内存和其他地址。这可以帮助您发现有关程序空间的信息。
好奇心可能是程序员工具箱中最重要的事情。
我没有调查过启动过程的细节,但我认为每次启动一个新shell时,都会为它创建一个环境副本。您可能会看到由您运行的命令或您编写的脚本等启动的shell的剩余部分。