如何处理“不可能”的Chip-8指令

时间:2016-05-21 21:57:13

标签: hex emulation machine-code chip-8

所以我一直在使用Chip-8模拟器作为我的CompSci类的最终项目,并且遇到了一个似乎超出我的代码的问题。我下载的大量演示(我确信它们是真正的Chip-8程序,而不是SuperChip或类似的东西)包含的机器指令不符合任何Chip-8操作码的格式。

http://mattmik.com/files/chip8/mastering/chip8.html

在页面底部是所有操作码的列表,每个操作码长2个字节,以及它们中的每个半字节数字代表什么。但是,相当数量的程序具有不符合任何指令格式的指令。例如,这是一个来自其中一个的十六进制转储 - 我会在其中指出一些个别情况

0000000 6a 00 6b 04 6c 01 6d 00 6e 02 23 26 23 20 60 30
0000010 61 01 f0 15 f0 07 f1 18 30 00 12 14 22 42 23 20
0000020 7d 01 23 20 60 08 e0 a1 23 0a 4a 00 12 3e a3 62
0000030 d8 91 79 01 d8 91 4f 01 12 f4 49 18 12 e4 22 b2
0000040 12 1e 4c 01 22 6c 4c 02 22 7a 4c 03 22 88 4c 04
0000050 22 96 4c 05 22 a4 a3 59 d6 72 44 00 00 ee a3 57
0000060 d4 52 42 00 00 ee a3 5b d2 32 00 ee 66 28 67 09
0000070 64 00 65 00 62 00 63 00 00 ee 66 28 67 0e 64 28
0000080 65 14 62 00 63 00 00 ee 66 28 67 07 64 28 65 0c
0000090 62 16 63 11 00 ee 66 28 67 07 64 28 65 0e 62 16
00000a0 63 14 00 ee 66 28 67 05 64 28 65 10 62 16 63 0b
00000b0 00 ee a3 59 d6 72 76 fe d6 72 44 00 00 ee a3 57
00000c0 d4 52 74 02 44 44 74 c0 d4 52 42 00 00 ee a3 5b
00000d0 d2 32 72 02 4c 04 72 02 4c 05 72 02 42 44 72 c0
00000e0 d2 32 00 ee 7c 01 6d 00 6e 02 00 e0 4c 06 6c 01
00000f0 6a 00 12 0a 60 06 f0 18 7b ff 4b 00 13 08 6d 00
0000100 6e 02 00 e0 6a 00 12 0a 13 08 4a 01 00 ee 60 02
0000110 f0 18 6a 01 88 d0 78 01 89 e0 79 01 d8 91 00 ee
0000120 a3 54 dd e2 00 ee 64 19 63 00 a3 56 d3 41 73 08
0000130 33 40 13 2c 63 1e 64 1b fc 29 d3 45 4b 04 a3 5f
0000140 4b 03 a3 60 4b 02 a3 61 4b 01 a3 62 63 01 74 02
0000150 d3 41 00 ee 80 f8 ff 80 e0 10 70 88 ee 11 77 aa
0000160 a8 a0 80 00                                    
0000164

在0x154,有

80 f8

但是没有以8开头的指令可以以8结尾 - 以8结尾的唯一合法指令必须以1,2,3,4,5,6,7或e结尾。另一个,在0x158,

e0 10

也没有指令符合这种格式。以e开头的任何指令的第二个字节必须是9E或A1。

这只是少数错误 - 在整个代码中还有几个“不可能”的指令

我做错了什么吗?我该如何处理这些说明?只是跳过它们?我用作Chip-8资源的页面是不完整的?任何关于如何处理这个问题的建议都非常感谢。谢谢!

2 个答案:

答案 0 :(得分:5)

请记住,我特别不熟悉chip-8;一般只是低级计算。

这很可能是数据;构成游戏的图形和声音。你不必处理它&#34 ;;如果程序写得正确,指令指针永远不会指向该区域。

如果它最终指向那里,那就像是除以零一样的错误; "处理它"无论你想要什么,大概是通过向用户显示一条消息说"你试图执行无效的指令。"

当程序员说出未定义的行为时,他们的意思是什么;"字面上没有定义当指令指针指向不是指令的东西时应该发生的事情。你可以做任何你想做的事,因为一个正确制作的程序永远不应该这样做(在现实生活中他们总是这么做,事实上,但他们真的不应该这样做。)

答案 1 :(得分:1)

你假设二进制文件中的每个字节对都是一条指令吗?这将是一个糟糕的假设。当您遵循切入点的筹码规则并遵循可能的代码路径时,这些不可能的指令会出现吗?固定或可变长度指令集,各种体系结构(arm,mips,x86等),你会发现二进制数据不是指令,这就是它的工作原理。反汇编一个完整大小的arm程序(固定长度32位指令)你会发现未定义的指令,因为它们不是指令,它们是数据,地址需要到达远距离,ascii字符串等。固定长度你可以从零到最后和diassemble(假设它是固定长度,并且那里没有拇指代码),但你只需要允许/忽略非法位模式。如果这就是你要击中的那个。它并不总是完美的,但是为了尝试消除它们中的一些,你应该遵循可能的执行路径(你几乎不得不为变长指令集做这些)。

