1

在为我的 6502/NES 仿真器创建指令函数时,我一直在理解 6502 中带符号字节和二进制补码的概念。显然,诸如 BMI 之类的分支指令使用内存中的带符号字节进行前向/后向分支,还有一些指令允许对负数进行算术运算。负标志也检测累加器的第 7 位。(二进制补码)

这是否意味着内存中的所有字节都已签名,并且我可以将内存初始化为int8_t CPUMEMORY[0x10000];而不是uint8_t CPUMEMORY[0x10000]

不过,困扰我的是,当运算结果超过无符号 8 位限制(即 255)时会设置进位标志。但如果所有字节都已签名,这不应该是 127 吗?(溢出标志可以做到这一点,但是有一个进位标志有什么意义呢?)

4

2 回答 2

3

内存中的字节只是字节:它们既没有符号也没有无符号。然而,一个字节的值可以解释为有符号数 (int8_t) 或无符号数 (uint8_t)。两个连续字节(int16_t 或 uint16_t)的值和四个连续字节(int32_t 或 uint32_t)的值相同。

为了处理这些字节,您有几个 6502 指令,允许您对有符号和无符号解释执行多个操作。您只需要使用正确的指令并使用正确的标志(进位、溢出、否定......)来完成您需要做的事情。

于 2017-07-30T19:46:27.693 回答
1

进位用于多字节算术(除其他外)。

这些主题已经写了数百次,所以我只引用一个好的来源

1.2 审查两个补码(签名)号码

一个字节有 256 个可能的值;在十六进制中,它们是:$00 到 $FF。8 位无符号数的范围是 0 ($00) 到 255 ($FF)。16 位无符号数的范围是 0 ($0000) 到 65535 ($FFFF),依此类推。它们被称为无符号数,因为它们为零或更大,即没有(减号)符号。另一方面,有符号数可以是负数或正数(或零)。下面使用术语“有符号数”来表示二进制补码(尽管还有其他表示有符号数的方式)。8 位有符号数的范围是 -128 到 127。值 -128 到 -1 在十六进制中分别为 $80 到 $FF。值 0 到 127 分别是十六进制的 $00 到 $7F。所以有符号数的最小值是 $80,而有符号数的最大值是 $7F。16 位有符号数的范围是 -32768 ($8000) 到 32767 ($7FFF)($8000 到 $FFFF 是负数),依此类推。这似乎是一种处理负数的奇怪方法,但这种方法有几个有用的属性。

首先,0 到 127(8 位有符号和无符号数字范围的重叠)在十六进制中是 $00 到 $7F,无论该数字是有符号还是无符号。

其次,当数字为非负数(0 到 127)时,最高有效位(8 位数字的第 7 位)为零,当数字为负数时为 1。事实上,这就是 6502 的 N(负)标志的名称。(请注意,当 N 标志受指令影响时,它反映了该指令结果的第 7 位。)另一个注意事项:在数学中,零不是正数或负数,但在计算机世界中,事情较少正式的; 术语“正数”通常包括零,因为 (a) 最高有效位为零的有符号数的所有其他可能值都是正数,并且 (b) 无符号数的所有其他可能值都是正数.

第三,考虑以下添加:

CLC
LDA #$FF
ADC #$01

结果(在累加器中)为 00 美元,并且设置了进位。无符号数的加法是:255 + 1 = 256(请记住,进位已设置)。有符号数的加法是 -1 + 1 = 0。换句话说,加(和减)有符号数与加(和减)无符号数完全相同。

6502.org 也有关于标志和溢出标志的详细讨论。

于 2017-07-30T21:45:25.247 回答