使用FreeBASIC设计8051单片机汇编编译器

发布时间:2024年01月13日

????????在STC论坛上看到有人用C++语言实现8051汇编编译器(源码),好奇下,试着用FB写了一下。

????????基本原理就是通过分析汇编文件然后转换为机器码。以下是51汇编与机器码对应的表格(数据来自网络,如果发现有误请联系QQ1493446087修正。)。

助记符说明字节周期机器码二进制机器码参数1参数2说明
NOP空操作11000000 0000//
ACALL addr 11绝对子程序调用22***0 0001a10a9a80 0001a7a6a5a4 a3a2a1a0/
LJMP addr 16长转移32020000 0010a15a14a13a12 a11a10a9a8a7a6a5a4 a3a2a1a0
RR AA右移一位11030000 0011//
INC AA加111040000 0100//
INC data直接字节加121050000 0101直接地址/
INC @Ri间接RAM加11106 - 070000 011i//i = 0,1
INC Rn寄存器加11108 - 0F0000 1rrr//r = 0 - 7
JBC bit,rel若直接位==1则转移且清除32100001 0000位地址相对地址 relrel = 标签地址 - 当前地址的下一个地址
AJMP addr 11绝对转移22***1 0001a10a9a81 0001a7a6a5a4 a3a2a1a0/
LCALL addr 16子程序调用32120001 0010a15a14a13a12 a11a10a9a8a7a6a5a4 a3a2a1a0
RRC AA带进位右移一位11130001 0011//
DEC AA减111140001 0100//
DEC data直接字节减121150001 0101直接地址/
DEC @Ri间接RAM减11116 - 170001 011i//i = 0,1
DEC Rn寄存器减11118 - 1F0001 1rrr//r = 0 - 7
JB bit,rel若直接位==1则转移32200010 0000位地址相对地址 rel
RET子程序调用返回12220010 0010//
RL AA循环左移一位11230010 0011//
ADD A,#data立即数加到A21240010 0100立即数/
ADD A,data直接字节加到A21250010 0101直接地址/
ADD A,@Ri间接RAM加到A1126 - 270010 011i//i = 0,1
ADD A,Rn寄存器加到A1128 - 2F0010 1rrr//r = 0 - 7
JNB bit,rel若直接位==0则转移32300011 0000位地址相对地址 rel
RETI中断程序调用返回12320011 0010//
RLC AA带进位左移一位11330011 0011//
ADDC A,#data立即数带进位加到A21340011 0100立即数/
ADDC A,data直接字节带进位加到A21350011 0101直接地址/
ADDC A,@Ri间接RAM带进位加到A1136 - 370011 011i//i = 0,1
ADDC A,Rn寄存器带进位加到A1138 - 3F0011 1rrr//r = 0 - 7
JC rel若C==1则转移22400100 0000相对地址 rel/
ORL data,AA或到直接字节21420100 0010直接地址
ORL data,#data立即数或到直接字节32430100 0011直接地址立即数
ORL A,#data立即数或到A21440100 0100立即数/
ORL A,data直接字节或到A21450100 0101直接地址/
ORL A,@Ri间接RAM或到A1146 - 470100 011i//i = 0,1
ORL A,Rn寄存器或到A1148 - 4F0100 1rrr//r = 0 - 7
JNC rel若C≠1则转移22500101 0000相对地址 rel/
ANL data,AA与到直接字节21520101 0010直接地址/
ANL data,#data立即数与到直接字节32530101 0011直接地址立即数
ANL A,#data立即数与到A21540101 0100立即数/
ANL A,data直接字节与到A21550101 0101直接地址/
ANL A,@Ri间接RAM与到A1156 - 570101 011i//i = 0,1
ANL A,Rn寄存器与到A1158 - 5F0101 1rrr//r = 0 - 7
JZ rel若A==0则转移22600110 0000相对地址 rel/
XRL data,AA异或到直接字节21620110 0010直接地址/
XRL data,#data立即数异或到直接字节32630110 0011直接地址立即数
XRL A,#data立即数异或到A21640110 0100立即数/
XRL A,data直接字节异或到A21650110 0101直接地址/
XRL A,@Ri间接RAM异或到A1166 - 670110 011i//i = 0,1
XRL A,Rn寄存器异或到A1168 - 6F0110 1rrr//r = 0 - 7
JNZ rel若A≠0则转移22700111 0000相对地址 rel/
ORL C,bit直接位或到进位位22720111 0010位地址/
JMP @A+DPTR相对于DPTR间接转移12730111 0011//
MOV A,#data立即数送A21740111 0100立即数/
MOV data,#data立即数送直接字节32750111 0101直接地址立即数
MOV @Ri,#data立即数送间接Rn2276 - 770111 011i立即数/i = 0,1
MOV Rn,#data立即数送寄存器2178 - 7F0111 1rrr立即数/r = 0 - 7
SJMP rel / JMP rel短转移22801000 0000相对地址 rel/
ANL C,bit直接位与到进位位22821000 0010位地址/
MOVC A,@A+PCA+PC寻址程序存贮字节送A12831000 0011//
DIV ABA除B14841000 0100//
MOV data,data直接字节送直接字节32851000 0101直接地址/
MOV data,@Ri间接Rn送直接字节2286 - 871000 011i直接地址/i = 0,1
MOV data,Rn寄存器送直接字节2188 - 8F1000 1rrr直接地址/r = 0 - 7
MOV DPTR,#data1616位常数送数据指针31901001 0000高立即数底立即数
MOV bit,C进位位送直接位22921001 0010位地址/
MOVC A,@A+DPTRA+DPTR寻址程序存贮字节送A12931001 0011//
SUBB A,#data从A中减去立即数和进位21941001 0100立即数/
SUBB A,data从A中减去直接字节和进位21951001 0101直接地址/
SUBB A,@Ri从A中减去间接RAM和进位1196 - 971001 011i//i = 0,1
SUBB A,Rn从A中减去寄存器和进位1198 - 9F1001 1rrr//r = 0 - 7
ORL C,/bit直接位的反码或到进位位22A01010 0000位地址/
MOV C,bit直接位送进位位21A21010 0010位地址/
INC DPTR数据指针加112A31010 0011//
MUL ABA乘B14A41010 0100//
MOV @Ri,data直接字节送间接Rn11A6 - A71010 011i//i = 0,1
MOV Rn,data直接数送寄存器22A8 - AF1010 1rrr直接地址/r = 0 - 7
ANL C,/bit直接位的反码与到进位位22B01011 0000位地址/
CPL bit直接位取反21B21011 0010位地址/
CPL C进位位取反11B31011 0011//
CJNE A,#data,rel立即数与A比较,不等转移32B41011 0100立即数相对地址 rel
CJNE A,data,rel直接数与A比较,不等转移32B51011 0101直接地址相对地址 rel
CJNE @Ri,#data,rel立即数与间接RAM比较,不等转移32B6 - B71011 011i立即数相对地址 reli = 0,1
CJNE Rn,#data,rel立即数与寄存器比较不等转移32B8 - BF1011 1rrr立即数相对地址 relr = 0 - 7
PUSH data直接字节入栈,SP加122C01100 0000直接地址/
CLR bit直接位清021C21100 0010位地址/
CLR C进位位清011C31100 0011//
SWAP AA半字节交换11C41100 0100//
XCH A,data直接字节与A交换21C51100 0101直接地址/
XCH A,@Ri间接Rn与A交换11C6 - C71100 011i//i = 0,1
XCH A,Rn寄存器与A交换11C8 - CF1100 1rrr//r = 0 - 7
POP data直接字节出栈,SP减122D01101 0000直接地址/
SETB bit直接位置位 121D21101 0010位地址/
SETB C进位位置位 111D31101 0011//
DA AA十进制调整11D41101 0100//
DJNE data,rel直接字节减1不为0转移32D51101 0101直接地址相对地址 rel
XCHD A,@Ri间接Rn与A低半字节交换11D6 - D71101 011i//i = 0,1
DJNE Rn,rel寄存器减1不为0转移22D8 - DF1101 1rrr相对地址 rel/r = 0 - 7
MOVX A,@DPTR外部数据送A(16位地址)12E01110 0000//
MOVX A,@Ri外部数据送A(8位地址)12E2 - E31110 0010//
CLR AA清011E41110 0011//
MOV A,data直接字节送A21E51110 0100直接地址/
MOV A,@Ri间接RAM送A11E6 - E71110 011i//i = 0,1
MOV A,Rn寄存器送A11E8 - EF1110 1rrr//r = 0 - 7
MOVX @DPTR,AA送外部数据(16位地址)12F01111 0000//
MOVX @Ri,AA送外部数据(8位地址)12F2 - F31111 001i//
CPL AA求反码11F41111 0100//
MOV data,AA送直接字节21F51111 0101直接地址/
MOV @Ri,AA送间接Rn12F6 - F71111 0101//i = 0,1
MOV Rn,AA送寄存器11F8 - FF1111 1rrr//r = 0 - 7

