我想将16位数除以2。我对这个问题的解决方案如下:
lda $17 ;set high byte
ldx $32 ;set low byte
divide:
PHA ;push A to stack
TXA ;X > A
LSR ;divide low byte by 2
TAX ;A > X
PLA ;pull A from stack
LSR ;divide high byte by 2
BCC + ;C=0, skip
PHA ;while C=1
TXA ;add $80 to the lsb
ADC #$80
TAX
PLA
+
+printDecimal $0400+120
所有PHA/PLA
技巧都是因为我的printDecimal
宏从A读取MSB而从X读取LSB。
当我在网上检查替代方案时,我发现了4个指令替代我的简单划分例程。但我不明白。
div2:
LDA counter_hi ;Load the MSB
ASL ;Copy the sign bit into C
ROR counter_hi ;And back into the MSB
ROR counter_lo ;Rotate the LSB as normal
LDA counter_hi
LDX counter_lo
+printDecimal $0400+40
这是如何运作的?
答案 0 :(得分:9)
除以2(无符号数)与将所有位向右移位一位相同。例如,数字100以二进制表示:
01100100
将所有位置向右移动
00110010
这是50的二进制表示。
ROR命令将所有位置向右移动。字节的新MSB将等于进位标志的旧值,而进位标志的新值将等于字节的旧LSB。
如果16位数字是无符号的,则将数字的高字节和低字节向右移动就足够了:
LSR counter_hi
ROR counter_lo
LSR和ROR都将它们的参数向右移动,但LSR使counter_hi的MSB为0并将counter_hi的LSB移入进位标志,而ROR使counter_lo的MSB等于counter_hi的(旧)LSB。
如果数字已签名,则需要存储符号位并确保新数字的符号位相同。这就是你引用的代码的前两个命令。请注意,这是有效的,因为号码存储在two's complement。
答案 1 :(得分:4)
它的作用就像代码中的注释所说;)
在6502中,遗憾的是没有算术右移,这将使符号位保持不变。所以需要模仿。为此,首先从高位字中提取符号位。请注意,这是使用累加器完成的,因此原始值不会更改。 ROR
用在高位字上,该高位字旋转了使用进位标志扩展操作数所产生的9位值。因此,当前在CF中的符号位将旋转到MSB中,其余位将向右移位,LSB将在CF中结束。这完成了签署的部门。低字上的第二个ROR
只是将LSB从高字传送到低字的MSB,并将其余的位移位。
答案 2 :(得分:2)
(显然你知道向右移动N位除以2 ^ N,同样左移也乘以2)
ASL
将hi字节counter_hi
的最高有效位(MSB)放入进位寄存器(以便在我们移位时记住符号 - 除以正整数(2)赢得' t改变我们16位数的原始符号。)
ROR counter_hi
将counter_hi
向右移1位。重要的是:
进位转入第7位,原位0转入进位。
有两个目的 - 保留原始符号,并且还将counter_hi
的LSB转移到第二个ROR
ROR counter_lo
对低字节做同样的事情。 counter_hi
的LSB现在转移到counter_lo
答案 3 :(得分:1)
如果我没记错的话,ROR和ROL会按照规定的方向移位,最低有效位(对于ROR)和最高有效位(对于ROL)会移入进位标志。
自从我查看任何6502以来已经过去了大约25年,但对我来说并不是很清楚,但这就是我认为它会立即完成的方式。
编辑:此外,在ROR和ROL中,进位标志的现有状态被传送到累加器的最低/最高有效位。
答案 4 :(得分:1)
不记得指令的所有寻址模式,但也许这样就可以了:
LSR
PHA
TXA
ROR
TAX
PLA