assembly 试着理解一些65 c816汇编代码-这种指令顺序的目的是什么?

q7solyqu  于 2023-03-02  发布在  其他
关注(0)|答案(3)|浏览(146)

我是汇编语言的新手,我想把这段代码拼凑起来,这是我使用的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的一页,如果有帮助的话。

我不能理解段落的开头,“位通常用在条件分支指令之前:“,虽然它似乎相关...

js4nwp54

js4nwp541#

回答关于这些线的一个问题

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

为什么TAX后面跟着TXA
这是因为第6行的分支,如果执行,将从第10行开始执行。
显示的TAX与 * 上一个 * TXA(不是下一个)匹配,如下所示

07: $A4918D 8A          TXA
08: $A4918E 49 FF FF    EOR #$FFFF
09: $A49191 AA          TAX

代码中的一些空格或标签会使这种“措辞”更清楚,尽管分支确实给予了目的地地址。
关于Z标志的问题1-3:如果正在测试的结果是0,则您说Z标志是set是正确的。
1.既然Z=0,那么我认为它将分支(到地址$05处的指令)是正确的吗?
是的,但是$05不是地址,它是一个有符号的位移(从 * 应该 * 跟随的指令开始,因为PC程序计数器(又名IP指令指针)在做出决定时已经前进)。

bvjveswy

bvjveswy2#

有人能帮我理解接下来的几条指令吗?特别是,先执行TAX再执行TXA有什么意义?这不就是交换值然后取消交换值吗?

  • 这根本不是一个 * 交换 *!这些Txx指令将一个值从一个寄存器复制到另一个寄存器,使两个寄存器彼此相等。
  • 第6行的BNE指令导致两条不同的执行路径最终不得不重新走到一起,程序员本可以使用BRA无条件跳转来达到这个效果,但最终没有这样做,因为他们更喜欢代码大小而不是执行速度:

BNE指令要么在第一个路径中失败,要么跳转到第二个路径。在第一个路径的末尾,BRA跳转到汇合点。此解决方案需要多1个字节(3个字节而不是2个字节),但第一个路径的执行周期少1个周期(3个周期而不是4个周期,除非出现页边界交叉,否则也将是4个周期):

06: $A4918B D0 06       BNE $06    [$9193]
    *** first path
07: $A4918D 8A          TXA
08: $A4918E 49 FF FF    EOR #$FFFF
09: $A49191 .. 01       BRA $01    [$9194]
    *** second path
10: $A49193 8A          TXA
    *** come together point
11: $A49194 18          CLC

TAX指令用于避免使用开销更大的分支指令。它设置X寄存器,以便代码可以在第二个路径的TXA指令中失败。此解决方案需要少1个字节(2个字节而不是3个字节),但第一个路径多执行1个周期(4个周期而不是3个周期):

06: $A4918B D0 05       BNE $05    [$9192]
    *** first path
07: $A4918D 8A          TXA
08: $A4918E 49 FF FF    EOR #$FFFF
09: $A49191 AA          TAX
    *** second path
10: $A49192 8A          TXA
    *** come together point
11: $A49193 18          CLC

相同的随机数输入到累加器中......但这里保证是相同的。

为什么这段代码如此复杂?

假设来自05E5的随机数保持不变,并且BIT不改变其任何操作数,并且我们测试的位是AND剩余的位中的一位,则我们甚至可以在不接触X的情况下编写以下代码:

01: $A4917E AD E5 05    LDA $05E5  [$A4:05E5]
02: $A49181 29 3F 00    AND #$003F
05: $A49184 89 02 00    BIT #$0002
06: $A49187 D0 03       BNE $03    [$918C]
08: $A49189 49 FF FF    EOR #$FFFF
11: $A4918C 18          CLC
8fq7wneg

8fq7wneg3#

关于这个问题和Weather Vane的答案,我认为根据RNG值(0x 05 E5),您可以猜到为什么要这样做:

  • 如果值为0x 3F(此处的重要位用于演示)
01: $A4917E AD E5 05    LDA $05E5  [$A4:05E5] ;  A=0x3F, X=?
02: $A49181 29 3F 00    AND #$003F ; A=0x3F, X=?, Y=?, flags: Z=0
03: $A49184 AA          TAX ; A=0x3F X=0x3F
04: $A49185 AD E5 05    LDA $05E5  [$A4:05E5] ; A=0x3F, X=0x3F
05: $A49188 89 02 00    BIT #$0002; A=0x3F, X=0x3F, flags: Z=0
06: $A4918B D0 05       BNE $05    [$9192] ; Branch !
10: $A49192 8A          TXA A=0x3F, X=0x3F
11: $A49193 18          CLC ; Continue code
  • 如果值V RNG & 0x3F == 0 && RNG & 0x2 == 0,如0x 40:
01: $A4917E AD E5 05    LDA $05E5  [$A4:05E5] ; A=0x40
02: $A49181 29 3F 00    AND #$003F ; Z=0
03: $A49184 AA          TAX ; A=0x40, X=0x40
04: $A49185 AD E5 05    LDA $05E5  [$A4:05E5] ; A=0x40
05: $A49188 89 02 00    BIT #$0002 ; A=0x40 Z=1
06: $A4918B D0 05       BNE $05    [$9192] ; No branching here
07: $A4918D 8A          TXA ; A=0x40, X=0x40
08: $A4918E 49 FF FF    EOR #$FFFF ; A=0xBF, X=0x40 , assuming 8 bits mode but I'll talk about that later
09: $A49191 AA          TAX ; A=0xBF, X=0xBF
10: $A49192 8A          TXA ; A=0xBF, X=0xBF
11: $A49193 18          CLC ; c=0

当看到这个,是的,问题是:为什么开发人员没有交换并执行TAX/TXA?
我对第一个问题最好的猜测是和风向标一样,是因为分支。我认为它确实有另一个用途:清除标记。
直到这里,我们才谈到8/16位模式(m标志)或其他标志。我认为这就是CLC的要点所在,也就是清除标志。
使用传输指令时,根据您复制的m标志(确定存储器宽度模式),您可以清除一些标志。
在我的源代码http://6502.org/tutorials/65c816opcodes.html#6.10.1中,他们给予了这个例子:
示例:如果累加器为$1234,X寄存器为$ABCD,m标志为1,则在TXA之后:

  • 累计金额为$12CD
  • n标志将为1(因为实际上只传输了$CD)
  • Z旗标将为0

我假设这只是将标志重置为已知状态。
关于你最后一个问题:
我不能理解以“BIT通常紧接在条件分支指令之前使用:“开头的段落,尽管它看起来很相关...
有可能在不改变值的情况下执行按位检查,这让你可以执行额外的指令。否则,你需要像第4行那样再次执行LDA。这就是我将如何使用它。

相关问题