

**********************************************
2010年3月4日

C51编译器基本完工了,变量类型的定义格式和C语言不同, 按如下格式:

    [8][9]int a = { ... };
    [8]*int a = { ... };
    *[8]int a = ???;
    **int a = ???;
    [8]*[9]int a = { ... };

支持的控制语句:

    和keil C一样，有 if、while、do while、for、switch等，
break语句是跳出整个控制语句向下执行，而continue是跳到当前控制语句的右花括号处执行。

另外增加了三种：
   a：once { ... } 
   表示只执行一次大括号里的语句，因为break语句也可以跳出once语句，
   所以有时候可能会用到，并且对于once语句，break和continue语句功能完全相同。

   b：forever { ... } 
   表示反复执行大括号里的语句，无限循环，可以用break跳出。

   c: loop( 整型表达式 ) { ... } 
   先求解整形表达式，得结果为n，再执行n次大括号的语句，这个语句是用djnz指令实现的，
   所以一般情况会比for语句执行快一些。

**********************************************
2010年3月5日

大三下半学期刚开学，到学校没有什么事，用16*16的LED点阵做了一个贪吃蛇游戏机，
发现了一个bug:

   //画蛇身
   public void draw()
   {
      uint8 i = 0;
      loop( length ) {
         screen.draw_point( snake_x[i], snake_y[i] );
         ++i;
      }
   }

假设蛇身长度length = 8，是一个静态变量，这段程序应该是执行8次，把蛇身各点坐标画到屏幕上，
但执行后length的值被改变了，成了0。然后试了试，把loop(length) 改成Loop(length + 1 - 1)
执行完后length还是8，符合原意。检查了一下编译器源代码,发现loop语句的处理有问题，它会修改
表达式变量,而 length + 1 - 1 运算的意思是生成一个临时变量值为 length, 
然后loop语句修改的是这个临时变量,不会影响原变量,这是一个变通的办法; 
现在改过来了,可以用 loop( length ) 而不会改变 length;

**********************************************
2010年3月7日

目前的编译器基本可以编译MCS51系列的芯片了,用128*64液晶屏写
了一个俄罗斯方块程序,测试通过;

语法上的主要特点:
设置了两条优先级序列，分别对应有符号和无符号的数，隐式转换如下：
uint8 -> uint16 -> uint24 -> uint32
int8  -> int16  -> int24  -> int32
只允许通过运算<uint>把有符号数转换为等长的无符号数,
<int>把无符号数转换为等长的有符号数，除此之外这两种类型的数没有任何联系，
不能混合运算，如uint8+int8，uint6*int6等都是不合法的。

**********************************************
修改时间: 2010年4月??日

学习凌阳的SPCE061A芯片，研究了这个芯片的汇编指令集，开始把编译器移植到这个芯片上；
做了一半，忽然发现没办法获取汇编中的变量地址，都被凌阳的汇编开发环境封装起来了，
那这样就不能实现指针和数组了，。。。哎，放弃了。换成AVR

**********************************************
修改时间: 2010年4月??日
最近把 uC编译器移植到了AVR单片机上(用ATMEGA8试验)，只生成汇编程序，然后再用AVR studio编译为hex文件；
把变量分配到内部的31个寄存器中,用小程序测试没问题;

**********************************************
修改时间: 2010年4月15日

程序稍大一点空间就不够了,于是修改编译器的地址分配, 把局部变量,形参等分配到1KB的外部RAM,
而内部的31个寄存器用于汇编库的运算,测试通过

**********************************************
修改时间: 2010年4月??日

目前编译器只是把C程序编译成汇编代码,然后调用AVR studio的汇编器生成HEX机器代码.
现在需要自己写一个汇编器. 花一天时间参考双龙AVR文档,把每个汇编指令弄成一个指令-机器码表，
然后写程序查找这个表，把汇编源程序翻译成机器码序列，再加上校验、地址等产生HEX文件。
写完后用一个流水灯程序和PROTEUS仿真测试，不行！仔细对比发现，
原来那个AVR文档里的机器码有不少错误,...汗..

**********************************************
修改时间: 2010年4月??日

最后的办法：在AVR Studio中依次输入所有的汇编指令，查看生成的机器码文件，
再和AVR文档相比较，得出每个指令的机器码。好乏味，真是个挑战耐力的事情。
花了一天时间，终于完成。用uC写了一个16*16点阵显示屏的弹球游戏，运行良好。
那个弹球游戏原本是针对MCS51单片机的，只是简单的改了一下引脚配置，就成功的在AVR上运行了。

**********************************************
修改时间: 2010年4月17日

到现在为止编译器基本支持AVR了. 关于AVR的机器码有个让人疑惑的地方，
比如，寄存器置位（SBR）和立即数或（ORI），寄存器位清零（CBI）和立即数与（ANDI）
等指令完全一致，CLR和EOR完全一致，按照这个规律，寄存器全置1的指令SER r16
也就是ORI r16，0xff的简写，但是不对：

  SER r16       机器码:  (H->L) 1110_1111_0000_1111  字节数：1 时钟数：1
  ORI r16,0xff  机器码:  (H->L) 0110_1111_0000_1111  字节数：1 时钟数：1

   仅仅差了一个最高位。既然SER指令完全可以用ORI实现，没有必要为它单独分配一个机器码。
非常疑惑....

**********************************************
修改时间: 2010年4月??日

现在uC支持三种单片机，MCS51、ATMEGA8 和凌阳的SPCE061A.目前的一个小小缺陷是
对于凌阳的SPCE061A不支持指针和数组，只能生成汇编程序，还需要用unSP编译为机器码文件。

**********************************************
修改时间: 2010年5月 - 9月
这段时间主要忙着专接本考试,放假了去农大给李老师做无线测温的项目，
9月接本大三开学后研究热转印制电路板；

