编程语言和方法效率低下吗? (需要汇编语言和 C 语言知识)
很长一段时间,我都在思考和研究C语言编译器的汇编形式的输出,以及CPU架构。我知道这对你来说可能很愚蠢,但在我看来,有些东西是非常无效的。如果我错了,请不要生气,并且有一些我不明白所有这些原则的原因。如果您告诉我为什么这样设计,我将非常高兴。事实上,我真的相信我错了,我知道将个人电脑组装在一起的人们的天才头脑知道这样做的理由。你问具体是什么?我马上告诉你,我以C为例:
1:堆栈本地范围内存分配:
所以,典型的本地内存分配使用堆栈。只需将 esp 复制到 ebp,然后通过 ebp 分配所有内存。好的,如果您明确需要通过默认堆栈值分配 RAM,我会理解这一点,但如果我理解正确的话,现代操作系统使用分页作为应用程序和物理 RAM 之间的转换层,当您想要的地址在到达实际 RAM 之前进一步转换时字节。那么为什么不直接说 0x00000000 是 int a,0x00000004 是 int b 等等呢?只需通过 mov 0x00000000,#10 即可访问它们?因为您实际上不会访问内存块 0x00000000 和 0x00000004,而是访问操作系统设置分页表的内存块。实际上,由于 ebp 和 esp 的内存分配使用间接寻址,“我的”方式会更快。
2:变量分配口是心非:
当您运行应用程序时,Loader将其代码加载到RAM中。当您创建变量或字符串时,编译器会生成代码,在 main 中创建时将这些值推送到堆栈顶部。因此,有这样做的实际指令,以及内存中的实际数字。因此,RAM 中有 2 个具有相同值的条目。第一个是指令的形式,第二个是 RAM 中实际字节的形式。但为什么?为什么不只在声明变量 count 时将其位于哪个内存块中,而不是在使用时只插入此内存位置?
for a long time, I am thinking and studying output of C language compiler in assembler form, as well as CPU architecture. I know this may be silly to you, but it seems to me that something is very ineffective. Please, don´t be angry if I am wrong, and there is some reason I do not see for all these principles. I will be very glad if you tell me why is it designed this way. I actually truly believe I am wrong, I know the genius minds of people which get PCs together knew a reason to do so. What exactly, do you ask? I´ll tell you right away, I use C as a example:
1: Stack local scope memory allocation:
So, typical local memory allocation uses stack. Just copy esp to ebp and than allocate all the memory via ebp. OK, I would understand this if you explicitly need allocate RAM by default stack values, but if I do understand it correctly, modern OS use paging as a translation layer between application and physical RAM, when address you desire is further translated before reaching actual RAM byte. So why don´t just say 0x00000000 is int a,0x00000004 is int b and so? And access them just by mov 0x00000000,#10? Because you wont actually access memory blocks 0x00000000 and 0x00000004 but those your OS set the paging tables to. Actually, since memory allocation by ebp and esp use indirect addressing, "my" way would be even faster.
2: Variable allocation duplicity:
When you run application, Loader load its code into RAM. When you create variable, or string, compiler generates code that pushes these values on the top o stack when created in main. So there is actual instruction for do so, and that actual number in memory. So, there are 2 entries of the same value in RAM. One in form of instruction, second in form of actual bytes in the RAM. But why? Why not to just when declaring variable count at which memory block it would be, than when used, just insert this memory location?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您将如何实现递归函数?您所描述的相当于在任何地方使用全局变量。
这只是一个问题。如何链接到预编译的目标文件并确保它不会损坏程序的内存?
How would you implement recursive functions? What you are describing is equivalent to using global variables everywhere.
That's just one problem. How can you link to a precompiled object file and be sure it won't corrupt the memory of your procedures?
因为 C(和大多数其他语言)支持递归,所以函数可以调用自身,并且函数的每次调用都需要任何局部变量的单独副本。另外,在大多数当前的处理器上,您的方法实际上会更慢 - 间接寻址非常常见,因此处理器针对它进行了优化。
您似乎希望 C 的行为(或者至少 C 允许)用于字符串文字。这有好处也有坏处,例如即使您定义了一个“变量”,您实际上也无法修改其内容(不会影响指向同一位置的其他变量)。
Because C (and most other languages) support recursion, so a function can call itself, and each call of the function needs separate copies of any local variables. Also, on most current processors, your way would actually be slower -- indirect addressing is so common that processors are optimized for it.
You seem to want the behavior of C (or at least that C allows) for string literals. There are good and bad points to this, such as the fact that even though you've defined a "variable", you can't actually modify its contents (without affecting other variables that are pointing at the same location).
您的问题的答案大多包含在不同存储类别的不同语义中
The answers to your questions are mostly wrapped up in the different semantics of different storage classes
由于您正在比较汇编程序和 c(从体系结构的角度来看它们非常接近),我倾向于说您正在描述微优化,这是没有意义的,除非您分析代码以查看它是否性能更好。
一般来说,编程语言正在朝着更具声明性的风格发展(即告诉计算机你想要做什么,而不是你想要如何完成)。当您使用命令式语言(如汇编语言或 c)进行编程时,您需要极其详细地指定您希望如何解决问题。这使得编译器几乎没有空间代表您做出优化决策。
然而,随着语言变得更加声明性,编译器变得更加智能,因为我们为它们提供了进行更智能的性能优化所需的空间。
Since you are comparing assembler and c (which are very close together from an architectural standpoint), I'm inclined to say that you're describing micro-optimization, which is meaningless unless you profile the code to see if it performs better.
In general, programming languages are evolving towards a more declarative style (i.e. telling the computer what you want done, rather than how you want it done). When you program in an imperative language (like assembly or c), you specify in extreme detail how you want the problem solved. This gives the compiler little room to make optimization decisions on your behalf.
However, as the languages become more declarative, the compilers are getting smarter, because we are giving them the room they need to make more intelligent performance optimizations.
如果每个函数都将其第一个变量放在偏移量 0 处,依此类推,那么每次进入函数时都必须更改内存映射(如果要递归,则无法将所有变量分配给唯一地址)。这是可行的,但对于当前的硬件来说,速度非常慢。此外,虚拟内存执行的地址转换也不是免费的,有效实现这一点实际上相当复杂。
寻址 ebp(或任何其他寄存器)需要使用多路复用器(用于选择寄存器)和加法器(用于将偏移量添加到寄存器)。此操作所花费的时间通常会与其他操作重叠。
如果您希望能够修改静态值,则必须将其复制到堆栈中。如果你不这样做(说它是'const'),那么一个好的C编译器不会将它复制到堆栈。
If every function would put its first variable at offset 0 and so on then you would have to change the memory mapping each time you enter a function (you could not allocate all variables to unique addresses if you want recursion). This is doable, but with current hardware it's very slow. Furthermore, the address translation performed by the virtual memory is not free either, it's actually quite complicated to implement this efficiently.
Addressing off ebp (or any other register) costs having a mux (to select the register) and an adder (to add the offset to the register). The time taken for this can often be overlapped with other operations.
If you want to be able to modify the static value you have to copy it to the stack. If you don't (saying it's 'const') then a good C compiler will no copy it to the stack.