现在,如果您正在模拟获取这些并正确模拟,那么您正在遵循执行路径。我们可能无法帮助你。你有正确的字节顺序吗,你正确地解释字节对吗?也许你很幸运一段时间然后打了一个未定义的?

编辑:

这是我用二进制文件得到的所有内容,因为它没有描述0x300s中的内容

0000: 6A00
mov r10,0x00
0002: 6B04
mov r11,0x04
0004: 6C01
mov r12,0x01
0006: 6D00
mov r13,0x00
0008: 6E02
mov r14,0x02
000A: 2326
call 326
0326: 0000
UNDEFINED

比我看到的模拟器和其他文档更糟糕的说电脑从0x200开始,你的二进制文件没有任何数据。

好的,所以我刚刚敲出了一个chip8模拟器,到目前为止你的程序还没有击中任何未定义的。它正在等待击键和其他我尚未手动解码的东西。

将尝试使用反汇编程序。

EDIT2:

所以我敲了一个反汇编程序,它没有点击那些地址,它结束于

034E : 0x7402  add v4,0x02
0350 : 0xD341  drw v3,v4,1
0352 : 0x00EE  ret

你可以自己敲打一个,按照所有代码路径,希望你得到相同的结果。

0xBnnn指令是我认为唯一可以绊倒你的指令,因为它在执行时依赖于数据,因此你必须模拟它(具有可能真正发生的所有可能组合)以查看它可以采取的位置您。基本上,如果你遇到一个,你在某种程度上必须亲自检查可能的着陆点并从那里开始。

我在这段代码中没有找到。

我的反汇编,看看它与你的比较:

0200 : 0x6A00  ld v10,0x00
0202 : 0x6B04  ld v11,0x04
0204 : 0x6C01  ld v12,0x01
0206 : 0x6D00  ld v13,0x00
0208 : 0x6E02  ld v14,0x02
020A : 0x2326  call 326
020C : 0x2320  call 320
020E : 0x6030  ld v0,0x30
0210 : 0x6101  ld v1,0x01
0212 : 0xF015  ld dt,v0
0214 : 0xF007  ld v0,dt
0216 : 0xF118  ld st,v1
0218 : 0x3000  se v0,0x00
021A : 0x1214  jp 214
021C : 0x2242  call 242
021E : 0x2320  call 320
0220 : 0x7D01  add v13,0x01
0222 : 0x2320  call 320
0224 : 0x6008  ld v0,0x08
0226 : 0xE0A1  sknp v0
0228 : 0x230A  call 30A
022A : 0x4A00  sne v10,0x00
022C : 0x123E  jp 23E
022E : 0xA362  ld i,362
0230 : 0xD891  drw v8,v9,1
0232 : 0x7901  add v9,0x01
0234 : 0xD891  drw v8,v9,1
0236 : 0x4F01  sne v15,0x01
0238 : 0x12F4  jp 2F4
023A : 0x4918  sne v9,0x18
023C : 0x12E4  jp 2E4
023E : 0x22B2  call 2B2
0240 : 0x121E  jp 21E
0242 : 0x4C01  sne v12,0x01
0244 : 0x226C  call 26C
0246 : 0x4C02  sne v12,0x02
0248 : 0x227A  call 27A
024A : 0x4C03  sne v12,0x03
024C : 0x2288  call 288
024E : 0x4C04  sne v12,0x04
0250 : 0x2296  call 296
0252 : 0x4C05  sne v12,0x05
0254 : 0x22A4  call 2A4
0256 : 0xA359  ld i,359
0258 : 0xD672  drw v6,v7,2
025A : 0x4400  sne v4,0x00
025C : 0x00EE  ret
025E : 0xA357  ld i,357
0260 : 0xD452  drw v4,v5,2
0262 : 0x4200  sne v2,0x00
0264 : 0x00EE  ret
0266 : 0xA35B  ld i,35B
0268 : 0xD232  drw v2,v3,2
026A : 0x00EE  ret
026C : 0x6628  ld v6,0x28
026E : 0x6709  ld v7,0x09
0270 : 0x6400  ld v4,0x00
0272 : 0x6500  ld v5,0x00
0274 : 0x6200  ld v2,0x00
0276 : 0x6300  ld v3,0x00
0278 : 0x00EE  ret
027A : 0x6628  ld v6,0x28
027C : 0x670E  ld v7,0x0E
027E : 0x6428  ld v4,0x28
0280 : 0x6514  ld v5,0x14
0282 : 0x6200  ld v2,0x00
0284 : 0x6300  ld v3,0x00
0286 : 0x00EE  ret
0288 : 0x6628  ld v6,0x28
028A : 0x6707  ld v7,0x07
028C : 0x6428  ld v4,0x28
028E : 0x650C  ld v5,0x0C
0290 : 0x6216  ld v2,0x16
0292 : 0x6311  ld v3,0x11
0294 : 0x00EE  ret
0296 : 0x6628  ld v6,0x28
0298 : 0x6707  ld v7,0x07
029A : 0x6428  ld v4,0x28
029C : 0x650E  ld v5,0x0E
029E : 0x6216  ld v2,0x16
02A0 : 0x6314  ld v3,0x14
02A2 : 0x00EE  ret
02A4 : 0x6628  ld v6,0x28
02A6 : 0x6705  ld v7,0x05
02A8 : 0x6428  ld v4,0x28
02AA : 0x6510  ld v5,0x10
02AC : 0x6216  ld v2,0x16
02AE : 0x630B  ld v3,0x0B
02B0 : 0x00EE  ret
02B2 : 0xA359  ld i,359
02B4 : 0xD672  drw v6,v7,2
02B6 : 0x76FE  add v6,0xFE
02B8 : 0xD672  drw v6,v7,2
02BA : 0x4400  sne v4,0x00
02BC : 0x00EE  ret
02BE : 0xA357  ld i,357
02C0 : 0xD452  drw v4,v5,2
02C2 : 0x7402  add v4,0x02
02C4 : 0x4444  sne v4,0x44
02C6 : 0x74C0  add v4,0xC0
02C8 : 0xD452  drw v4,v5,2
02CA : 0x4200  sne v2,0x00
02CC : 0x00EE  ret
02CE : 0xA35B  ld i,35B
02D0 : 0xD232  drw v2,v3,2
02D2 : 0x7202  add v2,0x02
02D4 : 0x4C04  sne v12,0x04
02D6 : 0x7202  add v2,0x02
02D8 : 0x4C05  sne v12,0x05
02DA : 0x7202  add v2,0x02
02DC : 0x4244  sne v2,0x44
02DE : 0x72C0  add v2,0xC0
02E0 : 0xD232  drw v2,v3,2
02E2 : 0x00EE  ret
02E4 : 0x7C01  add v12,0x01
02E6 : 0x6D00  ld v13,0x00
02E8 : 0x6E02  ld v14,0x02
02EA : 0x00E0  cls
02EC : 0x4C06  sne v12,0x06
02EE : 0x6C01  ld v12,0x01
02F0 : 0x6A00  ld v10,0x00
02F2 : 0x120A  jp 20A
02F4 : 0x6006  ld v0,0x06
02F6 : 0xF018  ld st,v0
02F8 : 0x7BFF  add v11,0xFF
02FA : 0x4B00  sne v11,0x00
02FC : 0x1308  jp 308
02FE : 0x6D00  ld v13,0x00
0300 : 0x6E02  ld v14,0x02
0302 : 0x00E0  cls
0304 : 0x6A00  ld v10,0x00
0306 : 0x120A  jp 20A
0308 : 0x1308  jp 308
030A : 0x4A01  sne v10,0x01
030C : 0x00EE  ret
030E : 0x6002  ld v0,0x02
0310 : 0xF018  ld st,v0
0312 : 0x6A01  ld v10,0x01
0314 : 0x88D0  ld v8,v13
0316 : 0x7801  add v8,0x01
0318 : 0x89E0  ld v9,v14
031A : 0x7901  add v9,0x01
031C : 0xD891  drw v8,v9,1
031E : 0x00EE  ret
0320 : 0xA354  ld i,354
0322 : 0xDDE2  drw v13,v14,2
0324 : 0x00EE  ret
0326 : 0x6419  ld v4,0x19
0328 : 0x6300  ld v3,0x00
032A : 0xA356  ld i,356
032C : 0xD341  drw v3,v4,1
032E : 0x7308  add v3,0x08
0330 : 0x3340  se v3,0x40
0332 : 0x132C  jp 32C
0334 : 0x631E  ld v3,0x1E
0336 : 0x641B  ld v4,0x1B
0338 : 0xFC29  ld f,v12
033A : 0xD345  drw v3,v4,5
033C : 0x4B04  sne v11,0x04
033E : 0xA35F  ld i,35F
0340 : 0x4B03  sne v11,0x03
0342 : 0xA360  ld i,360
0344 : 0x4B02  sne v11,0x02
0346 : 0xA361  ld i,361
0348 : 0x4B01  sne v11,0x01
034A : 0xA362  ld i,362
034C : 0x6301  ld v3,0x01
034E : 0x7402  add v4,0x02
0350 : 0xD341  drw v3,v4,1
0352 : 0x00EE  ret

有许多指令在0x354之后和之后用该地址加载i,所以我假设您发现程序使用的数据,而不是指令。最大的一个是0x362。你的hexdump描述的数据中最大的地址是0x363,但它是零和/或有意填充,或者必须查看关于i的使用的代码。

022E : 0xA362  ld i,362
0256 : 0xA359  ld i,359
025E : 0xA357  ld i,357
0266 : 0xA35B  ld i,35B
02B2 : 0xA359  ld i,359
02BE : 0xA357  ld i,357
02CE : 0xA35B  ld i,35B
0320 : 0xA354  ld i,354
032A : 0xA356  ld i,356
033E : 0xA35F  ld i,35F
0342 : 0xA360  ld i,360
0346 : 0xA361  ld i,361
034A : 0xA362  ld i,362