找回密码
 立即注册
查看: 453|回复: 2

F351(9):用Forth 打造16位的新8051指令和新编译器的方法

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:16
  • 最近打卡:2025-04-30 08:41:32

105

主题

1215

回帖

1万

积分

荣誉版主

积分
12882
发表于 2024-11-30 14:47:48 | 显示全部楼层 |阅读模式
一、新的16位的8051指令设计
(1)8051指令集是8位的指令集,对于16/32位的数据操作就需要多条指令来完成。用8位8051汇编语言来写的程序,无论是用Keil的A51或者是用Fort的F051写的汇编语言程序比起C语言程序都有两个明显的差距:一个程序太长,另一个是重复性很高。如果汇编语言程序能够直接采用16/32位指令,则可以大大地缩短这个差距。
(2)本文范例仍然用LED交替闪烁的例子,其C语言的程序见下图:
Fig_01_C51.jpg
(3)上面C51程序涉及16位数据操作有4种:第26行的16位变量初值操作、第27和29行的16位减1操作、第28和30行的16位条件转移操作以及第46和50行的16位函数参数初值操作。本文将介绍如何用Forth打造这4种16位指令,以实现缩短Forth语言程序,达到与C语言程序一一对应的效果。
(4)Forth程序的设计与实现方法是“自上而下”的设计,“自下而上”的实现。为了打造新的“16位指令”,首先设计出最终的与上面C51程序对应的Forth语言程序,。

设计程序如下
Fig_02_F151_main.jpg
在上面的Forth 80151语言程序与C51程序一一对应,对应C51程序写在每行程序的注释中。
(5)参数设计:F80151语言采用Keil的C51规范,单个16位的函数参数放在R6R7寄存器对中,即Delay_MS函数的参数MS放在寄存器对R6R7中。
(6)变量设计:F80151语言采用Keil的C51规范,在进行优化后,将单个16位的函数局部变量放在R2R3寄存器对中,即Delay_MS函数的局部变量n放在寄存器对R2R3中。
(7)命名设计:F80151语言采用Keil的C51规范和8086的助记符规范,将16位目标操作数R6R7命名为“AX”寄存器,将16位源操作数R2R3命名为“BX”寄存器。
(8)指令设计:根据上面程序,共需要9条新的80151的16位指令:
1)“F151_AX_LD#”,初值指令,将16位立即数加载到AX寄存器中。
2)“F151_BX_LD#” ,初值指令,将16位立即数加载到BX寄存器中。
3)“F151_AX_DEC” ,减1指令,将16位AX寄存器中的值减1。
4)“F151_BX_DEC” ,减1指令,将16位BX寄存器中的值减1。
5)“F151_AX_JNZ” ,条件转移指令,如果16位AX寄存器中的值不等于0则转移。
6)“F151_BX_JNZ” ,条件转移指令,如果16位BX寄存器中的值不等于0则转移。
7)“F151_RETURN”,函数返回指令
8)“F151_SFR_LD#” ,初值指令,将8位立即数加载到SFR寄存器中。
9)“F151_GOTO”,无条件转移指令。
(9)总结:用Forth 打造16位的8051指令,先完成程序设计、参数设计、变量设计、命名设计和指令设计,然后再去用Forth语言去实现这些指令。

二、Forth程序的项目管理方法
(10)通常一个大一点的编程项目都是由多个程序文件组成,这就需要一个“项目管理”方法来控制这些程序按一定的次序进行编译、连接和输出,Forth语言编程也不例外:
Forth程序项目管理方法是不用专门的IDE,由用户在自己程序中各种“编译命令”来控制编译器按程序语句次序对文件进行模块加载、源程序编译、模块保存和HEX烧录文件生成。
(11)Forth提倡用一个专门的文本文件来使用这些编译命令,控制编译的进行,这个文件称为“项目文件”。
(12)本文范例“F051_16指令”子目录下有下列文件:
Fig_03_F151_文件.jpg
1)“01_P151.J”,Forth“项目”文件,文本文件。
2)“02_META.J”,Forth“元接口”程序文件,文本文件。
3)“03_BOOT.J”,Forth“引导”程序文件,文本文件。
4)“11_MAIN.J”,Forth“主函数”程序文件,文本文件。
5)“LOAD.COM”,DOS“COM”程序加载器。
6)“YTJ_F051.COM”,“倚天剑XCC51交叉编译器”DOS程序。
7)“YTJ_XCC51_V21.BAT”,启动“倚天剑XCC51交叉编译器”的批处理文件。
8)“Zap_HEX.bat”,防止头脑不清醒时出错,编译前先删除旧HEX格式烧录文件的批处理文件。
(13)在DOS、WinXP已经Win7-32位等操作系统下,双击“YTJ_XCC51_V21.BAT”批处理文件就可以进入DOS环境,执行YTJ_F051.COM程序,进入“倚天剑XCC51交叉编译器”命令行界面,此时键入“TF_LAOD 01_P151.J<CR>”,就可以编译本范例项目,生成“H80151.hex”烧录文件,把它烧录到STC8H单片机中执行就可以看到LED灯闪烁了。
下面是这一过程的视频:

