加法和减法如何影响 GameBoy 中的寄存器状态?
How does adding and subtracting affect register states in a GameBoy?
我目前正在开发 GameBoy 模拟器。在编码时,我开始质疑添加到寄存器会如何影响它。
cpu上有8个8位寄存器和4个16位寄存器。 8 位寄存器可以组合成 16 位寄存器。这是我在代码中表示它们的方式。
struct Registers{
//8 bit registers
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
uint8_t e;
uint8_t f;
uint8_t h;
uint8_t l;
//16 bit registers
uint16_t af;
uint16_t bc;
uint16_t de;
uint16_t hl;
};
问题:
如果低位寄存器的值为0b11111111,我给它加1。该位是继续到高位寄存器,还是环绕到低 8 位寄存器的开头。
如果低位寄存器的值为 0b00000000 并且我从中减去 1,它是保持为零,还是该位回绕到寄存器的顶部。
如果高位寄存器的值为0b00000000,我从中减1,会影响低位寄存器吗
首先,我认为您组织寄存器的方式不是很好,因为您有重复的信息(同时存储 a、f 和 af)。一种选择是使用联合;联合确保两个变量共享相同的内存位置。所以,你可以这样做:
struct Registers{
union{
struct{
uint_8t f;
uint_8t a;
};
uint_16t af;
};
// And so on for the rest...
};
这样您就可以单独操作每个 8 位寄存器 (registers.a) 或同时操作两者 (registers.af)。请注意,如果您在大端机器上进行开发,则应交换 f 和 a 以确保正确的字节顺序。
如果您的编译器不支持匿名结构和联合,我认为更好的选择是制作一个函数来操作两个 8 位寄存器并将它们移位以形成一个 16 位寄存器。这样您就不必在每次修改 a 和 af 时都访问它们。
现在回答你的实际问题。我的信息基于 this table (which contains some errors i've been told, so better to look at other sources to confirm them), and this manual。
问题一:
不行,它不进位到高位寄存器,它会溢出。
问题二:
同样的事情,它换行到 0xFF。
问题三:
假设您使用的是 8 位 ALU 运算,那么不会,同样不会影响它。
请注意,如果您使用 16 位 ALU 操作,那么它们会影响其他寄存器。例如:
假设 SP = 0x00FF;
ADD SP, 0x1 #Now SP does contain 0x0100 because you used 16 bit arithmetic.
但是:
假设 HL = 0x00FF;
ADD L, 1 # L Overflows to 0x00, however HL = 0x0000 because you used 8 bit arithmetic
我目前正在开发 GameBoy 模拟器。在编码时,我开始质疑添加到寄存器会如何影响它。
cpu上有8个8位寄存器和4个16位寄存器。 8 位寄存器可以组合成 16 位寄存器。这是我在代码中表示它们的方式。
struct Registers{
//8 bit registers
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t d;
uint8_t e;
uint8_t f;
uint8_t h;
uint8_t l;
//16 bit registers
uint16_t af;
uint16_t bc;
uint16_t de;
uint16_t hl;
};
问题:
如果低位寄存器的值为0b11111111,我给它加1。该位是继续到高位寄存器,还是环绕到低 8 位寄存器的开头。
如果低位寄存器的值为 0b00000000 并且我从中减去 1,它是保持为零,还是该位回绕到寄存器的顶部。
如果高位寄存器的值为0b00000000,我从中减1,会影响低位寄存器吗
首先,我认为您组织寄存器的方式不是很好,因为您有重复的信息(同时存储 a、f 和 af)。一种选择是使用联合;联合确保两个变量共享相同的内存位置。所以,你可以这样做:
struct Registers{
union{
struct{
uint_8t f;
uint_8t a;
};
uint_16t af;
};
// And so on for the rest...
};
这样您就可以单独操作每个 8 位寄存器 (registers.a) 或同时操作两者 (registers.af)。请注意,如果您在大端机器上进行开发,则应交换 f 和 a 以确保正确的字节顺序。
如果您的编译器不支持匿名结构和联合,我认为更好的选择是制作一个函数来操作两个 8 位寄存器并将它们移位以形成一个 16 位寄存器。这样您就不必在每次修改 a 和 af 时都访问它们。
现在回答你的实际问题。我的信息基于 this table (which contains some errors i've been told, so better to look at other sources to confirm them), and this manual。
问题一: 不行,它不进位到高位寄存器,它会溢出。
问题二: 同样的事情,它换行到 0xFF。
问题三: 假设您使用的是 8 位 ALU 运算,那么不会,同样不会影响它。
请注意,如果您使用 16 位 ALU 操作,那么它们会影响其他寄存器。例如:
假设 SP = 0x00FF;
ADD SP, 0x1 #Now SP does contain 0x0100 because you used 16 bit arithmetic.
但是:
假设 HL = 0x00FF;
ADD L, 1 # L Overflows to 0x00, however HL = 0x0000 because you used 8 bit arithmetic