我是汇编语言的新手,我想把这段代码拼凑起来,这是我使用的Super NES 65c816 reference。
01: $A4917E AD E5 05 LDA $05E5 [$A4:05E5]
02: $A49181 29 3F 00 AND #$003F
03: $A49184 AA TAX
04: $A49185 AD E5 05 LDA $05E5 [$A4:05E5]
05: $A49188 89 02 00 BIT #$0002
06: $A4918B D0 05 BNE $05 [$9192]
07: $A4918D 8A TXA
08: $A4918E 49 FF FF EOR #$FFFF
09: $A49191 AA TAX
10: $A49192 8A TXA
11: $A49193 18 CLC
12: $A49194 6D 7A 0F ADC $0F7A [$A4:0F7A]
13: $A49197 85 12 STA $12 [$00:0012]
14: $A49199 AD E5 05 LDA $05E5 [$A4:05E5]
15: $A4919C 29 00 1F AND #$1F00
16: $A4919F EB XBA
17: $A491A0 85 14 STA $14 [$00:0014]
我已经知道$05E5是游戏的随机数生成器(RNG)的存储位置,它是一个16位的值,我想弄清楚的是游戏试图用这个随机数做什么样的数学运算。
对于初学者来说,这里有一个更简单的例子:
$86AE1C AD E5 05 LDA $05E5 [$86:05E5]
$86AE1F 29 01 00 AND #$0001
$86AE22 F0 05 BEQ $05 [$AE29]
很明显,这里只是用掷硬币的随机数--最高熵位是0或1--来决定是否分支。
回到最初的例子,让我说什么(我认为)我理解,在片段:
01: $A4917E AD E5 05 LDA $05E5 [$A4:05E5]
02: $A49181 29 3F 00 AND #$003F
03: $A49184 AA TAX
这是将随机数加载到累加器中,例如11010101001100010
,并将其与0000000000111111
进行AND运算,在累加器中生成0000000000100010
,然后将其传输到寄存器X。
04: $A49185 AD E5 05 LDA $05E5 [$A4:05E5]
接下来,它将相同的随机数加载到累加器中--我猜是因为在AND操作中丢失了它吧?(随机数是在别处生成的,大约每1/60秒执行一次。但在这里它肯定是相同的。)
05: $A49188 89 02 00 BIT #$0002
06: $A4918B D0 05 BNE $05 [$9192]
这就是我觉得有点模糊的地方。我在网上读了很多资料(虽然不是针对65816的),说BIT类似于AND,但没有改变任何一个操作数。但似乎有一些细微差别与标志有关。
1.继续我的例子,我认为累加器值11010101001100010
上的BIT #$0002
应该是1,因为第二低的位是1,这是正确的吗?
1.我认为作为位测试的结果,z 标志的值将被设置为0,与前面的结果正好相反,这种看法是否正确?
1.既然Z=0,那么我相信它 * 将 * 然后分支(到地址$05处的指令),这是正确的吗?
好吧,如果我已经把这些基本原理记下来了,那么这些就是我真实的的问题:
***为什么开发人员(他们在那个年代优化了 * 所有东西 *)不把01-03行和04-06行交换一下呢?**也就是说,如果你有机会跳到某个完全不同的代码段,为什么不先测试并执行跳转,只有在 * 没有 * 分支的情况下,才执行AND操作呢?(等等,寄存器X有没有可能在代码跳转到的任何地方使用?)
- 有人能帮我理解接下来的几条指令吗?特别是,先执行TAX再执行TXA有什么意义?这不就是交换值然后取消交换值吗?
抱歉,这是许多问题在一个,但希望它是好的,因为我指的是同一套指示。提前感谢任何帮助。
这是我关于65816的教科书中关于BIT的一页,如果有帮助的话。
我不能理解段落的开头,“位通常用在条件分支指令之前:“,虽然它似乎相关...
3条答案
按热度按时间js4nwp541#
回答关于这些线的一个问题
为什么
TAX
后面跟着TXA
?这是因为第6行的分支,如果执行,将从第10行开始执行。
显示的
TAX
与 * 上一个 *TXA
(不是下一个)匹配,如下所示代码中的一些空格或标签会使这种“措辞”更清楚,尽管分支确实给予了目的地地址。
关于
Z
标志的问题1-3:如果正在测试的结果是0
,则您说Z
标志是set是正确的。1.既然Z=0,那么我认为它将分支(到地址$05处的指令)是正确的吗?
是的,但是
$05
不是地址,它是一个有符号的位移(从 * 应该 * 跟随的指令开始,因为PC
程序计数器(又名IP
指令指针)在做出决定时已经前进)。bvjveswy2#
有人能帮我理解接下来的几条指令吗?特别是,先执行TAX再执行TXA有什么意义?这不就是交换值然后取消交换值吗?
Txx
指令将一个值从一个寄存器复制到另一个寄存器,使两个寄存器彼此相等。BNE
指令导致两条不同的执行路径最终不得不重新走到一起,程序员本可以使用BRA
无条件跳转来达到这个效果,但最终没有这样做,因为他们更喜欢代码大小而不是执行速度:BNE
指令要么在第一个路径中失败,要么跳转到第二个路径。在第一个路径的末尾,BRA
跳转到汇合点。此解决方案需要多1个字节(3个字节而不是2个字节),但第一个路径的执行周期少1个周期(3个周期而不是4个周期,除非出现页边界交叉,否则也将是4个周期):TAX
指令用于避免使用开销更大的分支指令。它设置X寄存器,以便代码可以在第二个路径的TXA
指令中失败。此解决方案需要少1个字节(2个字节而不是3个字节),但第一个路径多执行1个周期(4个周期而不是3个周期):相同的随机数输入到累加器中......但这里保证是相同的。
为什么这段代码如此复杂?
假设来自05E5的随机数保持不变,并且
BIT
不改变其任何操作数,并且我们测试的位是AND
剩余的位中的一位,则我们甚至可以在不接触X的情况下编写以下代码:8fq7wneg3#
关于这个问题和Weather Vane的答案,我认为根据RNG值(0x 05 E5),您可以猜到为什么要这样做:
RNG & 0x3F == 0 && RNG & 0x2 == 0
,如0x 40:当看到这个,是的,问题是:为什么开发人员没有交换并执行TAX/TXA?
我对第一个问题最好的猜测是和风向标一样,是因为分支。我认为它确实有另一个用途:清除标记。
直到这里,我们才谈到8/16位模式(m标志)或其他标志。我认为这就是CLC的要点所在,也就是清除标志。
使用传输指令时,根据您复制的m标志(确定存储器宽度模式),您可以清除一些标志。
在我的源代码http://6502.org/tutorials/65c816opcodes.html#6.10.1中,他们给予了这个例子:
示例:如果累加器为$1234,X寄存器为$ABCD,m标志为1,则在TXA之后:
我假设这只是将标志重置为已知状态。
关于你最后一个问题:
我不能理解以“BIT通常紧接在条件分支指令之前使用:“开头的段落,尽管它看起来很相关...
有可能在不改变值的情况下执行按位检查,这让你可以执行额外的指令。否则,你需要像第4行那样再次执行LDA。这就是我将如何使用它。