视频中可以看到:
1)双击“YTJ_XCC51_V21.BAT”批处理文件进入进入倚天剑XCC51交叉编译器”命令行界面的过程:
Fig_04_XCC51.jpg
2)可以看到键入“TF_LAOD 01_P151.J<CR>”,开始编译本范例项目,生成“H80151.hex”烧录文件的过程:
Fig_05_LOAD.jpg
3)可以看到把它烧录到STC8H单片机中后打狗棒开发板上LED灯闪烁的过程:
Fig_06_LED.jpg
4)可以看到重新启动“倚天剑XCC51交叉编译器”进入命令行界面,键入了错误的命令“LIST”后,系统提示出错的结果和键入“BYE”命令后退出系统的过程:
Fig_07_ERROR.jpg

(14)重要结论:倚天剑XCC51交叉编译器具有执行手工命令,读写DOS文件以及完善的命令出错复位功能,如果再加上对文件的删除功能,就构成了一个“寄生在DOSINT21”上的微型的“操作系统”了。

三、构造8015116位指令的方法
(15)作为Forth“自下而上”的实现部分,本文范例的新16位指令在Forth程序文件“02_META.J”中构建:
Fig_08_16位指令.jpg
(16)第29行到第36行的程序转移指令的构造最简单,这两条指令本来在8051指令集中有,在F151中只需要加增加新定义就可以了。
重要说明:倚天剑XCC51交叉编译器 的设计目标是作为一个Forth操作系统因此采用标准Forth语法,采用英文冒号“:”和分号“;”来定义一个Forth复合词。前面介绍的金湖X51 Forth的设计目标是作为专门的Forth编译器,因此把英文冒号“:”和分号“;”留给了目标机专用,其本身用英文冒号“CW_:”和分号“;_CW”来定义一个Forth复合词。
(17)第43行到第45行构造了一个将16位立即数赋值给R6R7寄存器对的新16位指令。在Keil的A51汇编语言中,这个操作需要两条指令来完成:
MOV        R6, # HIGH(立即数)
MOV        R7, # LOW(立即数)
第44行Forth程序中的“DUP”字的意思就是把立即数复制两份,分别给R6和R7赋值用。
其中“R6,”的意思是将R6设置为目的操作数,其中的“100 / FF AND”这三个字换成十进制的意思是“把立即数除以256,然后再与255执行二进制AND操作”,这就是妥妥的“HIGH(立即数)”函数的操作了,然后的“MOV#”字就是执行8051的MOV指令。
同理该行程序后面的“FF AND”就是“LOW(立即数)”函数,然后“MOV#”指令将16位立即数的低8位赋值给R7。
(18)第54行到第58行构造了16位寄存器减1的新16位指令。实现的方法就是写一段将R6R7寄存器对做减去16位立即数1的8051指令程序。只是8051指令集中的寄存器名“A”、“B”、“C”在Forth语言中也是十六进制数符号,为避免混乱,在Forth汇编语言中将它变为了“ACC”、“BCC”和“CY”了。
(19)第69行到第72行构造了根据16位寄存器AX的值进行转移的新16位指令。由于R6R7寄存器对16位数据是否为0的充分必要条件是R6和R7的二进制OR操作后为0,所以实现的方法就是将R6和R7在累加器ACC中ORL,然后使用8051指令集的“JNZ”指令进行条件转移。
(20)第81行到第83行构造了对SFR进行立即数赋值的新指令。这段程序是展示Forth编译器如何根据8051二进制指令来构造新指令的方法。
在8051指令集中,向DATA空间的某个地址dir8(8位地址)写入一个立即数data8(8位)的二进制机器码由3个字节组成:75,dir8, data8,其中十六进制数“75”指令操作码,对应的汇编语言语句为“MOV  dir8, # data8”或者写为“MOV  d8, # i8” 。
倚天剑XCC51交叉编译器的Forth语言中,字“CODE_C,”的意思是把堆栈顶上一个数的最低8位以二进制的形式放到目标机的CODE空间中,存放的地址由编译器的地址指针“PC”决定,放完后“PC”的值加1,执行下一个存放地址。
第82行程序“75  CODE_C,  SWAP  CODE_C,  CODE_C,”的意思是首先将指令的操作码“75”写入CODE空间,然后交换两个操作数“SFR  V”的位置,先将SFR地址接着写入CODE空间,最后将要赋给SFR的值V写入CODE空间,形成一个完整的3字节机器码指令供CPU去执行。
(21)结论:使用上面这个方法,只要我们知道某个指令集的每个指令的二进制机器码,那么就可以用Forth系统构造出一个完整的“该指令集的编译器”。比如可以构造出80251指令集、ARM指令集或者RISC-V指令集的编译器。“倚天剑XCC51交叉编译器”就是针对8051单片机的编译器。
当然对于STC单片机现在和未来的新指令集,如法炮制,也可以用Forth系统打造出其专用的编译器,比如“Forth@AI8051U编译器”和“Forth@AI8052U编译器”。