所以就可以开始分析汇编文件,然后根据以上表格转换对应的机器码。

1、使用main函数来接收控制台的命令参数

? ? FB里使用Main函数需要自己定义入口点,并使用__FB_ARGC__和__FB_ARGV__来获取参数。ParseAsmFile来解析ASM文件到机器码。CompileToHex将机器码转换为Hex文件。(具体实现看源码)

Private Function main(ByVal argc As Integer,ByVal argv As ZString Ptr Ptr) As Integer
    Print argc,*argv[1],*argv[2]
    'argc 是参数个数
    'argv 是命令行的参数指针
    '*argv[0] 表示第1个参数,是exe本身的名字
    '*argv[1] 表示第2个参数,这里固定为ASM文件名
    '*argv[2] 表示第3个参数,这里固定为Hex文件名
    If argc > 1 Then '有参数
        '1、解析命令(未完成)
        '根据命令添加8051默认寄存器
        '2、解析汇编文件
		ParseAsmFile(*argv[1])
        '3、输出Hex文件
		CompileToHex(*argv[2])
	End If
	Return 0
End Function

End main(__FB_ARGC__, __FB_ARGV__)

2、另外建立一个调用编译器的窗体工程

窗体如下:

测试打印信息:

源码工程

文章来源:https://blog.csdn.net/rainheart311/article/details/135570909
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。