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

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

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

助记符 说明 字节 周期 机器码 二进制机器码 参数1 参数2 说明
NOP 空操作 1 1 00 0000 0000 / /
ACALL addr 11 绝对子程序调用 2 2 ***0 0001 a10a9a80 0001 a7a6a5a4 a3a2a1a0 /
LJMP addr 16 长转移 3 2 02 0000 0010 a15a14a13a12 a11a10a9a8 a7a6a5a4 a3a2a1a0
RR A A右移一位 1 1 03 0000 0011 / /
INC A A加1 1 1 04 0000 0100 / /
INC data 直接字节加1 2 1 05 0000 0101 直接地址 /
INC @Ri 间接RAM加1 1 1 06 - 07 0000 011i / / i = 0,1
INC Rn 寄存器加1 1 1 08 - 0F 0000 1rrr / / r = 0 - 7
JBC bit,rel 若直接位==1则转移且清除 3 2 10 0001 0000 位地址 相对地址 rel rel = 标签地址 - 当前地址的下一个地址
AJMP addr 11 绝对转移 2 2 ***1 0001 a10a9a81 0001 a7a6a5a4 a3a2a1a0 /
LCALL addr 16 子程序调用 3 2 12 0001 0010 a15a14a13a12 a11a10a9a8 a7a6a5a4 a3a2a1a0
RRC A A带进位右移一位 1 1 13 0001 0011 / /
DEC A A减1 1 1 14 0001 0100 / /
DEC data 直接字节减1 2 1 15 0001 0101 直接地址 /
DEC @Ri 间接RAM减1 1 1 16 - 17 0001 011i / / i = 0,1
DEC Rn 寄存器减1 1 1 18 - 1F 0001 1rrr / / r = 0 - 7
JB bit,rel 若直接位==1则转移 3 2 20 0010 0000 位地址 相对地址 rel
RET 子程序调用返回 1 2 22 0010 0010 / /
RL A A循环左移一位 1 1 23 0010 0011 / /
ADD A,#data 立即数加到A 2 1 24 0010 0100 立即数 /
ADD A,data 直接字节加到A 2 1 25 0010 0101 直接地址 /
ADD A,@Ri 间接RAM加到A 1 1 26 - 27 0010 011i / / i = 0,1
ADD A,Rn 寄存器加到A 1 1 28 - 2F 0010 1rrr / / r = 0 - 7
JNB bit,rel 若直接位==0则转移 3 2 30 0011 0000 位地址 相对地址 rel
RETI 中断程序调用返回 1 2 32 0011 0010 / /
RLC A A带进位左移一位 1 1 33 0011 0011 / /
ADDC A,#data 立即数带进位加到A 2 1 34 0011 0100 立即数 /
ADDC A,data 直接字节带进位加到A 2 1 35 0011 0101 直接地址 /
ADDC A,@Ri 间接RAM带进位加到A 1 1 36 - 37 0011 011i / / i = 0,1
ADDC A,Rn 寄存器带进位加到A 1 1 38 - 3F 0011 1rrr / / r = 0 - 7
JC rel 若C==1则转移 2 2 40 0100 0000 相对地址 rel /
ORL data,A A或到直接字节 2 1 42 0100 0010 直接地址
ORL data,#data 立即数或到直接字节 3 2 43 0100 0011 直接地址 立即数
ORL A,#data 立即数或到A 2 1 44 0100 0100 立即数 /
ORL A,data 直接字节或到A 2 1 45 0100 0101 直接地址 /
ORL A,@Ri 间接RAM或到A 1 1 46 - 47 0100 011i / / i = 0,1
ORL A,Rn 寄存器或到A 1 1 48 - 4F 0100 1rrr / / r = 0 - 7
JNC rel 若C≠1则转移 2 2 50 0101 0000 相对地址 rel /
ANL data,A A与到直接字节 2 1 52 0101 0010 直接地址 /
ANL data,#data 立即数与到直接字节 3 2 53 0101 0011 直接地址 立即数
ANL A,#data 立即数与到A 2 1 54 0101 0100 立即数 /
ANL A,data 直接字节与到A 2 1 55 0101 0101 直接地址 /
ANL A,@Ri 间接RAM与到A 1 1 56 - 57 0101 011i / / i = 0,1
ANL A,Rn 寄存器与到A 1 1 58 - 5F 0101 1rrr / / r = 0 - 7
JZ rel 若A==0则转移 2 2 60 0110 0000 相对地址 rel /
XRL data,A A异或到直接字节 2 1 62 0110 0010 直接地址 /
XRL data,#data 立即数异或到直接字节 3 2 63 0110 0011 直接地址 立即数
XRL A,#data 立即数异或到A 2 1 64 0110 0100 立即数 /
XRL A,data 直接字节异或到A 2 1 65 0110 0101 直接地址 /
XRL A,@Ri 间接RAM异或到A 1 1 66 - 67 0110 011i / / i = 0,1
XRL A,Rn 寄存器异或到A 1 1 68 - 6F 0110 1rrr / / r = 0 - 7
JNZ rel 若A≠0则转移 2 2 70 0111 0000 相对地址 rel /
ORL C,bit 直接位或到进位位 2 2 72 0111 0010 位地址 /
JMP @A+DPTR 相对于DPTR间接转移 1 2 73 0111 0011 / /
MOV A,#data 立即数送A 2 1 74 0111 0100 立即数 /
MOV data,#data 立即数送直接字节 3 2 75 0111 0101 直接地址 立即数
MOV @Ri,#data 立即数送间接Rn 2 2 76 - 77 0111 011i 立即数 / i = 0,1
MOV Rn,#data 立即数送寄存器 2 1 78 - 7F 0111 1rrr 立即数 / r = 0 - 7
SJMP rel / JMP rel 短转移 2 2 80 1000 0000 相对地址 rel /
ANL C,bit 直接位与到进位位 2 2 82 1000 0010 位地址 /
MOVC A,@A+PC A+PC寻址程序存贮字节送A 1 2 83 1000 0011 / /
DIV AB A除B 1 4 84 1000 0100 / /
MOV data,data 直接字节送直接字节 3 2 85 1000 0101 直接地址 /
MOV data,@Ri 间接Rn送直接字节 2 2 86 - 87 1000 011i 直接地址 / i = 0,1
MOV data,Rn 寄存器送直接字节 2 1 88 - 8F 1000 1rrr 直接地址 / r = 0 - 7
MOV DPTR,#data16 16位常数送数据指针 3 1 90 1001 0000 高立即数 底立即数
MOV bit,C 进位位送直接位 2 2 92 1001 0010 位地址 /
MOVC A,@A+DPTR A+DPTR寻址程序存贮字节送A 1 2 93 1001 0011 / /
SUBB A,#data 从A中减去立即数和进位 2 1 94 1001 0100 立即数 /
SUBB A,data 从A中减去直接字节和进位 2 1 95 1001 0101 直接地址 /
SUBB A,@Ri 从A中减去间接RAM和进位 1 1 96 - 97 1001 011i / / i = 0,1
SUBB A,Rn 从A中减去寄存器和进位 1 1 98 - 9F 1001 1rrr / / r = 0 - 7
ORL C,/bit 直接位的反码或到进位位 2 2 A0 1010 0000 位地址 /
MOV C,bit 直接位送进位位 2 1 A2 1010 0010 位地址 /
INC DPTR 数据指针加1 1 2 A3 1010 0011 / /
MUL AB A乘B 1 4 A4 1010 0100 / /
MOV @Ri,data 直接字节送间接Rn 1 1 A6 - A7 1010 011i / / i = 0,1
MOV Rn,data 直接数送寄存器 2 2 A8 - AF 1010 1rrr 直接地址 / r = 0 - 7
ANL C,/bit 直接位的反码与到进位位 2 2 B0 1011 0000 位地址 /
CPL bit 直接位取反 2 1 B2 1011 0010 位地址 /
CPL C 进位位取反 1 1 B3 1011 0011 / /
CJNE A,#data,rel 立即数与A比较,不等转移 3 2 B4 1011 0100 立即数 相对地址 rel
CJNE A,data,rel 直接数与A比较,不等转移 3 2 B5 1011 0101 直接地址 相对地址 rel
CJNE @Ri,#data,rel 立即数与间接RAM比较,不等转移 3 2 B6 - B7 1011 011i 立即数 相对地址 rel i = 0,1
CJNE Rn,#data,rel 立即数与寄存器比较不等转移 3 2 B8 - BF 1011 1rrr 立即数 相对地址 rel r = 0 - 7
PUSH data 直接字节入栈,SP加1 2 2 C0 1100 0000 直接地址 /
CLR bit 直接位清0 2 1 C2 1100 0010 位地址 /
CLR C 进位位清0 1 1 C3 1100 0011 / /
SWAP A A半字节交换 1 1 C4 1100 0100 / /
XCH A,data 直接字节与A交换 2 1 C5 1100 0101 直接地址 /
XCH A,@Ri 间接Rn与A交换 1 1 C6 - C7 1100 011i / / i = 0,1
XCH A,Rn 寄存器与A交换 1 1 C8 - CF 1100 1rrr / / r = 0 - 7
POP data 直接字节出栈,SP减1 2 2 D0 1101 0000 直接地址 /
SETB bit 直接位置位 1 2 1 D2 1101 0010 位地址 /
SETB C 进位位置位 1 1 1 D3 1101 0011 / /
DA A A十进制调整 1 1 D4 1101 0100 / /
DJNE data,rel 直接字节减1不为0转移 3 2 D5 1101 0101 直接地址 相对地址 rel
XCHD A,@Ri 间接Rn与A低半字节交换 1 1 D6 - D7 1101 011i / / i = 0,1
DJNE Rn,rel 寄存器减1不为0转移 2 2 D8 - DF 1101 1rrr 相对地址 rel / r = 0 - 7
MOVX A,@DPTR 外部数据送A(16位地址) 1 2 E0 1110 0000 / /
MOVX A,@Ri 外部数据送A(8位地址) 1 2 E2 - E3 1110 0010 / /
CLR A A清0 1 1 E4 1110 0011 / /
MOV A,data 直接字节送A 2 1 E5 1110 0100 直接地址 /
MOV A,@Ri 间接RAM送A 1 1 E6 - E7 1110 011i / / i = 0,1
MOV A,Rn 寄存器送A 1 1 E8 - EF 1110 1rrr / / r = 0 - 7
MOVX @DPTR,A A送外部数据(16位地址) 1 2 F0 1111 0000 / /
MOVX @Ri,A A送外部数据(8位地址) 1 2 F2 - F3 1111 001i / /
CPL A A求反码 1 1 F4 1111 0100 / /
MOV data,A A送直接字节 2 1 F5 1111 0101 直接地址 /
MOV @Ri,A A送间接Rn 1 2 F6 - F7 1111 0101 / / i = 0,1
MOV Rn,A A送寄存器 1 1 F8 - FF 1111 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、另外建立一个调用编译器的窗体工程

窗体如下:

测试打印信息:

源码工程

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-13 18:14:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-13 18:14:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-01-13 18:14:01       87 阅读
  4. Python语言-面向对象

    2024-01-13 18:14:01       96 阅读

热门阅读

  1. C++面试八股--inline函数

    2024-01-13 18:14:01       47 阅读
  2. Vue中避免滥用this去读取data中数据

    2024-01-13 18:14:01       62 阅读
  3. Flutter--常用技术文档

    2024-01-13 18:14:01       43 阅读
  4. 网络基础面试题(五)

    2024-01-13 18:14:01       55 阅读
  5. Redis 内存碎片

    2024-01-13 18:14:01       58 阅读