四、Forth项目文件的结构
(22)Forth项目文件是一个文本文件,其内容本身也是一个“Forth源程序”,当用户输入命令“TF_LOAD项目文件名<CR>”之后,倚天剑XCC51交叉编译器就逐行从左到右依次执行每一个Forth字,对整个Forth项目进行编译、连接和输出。

下图是本文范例的项目文件程序:
Fig_09_项目文件.jpg
(23)第17行首先加载“02_META.J”源程序文件。Forth字“TF_include”的意思将后面文件名指定的文件以文本文件的在这个位置“包含”进来。Forth字“TF_include”与C语言“#inlucde”的功能是一样的。
(24)当第17行程序加载“META”程序,构造好了新的16位指令以后,第20行程序加载“11_MAIN.J”Forth主程序,用新的16位指令集编译与C语言一一对应的主程序。
(25)作为一个在STC单片机的可从0000H地址启动的独立运行的程序,第23行程序继续为项目添加引导程序,为主程序的运行建立起工作环境。
(26)第26行程序将从地址0000H到标号“Forth_Code_Top”地址范围的机器码按HEX格式输出为“H80151.hex”烧录文件。
其中标号“Forth_Code_Top”在“03_BOOT.J”程序中定义,位于本次编译的所有机器码的顶部。
(27)在完成本次由“TF_LOAD”命令执行的所有编译任务后,第29行程序“BYE”命令强制倚天剑XCC51交叉编译器系统退出,PC机回到DOS状态。用户还想要做什么操作,必须重新启动Forth系统。如前面的视频展示的那样。
(28)由于Forth在进行编译的过程中,由可能改变了系统的某些状态,留下一些新定义的Forth字,因此需要第,如果不退出系统,如果用户后面进行了错误操作可能导致不可预料的结果。

(29)当然如果用户有足够的把握,也可以不要第29行程序,不退出Forth系统,用户可以继续用手工命令继续进行编译工作,手工生成HEX格式的烧录文件。



附件:F051_打造16位指令.rar

126.59 KB, 阅读权限: 100, 下载次数: 26

1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:80
  • 最近打卡:2025-05-01 08:54:26
已绑定手机

0

主题

36

回帖

238

积分

中级会员

积分
238
发表于 2025-3-5 14:07:05 | 显示全部楼层
看上去很厉害的样子,学习一下
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民II
  • 打卡总天数:98
  • 最近打卡:2025-04-29 07:45:37

3

主题

74

回帖

358

积分

中级会员

积分
358
发表于 2025-3-5 14:45:41 | 显示全部楼层
学习啦
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:22 , Processed in 0.109044 second(s), 66 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表