为什么编译器会创建一个"两次"变量?

B.G*_*ill 1 c windows compiler-construction

我知道这是一个更"沉重"的问题,但我认为它也很有趣.这是我之前关于编译器功能的问题的一部分,但是我回答的非常糟糕,许多人回答了我的第一个问题,所以它是:

因此,如果我的知识是正确的,现代Windows系统使用分页作为切换任务的方式,并保证每个任务都在内存中占有一席之地.因此,每个流程从0开始都有自己的位置.

当多任务处理生效时,内核必须将所有重要的寄存器保存到任务堆栈我相信比保存当前堆栈指针,更改页面条目以切换到另一个进程的物理地址空间,加载新进程堆栈指针,弹出保存通过调用poped指令指针地址来注册并继续.

对于这个不错的功能(分页)而言,每个进程都认为它具有良好的平坦内存.因此,没有远端跳转,远指针,内存段或数据段.一切都很好,线性.

但是,当流程没有更多细分时,为什么编译器仍然在堆栈上创建变量,或者直接在其他内存空间中创建变量,而不是直接在程序代码中?

让我举个例子,我有一个C代码:int a=10;

它被翻译成(英特尔语法):mov [position of a],#10

但实际上,你实际上在RAM中的字节数比需要的多.Becouse,前几个字节接受actuall指令,在该指令完成后,有一个包含值10的新字节.

为什么,而不是这个,当不需要切换任何段(从而减慢处理速度)时,不仅仅是10的值直接编码到程序中,如下所示:

xor eax,eax //just some instruction
10 //the value iserted to the program
call end //just some instruction

Becouse编译器知道每条指令的确切位置,当使用该变量操作时,它只会使用它的地址.

我知道,const变量可以做到这一点,但是当你无法改变它们时,它们不是真正的变量.

我希望我能很好地解释我的问题,但我仍然在学习英语,所以请原谅我的同情甚至是语义上的错误.

编辑:

我已经阅读了你的答案,似乎基于那些我可以修改我的问题:

所以,有人告诉我,全局变量实际上是直接附加到程序中的那一段值,我的意思是,当变量是全局变量时,它是在程序结束时,还是在执行时就像本地变量一样创建,但是而不是直接在堆上堆栈?

如果第一种情况 - 附加到程序本身,为什么甚至存在局部变量?我知道,你会告诉我因为递归,但事实并非如此.当你调用函数时,你可以在堆栈上推送任何内存空间,因此那里没有程序.

我希望你理解我,当某些指令在堆栈上创建一些值(甚至为0)时,总是会无法使用内存,因为你需要在程序中为该指令而不是实际的var.像这样:push #5 //instruction that says to create local variable with integer 5 并且比这个指令只让第5个堆栈.请帮帮我,我真的很想知道为什么会这样.谢谢.

dmc*_*kee 5

考虑:

  • 如果一个例程被递归地调用(甚至间接地在一个递归的正确解析器中)或者来自多个线程,则局部变量可能同时存在多个,并且这些情况发生在相同的内存上下文中
  • 标志着程序存储器不可写,堆栈+堆非可执行文件是针对某些类型的攻击(堆栈溢出...)一个小而有用的防御和由一些操作系统(我不知道如果Windows此但是)

您的提案不允许这两种情况.