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

        在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、另外建立一个调用编译器的窗体工程

窗体如下:

测试打印信息:

源码工程

第1章 单片机基础 1.1 单片机技术发展状况 1.2 51系列单片机体系结构 1.2.1 内部结构 1.2.2 存储器组织结构 l.2.3 内部功能模块 l.2.4 外部引脚 1.2.5 系统资源扩展 1.3 单片机的编程方法 第2章 C语言编程基础 2.1 基本概念 2.1.1 概述 2.1.2 变量与算术表达式 2.1.3 for语句 2.1.4 符号常量 2.2 数据类型、运算符和表达式 2.2.1 C语言的数据类型 2.2.2 常量与变量 2.2.3 整型数据 2.2.4 实型数据 2.2.5 字符型数据 2.2.6 运算符 2.2.7 表达式 2.3 程序控制语句 2.3.1 程序的3种基本结构 2.3.2 条件控制语句 2.3.3 程序应用举例 2.4 循环控制语句 2.4.1 while语句 2.4.2 dowhile语句 2.4.3 for语句 2.4.4 break与continue语句 2.4.5 程序应用举例 2.5 小结 第3章 C语言高级编程 3.1 函数与程序结构 3.1.1 函数的基本知识 3.1.2 返回非整数值的函数 3.1.3 外部变量 3.1.4 作用域规则 3.1.5 头文件 3.1.6 静态变量 3.1.7 寄存器变量 3.1.8 分程序结构 3.1.9 初始化 3.1.10 递归 3.2 数组 3.2.1 一维数组 3.2.2 维数组 3.2.3 多维数组 3.2.4 数组的初始化 3.3 指针 3.3.1 指针与指针变量. 3.3.2 指针变量的定义与引用 3.3.3 指针运算符与指针表达式 3.3.4 指针与数组 3.3.5 指针的地址分配 3.3.6 指针数组 3.3.7 指向指针的指针 3.4 占构体与共用体 3.4.1 结构体类型变量的定义和引用 3.4.2 结构体数组的定义和引用 3.4.3 结构体指针的定义和引用 3.4.4 共用体 3.5 小结 第4章C51程序设计 4.1 C51对标准C语言的扩展 4.1.1 存储区域 4.1.2 数据变量分类 4.1.3 存储器模式 4.1.4 绝对地址的访问 4.1.5 指针 4.1.6 函数 4.2 C5 1函数库 4.2.1 字符函数CTYPE.H 4.2.2 一般I/O函数STDIO.H 4.2.3 字符串函数STRING.H 4.2.4 标准函数STDLIB.H 4.2.5 数学函数MATH.H 4.2.6 绝对地址访问ABSACC.H 4.2.7 内部函数INTRINS.H 4.2.8 变量参数表STDARG.H 4.2.9 全程跳转SETJMPH 4.2.10 访问SFR和SFR bit地址REGxxx.H 4.3 C51程序编写 4.3.1 C程序基本结构 4.3.2 编写高效的C51程序及优化程序 第5章 Windows集成开发环境μVision2 5.1 μVision2编辑界面及其功能介绍 5.1.1 μVision2界面综述 5.1.2 主菜单栏 5.1.3 μVision2功能按钮 5.1.4 μVision2窗口环境 5.2 应用μVision2开发流程介绍 5.2.1 建立新项目 5.2.2 常用环境配置 5.2.3 代码优化 5.2.4 目标代码调试 5.3 CPU仿真 5.3.1 μVision2调试器 5.3.2 调试命令 5.3.3 存储器空间 5.3.4 表述(Expressions) 5.3.5 技巧 5.4 深入了解μVision2 5.4.1 μVision2的项目管理 5.4.2 使用技巧 5.4.3 μVision2调试函数 第6章 C5l编译器 6.1 预处理 6.1.1 宏定义 6.1.2 文件包含 6.1.3 条件编译 6.1.4 其他预处理命令 6.2 C51编译器控制指令详解 6.2.1 源控制指令 6.2.2 列表控制指令 6.2.3 目标控制指令 6.3 C5l的高级配置文件 6.3.1 目标程序启动配置文件——STARTUP.A51. 6.3.2 CPU初始化文件——START751.A51 6.3.3 静态变量初始化文件——INT.A51 6.3.4 专用变量初始化文件——INIT751.A51 第7章 C51的典型资源编程 7.1 中断系统设计 7.2 定时/计数器的使用 7.3 I/O口的使用 7.4 扩展存储器 7.4.1 外部ROM 7.4.2 外部RAM 7.4.3 外部串行E2PROM 7.5 一个使用多种资源的完整例程 7.5.1 项目需求 7.5.2 步进电机背景知识 7.5.3 解决方案设计与实现 第8章 单片机通信 8.1 串口通信 8.1.1 串行通信基础 8.1.2 单片机串口使用 8.2 单片机点对点通信 8.2.1 通信接口设计 8.2.2 单片机点对点通信程序设计 8.3 单片机多机通信 8.3.1 主机部分通信程序设计 8.3.2 从机部分通信程序设计 8.4 单片机I2C总线通信 8.4.1 I2C总线介绍 8.4.2 I2C总线硬件接口设计 8.4.3 I2C总线模拟硬件接口软件设计 8.4.4 I2C总线系统的设计要点 8.5 单片机与计算机的互连 8.5.1 电路设计 8.5.2电路的C5 1程序代码 8.5.3计算机端的Visual C++程序代码 第9章 C51单片机的工程开发实例 9.1 单片机系统设计方法 9.2 C51系统设计的相关知识 9.2.1 硬件以及电路的知识 9.2.2 软件以及编程语言的知识 9.3 C5l系统设计需要注意的一些问题 9.3.1 单片机资源的分配 9.3.2 单片机的寻址 9.3.3 C5 1函数的返回值 9.3.4 单片机的看门狗功能 9.3.5 单片机的外设 9.3.6 单片机的功耗 9.4 有关C51的一些问题 9.5 键盘和发光数码管显示 9.5.1 电路设计的背景及功能 9.5.2 电路的设计 9.5.3 键盘扫描电路的C51程序代码 9.5.4 电路的改进——键盘的消抖动程序 9.5.5 电路的显示部分-LED数码管电路 9.6 A/D、D/A转换器使用 9.6.1 电路设计的背景及功能 9.6.2 电路的设计 9.6.3 电路的C51程序代码 9.7 基于单片机的数字钟 9.7.1 电路设计的背景及功能 9.7.2 电路的设计 9.7.3 电路的C51程序代码 第10章 C5l单片机典型模块实例 10.1 典型外部ROM和RAM器件的使用 10.1.1 实例功能 10.1.2 器件和原理 10.1.3 电路 10.1.4 程序设计 10.2 液晶显示和驱动实例 10.2.1 实例功能 10.2.2 器件和原理 10.2.3 电路 lO.2.4 程序设计 10.3 用A/D芯片进行电压测量 10.3.1 实例功能 10.3.2 器件和原理 10.3.3 电路 10.3.4 程序设计 lO.4 使用DSl820进行温度补偿和测量 10.4.1 实例功能 10.4.2 器件和原理 10.4.3 电路 10.4.4 程序设计 10.5 语音芯片在单片机系统中的使用 10.5.1 实例功能 10.5.2 器件和原理 10.5.3 电路 10.5.4 程序设计 10.6 时钟芯片在单片机系统中的应用 10.6.1 实例功能 10.6.2 器件和原理 10.6.3 电路 10.6.4 程序设计 10.7 单片机中滤波算法的实现 10.8 信号数据的FFT变换
FreeBASIC 是一种免费的开源 BASIC 编程语言,它提供了许多图形编程的支持。CGpGraphics 是 GDI+ 中的一个图形绘制类,可以用它来绘制和处理图像。如果你想要在 FreeBASIC使用 CGpGraphics 来压缩图片,可以按照以下步骤进行: 1. 首先,你需要安装 .NET Framework 的最新版本,并将 GDI+ 库引入到 FreeBASIC 项目中。 2. 接下来,你需要创建一个 GpBitmap 对象,它可以从文件或内存中加载图像。例如,你可以使用 GpImage.FromFile 方法从文件中加载图像。 3. 然后,你需要创建一个新的 GpBitmap 对象作为输出缓冲区,并使用 GpGraphics 对象的 DrawImage 方法将输入图像绘制到输出缓冲区中。 4. 最后,你可以使用 GpEncoderParameters 对象来设置压缩参数,并使用 GpImage.Save 方法将输出缓冲区中的图像保存到文件或内存中。 下面是一个使用 CGpGraphics 压缩图片的示例代码: ``` #include once "vbcompat.bi" #include once "gdiplus.bi" ScreenRes 800, 600, 32 Dim Compressor As GpImageCodecInfo Ptr Dim Params As GpEncoderParameters Dim Image As GpImage Dim Bitmap As GpBitmap Dim Graphics As GpGraphics Dim Status As GpStatus ' 初始化 GDI+ 库 Status = GdiplusStartup(0, 0, 0) ' 加载图像 Image = GpImage.FromFile("input.jpg") ' 创建输出缓冲区 Bitmap = GpBitmap.Create(Image.GetWidth(), Image.GetHeight(), PixelFormat32bppARGB) Graphics = GpGraphics.CreateFromImage(Bitmap) ' 绘制图像 Graphics.DrawImage(Image, 0, 0) ' 设置压缩参数 Compressor = GpImageCodecInfo.FindEncoderByMimeType("image/jpeg") Params.Count = 1 Params.Parameter(0).Guid = EncoderQuality Params.Parameter(0).Type = EncoderParameterValueTypeLong Params.Parameter(0).NumberOfValues = 1 Params.Parameter(0).Value = VarPtr(90) ' 保存图像 Status = Bitmap.Save("output.jpg", Compressor.Clsid, Params) ' 清理资源 Graphics.Dispose() Bitmap.Dispose() Image.Dispose() ' 关闭 GDI+ 库 GdiplusShutdown() ``` 在上面的示例代码中,我们首先使用 GdiplusStartup 函数初始化 GDI+ 库,然后使用 GpImage.FromFile 方法加载输入图像。接着,我们创建一个 GpBitmap 对象作为输出缓冲区,并使用 GpGraphics 对象的 DrawImage 方法将输入图像绘制到输出缓冲区中。接下来,我们使用 GpImageCodecInfo 和 GpEncoderParameters 对象来设置压缩参数,并使用 GpImage.Save 方法将输出缓冲区中的图像保存到文件中。最后,我们使用 GdiplusShutdown 函数关闭 GDI+ 库,并释放所有资源。 需要注意的是,上面的示例代码仅供参考,具体实现方式可能因平台和版本而异。在实际使用中,你需要根据自己的需求和环境进行相应的修改和调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值