Joh*_*ane 11 c x86 assembly x86-64 low-level
我最近一直在努力让自己沉浸在汇编编程的世界中,最终目标是创建自己的编程语言.我希望我的第一个真正的项目是一个用C编写的简单汇编程序,它将能够组装一小部分x86机器语言并创建一个Windows可执行文件.没有宏,没有连接器.只是集会.
在纸面上,它似乎很简单.汇编代码进来,机器代码出来.
但是一旦我想到所有的细节,它就会突然变得非常艰巨.操作系统需要哪些约定?如何对齐数据并计算跳跃?可执行文件的内部甚至是什么样的?
我感到迷茫.我找不到任何关于这个的教程,看看流行汇编程序的源代码并不鼓舞人心(尽管我愿意再试一次).
我从哪里开始?你会怎么做的?有关于这个主题的任何好的教程或文献吗?
old*_*mer 14
我自己写了一些(汇编和反汇编程序),我不会从x86开始.如果你知道x86或任何其他指令集,你可以在短时间内(傍晚/下午)学习另一个指令集的语法,至少狮子会分享它.编写汇编程序(或反汇编程序)的行为肯定会教你一个快速的指令集,并且你会知道该指令集比那些没有检查过那个级别的微代码的指令集的许多经验丰富的汇编程序员更好.msp430,pdp11和thumb(不是thumb2扩展)(或mips或openrisc)都是很好的起点,不是很多指令,也不是过于复杂,等等.
我首先推荐一个反汇编程序,并使用一个固定长度的指令集,如arm或thumb或mips或openrisc等.如果没有,那么至少使用反汇编程序(肯定选择一个已经有汇编程序,链接器和反汇编)并用铅笔和纸理解机器代码和程序集之间的关系,特别是分支,它们通常有一个或多个怪癖,比如程序计数器是一个指令,或者当添加偏移量时提前两个,以获得另一个位它们有时在整个指令中测量而不是字节.
暴力破解用C程序解析文本非常容易阅读说明书.一个更艰巨的任务,但也许是教育,将使用bison/flex并学习编程语言,以允许这些工具创建(一个更极端的暴力)解析器,然后接口到您的代码,告诉你在哪里找到了什么.
汇编程序本身非常简单,只需读取ascii并设置机器代码中的位.分支和其他pc相关指令有点痛苦,因为它们可以通过源/表进行多次传递来完全解决.
mov r0,r1
mov r2 ,#1
Run Code Online (Sandbox Code Playgroud)
汇编程序开始解析一行的文本(定义为回车符0xD或换行符0xA后面的字节),丢弃空格(空格和制表符),直到你到达非空格的东西,然后strncmp与已知的助记符.如果你点击一个然后解析该指令的可能组合,在上面简单的情况下,在mov跳过白色空格到非白色空间之后,你可能发现的第一件事必须是一个寄存器,然后是可选的空格,然后是逗号.删除空格和逗号,并将其与字符串表进行比较,或者只是解析它.完成该注册后,再过去发现逗号的位置,然后说它是另一个寄存器或立即注册.如果立刻让我们说它必须有一个#符号,如果寄存器让我们说它必须从一个小写或大写'r'开始.在解析该寄存器或立即解析之后,请确保该行上没有其他内容不应该在该行上.为这个指令构建机器代码或者至少尽可能多地构建机器代码,然后继续下一行.这可能是乏味的,但解析ascii并不困难......
至少你会想要一个表/数组,它在创建时累积机器代码/数据,加上一些标记指令不完整的方法,pc相关指令将在未来通过时完成.您还需要一个表/数组来收集找到的标签以及找到的机器代码表中的地址/偏移量.除了指令中用作目标/源的标签以及表/数组中的偏移量,它们还包含部分完整的指令.在第一次传递之后,然后返回这些表,直到您将所有标签定义与用作源或目标的标签匹配,使用标签定义地址/偏移量来计算与相关指令的距离,然后完成创建该指令的机器代码.(可能需要进行一些反汇编和/或使用其他一些方法来记住以后为了完成构建机器代码而返回它时的编码类型).
下一步是允许多个源文件,如果这是您想要允许的内容.现在你必须拥有汇编程序无法解析的标签,因此你必须在输出中留下占位符并制作最长的跳转/分支指令,因为你不知道目的地有多远,预计会更糟.然后有你选择创建/使用的输出文件格式,那么链接器大部分都很简单,但是你必须记住为最终的pc相关指令填写机器代码,没有比汇编程序更难的了.本身.
注意,编写汇编程序并不一定与创建编程语言,然后为它编写编译器,单独的东西,不同的问题有关.实际上,如果您想要创建一种新的编程语言,只需使用现有的汇编程序来处理现有的指令集.当然不需要,但大多数教学和教程都将使用bison/flex方法编写语言,并且有很多大学课程讲义/资源用于开始编译器类,您可以使用它们来启动然后修改用于添加语言功能的脚本.中端和后端比前端更具挑战性.有很多关于这个主题的书籍以及许多在线资源.正如在另一个答案中所提到的,llvm并不是一个创建新编程语言的好地方,中间和后端都是为你完成的,你只需要专注于编程语言本身,即前端.
您正在寻找的不是教程或源代码,而是规范。请参阅http://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
一旦了解了可执行文件的规范,就可以编写一个程序来生成一个可执行文件。您构建的可执行文件应该尽可能简单。一旦掌握了这一点,您就可以编写一个简单的面向行的解析器,该解析器读取指令名称和数字参数以生成插入到 exe 中的代码块。稍后您可以添加符号、分支、部分,无论您想要什么,这就是像http://www.davidsalomon.name/assem.advertis/asl.pdf这样的内容。
PS Carl Norum 在上面的评论中有一个很好的观点。如果您的目标是创建自己的编程语言,那么学习编写汇编程序是无关紧要的,而且也不是正确的开始方式(除非您要创建的语言是汇编语言)。已经有汇编器可以从汇编器源代码生成可执行文件,因此您的编译器可以生成汇编器源代码,并且您可以避免重新创建汇编器的工作......而且您应该这样做。或者您可以使用 LLVM 之类的东西,它将解决编译器构建的许多其他令人畏惧的问题。您实际上能够生成自己的编程语言的可能性非常小,但如果您从头开始并且没有必要,那么可能性就会小得多。确定您的目标是什么,并使用可用的最佳工具来实现它。