我想用python做个tiny BASIC编译器。赋值和加减乘除,IF和FOR。

语法分析python有ply包,用ply.lex和ply.yacc做个计算器很简单,我已经做了。

做个解释器应该也不难。但解释器和编译器之间还差着代码生成呢。一来看书,二来用python的dis包看"汇编"形式的bytecode,连蒙带猜,应该也可以做,但不做怎知道难处?

a = b + c + d; 解释器遇到c + d就求值并把结果放在栈里或某处。编译器呢?看到c和d push,遇到+ add 栈顶和次栈顶,pop pop push? 如何分配寄存器?

搞个寄存器名字栈,栈溢出了咋办?编译时显示OOR (Out of Register)错误,表达式忒复杂了,请自行添加临时变量,哈哈。

用汇编可以偷个懒:汇编器支持jmp label啊。不用自己算要跳到哪儿或跳多远了。

汇编器本来想用nasm,但它不带linker. link.exe? 不想下个大包。

Go Tools for Windows (assembler, resource compiler, linker, debugger and information) (godevtool.com)

啥都有,而且有许多例子。这可是像模像样地能生成.exe,而且还是Windows,不是DOS的。

D:\asm>goasm 1.asm

GoAsm.Exe Version 0.61.0.1 - Copyright Jeremy Gordon 2001-2017 - JG@JGnet.co.uk
Output file: 1.obj

D:\asm>golink /console 1.obj kernel32.dll

GoLink.Exe Version 1.0.3.1 Copyright Jeremy Gordon 2002-2020 info@goprog.com
Output file: 1.exe
Format: Win32 Size: 2,048 bytes

D:\asm>1
Hello World (from GoAsm)

DATA SECTION
;
RCKEEP DD 0             ;temporary place to keep things
;
CODE SECTION
;
START:
PUSH -11D               ;STD_OUTPUT_HANDLE
CALL GetStdHandle       ;get, in eax, handle to active screen buffer
PUSH 0,ADDR RCKEEP      ;RCKEEP receives output from API
PUSH 24D,'Hello World (from GoAsm)'    ;24=length of string
PUSH EAX                ;handle to active screen buffer
CALL WriteFile
XOR EAX,EAX             ;return zero
RET

看来return 0 (xor eax, eax)就行,不用int 21。我也不是非得学会调用WriteFile(GetStdHandle),数都留在寄存器里,不print,生成的.exe在调试器(Go Tools里有,甚至还有IDE)运行即可。

D:\asm>copy con 1.py
quit(13)^Z
已复制 1 个文件。

D:\asm>1.py

D:\asm>echo %ERRORLEVEL%
13

我真是太机智了,调试器也不用了。试了下MOV EAX, 257:

D:\asm>echo %ERRORLEVEL%
257

D:\asm>echo %ErrorLevelL%
%ErrorLevelL%

D:\asm>echo %errorlevel%
257

我根本没打算算>100的数。IF x op y THEN算了,光有and算啥?not, or也得有。>= <= 还是得有的吧。

posted on 2021-12-04 23:59  华容道专家  阅读(98)  评论(0)    收藏  举报