1、申 请 I D:孤星
2、个人邮箱:bookhanming@yahoo.com
3、原创技术文章:
前言
我是一位来自马来西亚的中年单身汉,从1995年便开始学习汇编,当时主攻i8086指令码。最近几年,我有开始复出研究i386指令码,以及PE和ELF可执行文件格式。我总共做了三款简单编译器,分别是DOS (.COM),Windows (PE32),Linux (ELF64)。
我对反向编译感兴趣,这也是我申请加入《吾爱破解》论坛的缘由。
编译器的设计
今次我只介绍如何设计一款简单的编译器,着重的后端,这款编译器只接受两项指令:
WriteLine xxxxxx (显示字符串和换行)
ReadLine (等待用户按回车键)
我前后花费了3个小时来研究ELF64格式,概括如下:(自己动手绘制)
根据我从https://uclibc.org/docs/elf-64-gen.pdf 所获取的文件格式信息(虽然有点就旧,但是变化不大),以下是重要的文件头,分成:FileHeader, ProgramHeader (x2).
只要填妥一个FileHeader,两个ProgramHeader文件头(分别给CodeSegmentHeader和DataSegmentHeader),就可以将代码段和数据段加以填充。
我只需用汇编(FASM)写成一个源文件然后编译成Linux x64的可执行文件,就能开始破解自己的程序,以求知道如何设计一款属于自己的高级程序语言的简单编译器。
这是反汇编结果:
重点是EAX值为0时(syscall 0)是从标准I/O流读取,EAX值为1时(syscall 1)是从标准I/O流写入,而最后EAX值为60(或0x3C)(syscall 60)则是终止程序。
因此,在代码段(也就是紧接着64+56+56字节的文件头之后),开始根据指令生成CPU指令码。
例如:
WriteLine xxxxx 等于
[Asm] 纯文本查看 复制代码 MOV EDX, 字符串长度
LEA RSI, [RIP + 数据段地址]
MOV EDI, 0x1 ;StdOut
MOV EAX, 0x1
SYSCALL
ReadLine 等于[Asm] 纯文本查看 复制代码 MOV EDX, 保留缓冲长度
LEA RSI, [RIP + 数据段地址]
MOV EDI, 0x1 ;StdOut (正确的StdIn是0,不过两者通用)
XOR EAX, EAX
SYSCALL
然后我的Pascal代码(编译器后端)会计算出数据段地址,如下:
以下示范我的编译器(Pipit)如何编译52pojie.txt源代码至 52pojie ELF64可执行程序:
希望能通过申请,感谢论坛管理员! |