Nat*_*man 14 compiler-construction x86 assembly
我目前正在编写编译器,我似乎遇到了一些问题,让它输出代码在一个不错的时间框架内执行.
编译器的简要概述:
7Basic是一个编译器,旨在将7Basic代码直接编译为目标架构/平台的机器代码.目前,7Basic在给定源文件的情况下生成x86程序集.
问题是编译器生成的汇编代码速度慢且效率低.
例如,此代码(编译为此汇编代码)的执行时间比等效的C代码长近80.47倍.
部分问题是编译器生成如下代码:
push eax
push 5000000
pop ebx
pop eax
Run Code Online (Sandbox Code Playgroud)
而不是更合乎逻辑:
mov ebx,5000000
Run Code Online (Sandbox Code Playgroud)
......完成同样的事情.
我的问题是:有哪些技巧可以避免这类问题?解析器基本上使用递归来解析表达式,因此生成的代码反映了这一点.
Gre*_*ill 16
一种技术称为窥孔优化.这需要一种迭代方法来清理汇编代码.基本上,您扫描汇编代码,一次只查看两个或三个指令,并查看是否可以将它们简化为更简单的操作.例如,
push eax ; 1
push 5000000 ; 2
pop ebx ; 3
pop eax ; 4
Run Code Online (Sandbox Code Playgroud)
第一步将查看第2行和第3行,并将其替换为:
push eax ; 1
mov ebx,5000000 ; 2a
pop eax ; 4
Run Code Online (Sandbox Code Playgroud)
其次,您可能会考虑1和4,如果eax未在中间指令中触及,请将它们全部删除,留下您想要的内容:
mov ebx,5000000 ; 2a
Run Code Online (Sandbox Code Playgroud)
您可能想要考虑生成C代码而不是汇编,然后让C编译器(例如gcc)为您处理代码生成.试图重新发明轮子是没有意义的.
我目前正在学习编译器课程。我在输出高效代码方面取得了一些很大的进步,但是你应该看看龙书。这是一个成人仪式。您应该看一下 Jeremy Bennett 的书《编译技术简介:使用 ANSI C、LEX 和 YACC 的第一门课程》中的代码。这本书本身很难找到,但是您可以免费下载编译器的源代码
http://www.jeremybennett.com/publications/download.html
代码生成器文件(cg.c)具有一些用于生成相当优化的代码的函数。目标语言不是 i386,但您应该考虑查看他如何描述寄存器并跟踪符号表条目的存储位置。他的输出汇编可以进一步优化,但它为生成在某些方面可以与 gcc -S 的输出相媲美的代码提供了良好的基础。
一种通用的优化是减去堆栈指针,以便在进入函数时为所有局部变量和临时变量保留空间。然后只需参考偏移量,而不是不断地推送/弹出。
例如,如果您的中间代码是四元组的列表,您应该简单地为每个函数迭代它并跟踪最大偏移量。然后输出该行以减去堆栈上的空间量。这样就不需要打开和关闭如此多的变量。要消除弹出它们的需要,您只需将它们的值从堆栈上的偏移量移动到寄存器中即可。这将显着提高性能。