Lee*_*ogg 4 c compiler-construction z80 gameboy
我花了很多时间学习GameBoy编程,因为我已经熟悉Z80汇编我不怕开始使用它.我(当然)发现使用C或C++编程更有效率,但是找不到GameBoy的完整编译器,我可以找到自己管理的所有编译器,并且不向程序员提供系统寄存器的访问权限,也有一些编译器可怕的缺点,如100%CPU利用率和无中断支持.
是否有可能像Arduino的AVR编译器那样解决系统寄存器问题?能够简单地用其名称来寻址CPU或系统寄存器,例如DDRD = %10101011
将中断和系统寄存器添加到编译器中需要做些什么?所有但一个系统寄存器都只有一个字节的内存地址和中断向量是当然的存储位置,唯一的一个系统寄存器,是不是内存地址只能有两个安装说明进行修改EI
和DI
但可能是内联函数是否正确?
通常的策略是创建自己的指向系统寄存器的指针.我不知道DDRD的地址,但这样的事情应该是诀窍:
volatile unsigned char *reg_DDRD = (unsigned char *)0xE000;
*reg_DDRD = 0xAB;
Run Code Online (Sandbox Code Playgroud)
大多数C编译器不支持二进制常量,但您可以将它们与一些宏hackery一起使用.您可以使用宏来制作更直观的语法:
#define DDRD (*reg_DDRD)
DDRD = 0xAB;
Run Code Online (Sandbox Code Playgroud)
当vanilla C代码同样可以正常工作时,修改编译器是没有意义的.
处理中断归结为解决3个问题.第一种是让中断向量地址跳转到C函数.因为在ROM中,您需要修改C运行时环境以初始化它.这取决于系统,但通常你要做的是添加一个如下所示的汇编语言文件:
org 38h ; or wherever the gameboy CPU jumps to on interrupt
jp _intr_function
Run Code Online (Sandbox Code Playgroud)
这应该导致CPU进入intr_function()
C程序.您可能需要也可能不需要领先的下划线.并且您可能无法在汇编程序文件中设置目标地址,org
而是必须使用链接器和节来愚弄.
第二个问题是C函数不一定会保存它应该的所有寄存器.您可以通过向其添加内联汇编来执行此操作,如下所示:
void intr_function()
{
asm(" push af");
asm(" push bc");
asm(" push de");
asm(" push hl");
// ... now do what you like here.
asm(" pop hl");
asm(" pop de");
asm(" pop bc");
asm(" pop af");
}
Run Code Online (Sandbox Code Playgroud)
最后,可能必须通过操作硬件寄存器来确认中断.但你可以在C代码中做到这一点,所以没什么特别的.
我不清楚wait循环的问题.标准C编译器没有内置的这样的功能.它们调用main(),如果你想循环,它取决于你.确实,Arduino SDK中使用的类C语言有自己的内置无限循环来调用你编写的函数,但这不是正常的C.