如何解决6502 汇编:16 位减法中的进位结果
我恢复了一个旧的 6502 模拟器,我多年前做了一些新功能。在测试过程中,我发现了一些错误,肯定是由于我的实现错误。
我必须循环执行 16 位减法,直到结果为负:很简单,不是吗?下面是一个例子:
V1 equ $90
V2 equ $01
Label:
sec
lda V2
sbc #2
sta V2
lda V1
sbc #10
sta V1
"Branch" to Label if result is >0,otherwise exit
rts
现在,问题是确定选择哪个分支或找到不同的解决方案。
如果 V2 减法清除进位,则 BCS
无效。
如果 V1 为“负”(>$80),则 BPL
无效。
这应该很容易,但是...
编辑
我没有在答案中找到真正的解决方案。
让我尝试遵循逻辑,首先使用代码中的原始值。
- 进位由
SEC
设置
- 拳头子 (1-2) 清除进位。
V1
= $FF - 第二个子项($90-$0A-1(非借))结果为
V2
=$85 - 进位清零;结果 ($85FF) 仍然是负数)
我无法使用BCS
(跳转到标签)或BMI
测试结果,因为V2
为负值。
那么?
使用不同的集合,即 V1
=$1 和 V2
=$0A 我将得到
有什么建议吗?
解决方法
通常,这样的序列(我稍微修改了您问题中的代码以使其更加独立)
V1 equ $91
V2 equ $90
lda #00
sta V2
lda #20
sta V1
Label:
sec
lda V2
sbc #2
sta V2
lda V1
sbc #10
sta V1
将按预期工作。使用代码中使用的值,在第一次减法后将清除进位,并在第二次减法后再次设置。如果不是,那么最可能的原因是模拟器中的错误。我已经在在线 6502 仿真中运行了它,并且在到达最终 sta V1
时设置了进位。我也在 visual6502 中运行它,这是跟踪输出:
cycle ab db rw Fetch pc a x y s p
0 0000 a9 1 LDA # 0000 aa 00 00 fd nv‑BdIZc
0 0000 a9 1 LDA # 0000 aa 00 00 fd nv‑BdIZc
2 0002 85 1 STA zp 0002 00 00 00 fd nv‑BdIZc
4 0090 00 0 0004 00 00 00 fd nv‑BdIZc
5 0004 a9 1 LDA # 0004 00 00 00 fd nv‑BdIZc
7 0006 85 1 STA zp 0006 14 00 00 fd nv‑BdIzc
9 0091 14 0 0008 14 00 00 fd nv‑BdIzc
10 0008 38 1 SEC 0008 14 00 00 fd nv‑BdIzc
12 0009 a5 1 LDA zp 0009 14 00 00 fd nv‑BdIzC
15 000b e9 1 SBC # 000b 00 00 00 fd nv‑BdIZC
17 000d 85 1 STA zp 000d 00 00 00 fd nv‑BdIZC
19 0090 fe 0 000f fe 00 00 fd Nv‑BdIzc
20 000f a5 1 LDA zp 000f fe 00 00 fd Nv‑BdIzc
23 0011 e9 1 SBC # 0011 14 00 00 fd nv‑BdIzc
25 0013 85 1 STA zp 0013 14 00 00 fd nv‑BdIzc
27 0091 09 0 0015 09 00 00 fd nv‑BdIzC
正如你在最后看到的,进位被设置(用大写 C 表示)。
顺便说一下,您的代码还有一个问题。如果您有 2000(十进制),那么要将其加载到两个位置,您需要先将其转换为十六进制,然后再将其切成两个字节。如果您将 0 加载到零页位置并将 20 位小数加载到其后继位置,则您实际上加载了 20 * 256 = 5120。2000 的十六进制为 $07d0
。
遵循对问题的最新编辑。这是一段简化的代码,它通过进位清除从 $0a
中减去 $90
。
clc
lda #$90
sbc #$0a
这是 Visual 6502 跟踪
cycle ab db rw Fetch pc a x y s p
0 0000 18 1 CLC 0000 aa 00 00 fd nv‑BdIZc
0 0000 18 1 CLC 0000 aa 00 00 fd nv‑BdIZc
2 0001 a9 1 LDA # 0001 aa 00 00 fd nv‑BdIZc
4 0003 e9 1 SBC # 0003 90 00 00 fd Nv‑BdIzc
6 0005 ea 1 NOP 0005 90 00 00 fd Nv‑BdIzc
8 0006 ea 1 NOP 0006 85 00 00 fd Nv‑BdIzC
如果您的模拟器在这种情况下未设置进位,则您的模拟器存在错误。
,循环执行 16 位减法,直到结果为负
如果结果 >0,则“分支”到标签,
您是否发现这些描述相互矛盾?
第一个在0继续,第二个在0停止。
只有你能决定哪一个是正确的!
来自评论:
此代码是 Bin 到 Ascii 转换的一部分,由十次幂减法制成。 bin 值可能大于 8000 美元,因此它是“负数”,但这并不重要。在第一次迭代中,我每个循环减 10000,直到结果“低于 0”,然后我恢复以前的值并继续余数。问题是如何检测帖子中所说的“低于 0”条件
Do ... Loop While GE 0
下一个示例从存储在零页地址 $90 的无符号字中减去 10000 ($2710)。低字节为 90 美元,高字节为 91 美元(小端)。
Lo equ $90 ; The 16-bit bin is stored at zero page address $90
Hi equ $91
sec ; Because SBC subtracts the complement of C
ldx #-1
Label inx
lda Lo ; Load from a zero page address
sbc #$10 ; Subtracting immediate $10
sta Lo ; Store to a zero page address
lda Hi ; Load from a zero page address
sbc #$27 ; Subtracting immediate $27
sta Hi ; Store to a zero page address
bcs Label ; Result GE 0 (greater or equal)
rts
X
寄存器现在包含原始数字中 10000 的次数。
Do ... Loop While GT 0
您可以添加 ora
指令以查看生成的单词是否已变为否定。然后根据 Z
中的 ora
和(最后一个)C
中的 sbc
进行分支。
Lo equ $90 ; The 16-bit bin is stored at zero page address $90
Hi equ $91
sec ; Because SBC subtracts the complement of C
Label lda Lo ; Load from a zero page address
sbc #$10 ; Subtracting immediate $10
sta Lo ; Store to a zero page address
lda Hi ; Load from a zero page address
sbc #$27 ; Subtracting immediate $27
sta Hi ; Store to a zero page address
ora Lo ; To define Z for the whole word
beq Done ; Result EQ 0 (equal)
bcs Label ; Result GT 0 (greater)
Done rts
我的 6502 手册说:“最重要的是,请记住比较是通过 BCS
和 BCC
(不是 BPL
或 BMI
)完成的.
我找到了一个解决方案,既麻烦又不优雅,但有效:
LDY #0 _B2D161 INY PHA TXA SEC SBC #$10 TAX PLA ;---------------------- BCS _BD1 ;normal flow SEC ;set carry for the next sub SBC #$28 ;the carry=0 would have incremented the minuend BCS _B2D161 ;loop again BCC _BD11 ;exit and restore the previous value ;----------------------- _BD1 SBC #$27 ;normal jump comes here BCS _B2D161 _BD11 PHA TXA CLC ADC #$10 TAX PLA ADC #$27 DEY STY _L10K ... continue with next section
隔离部分显示了应用的变体:如果第一个 sub 清除进位,则通过减去增加 1 的值(#28 而不是 #27)并恢复下一个 sub 的进位来“模拟”。
这样我就可以再次依靠 Carry 来决定分支的位置。
我要感谢 Sep Roland 提供的建议代码(与我最初使用的代码相同),但不幸的是它没有完成这项工作。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。