这只是一个有趣的问题。我正在开发 SC61860 CPU,它是 1987 年生产的 Sharp PC-1360 掌上电脑(也用于 PC-1401 和 1403)的 8 位 CPU。它的指令集实际上并不包含 XOR。它确实有 AND、OR、比较、减法和加法指令。
我尝试了 AND 和 ORing 值的一些变体来获得 XOR 产生的结果,但没有运气。我本来希望避免比较,但看起来我别无选择。
有兴趣的话可以查看指令集。
顺便说一句,这款 CPU 非常适合学习汇编。漂亮、简单,而且足够慢(768kHz),机器语言明显比使用 BASIC 内置的计算机快;)我通常用 C/C++/Java 编程。大会让人呼吸新鲜空气。
从布尔代数我们知道:
A XOR B = (NOT(A) AND B) OR (A AND NOT(B))
更新: 感谢@Brett Hale,@slebetman,因为CPU令人惊讶地不支持
NOT
指令,它可以通过算术求反和减法来模拟,假设2的补码负数表示):
NOT(A) = (-1) - A
或者在不同负数表示的情况下,
-1
可以替换为相应的存储类型最大值(即8位寄存器为255或16位寄存器为65565)。
光滑!谢谢,效果非常好。
9 XOR 11 = 2
a XOR b = (NOT(a) AND b) OR (a AND NOT(b))
= ((255-9) and 11) or (9 and (255-11))
= (246 and 11) or (9 and 244)
= 2 or 0
= 2
这是使用8位寄存器的程序。要一起使用 2 个寄存器(例如 AND 运算),您必须将 P 指向第二个寄存器。然后你可以[P]和A -> P:
##############################################################################
## xor.asm
## perform a logical XOR operation on numA and numB and store to numC
## numC = numA XOR numB
##############################################################################
$JR
org &C030
jp start
I_REG equ 0 # Internal Registers
J_REG equ 1
A_REG equ 2
B_REG equ 3
XL_REG equ 4
XH_REG equ 5
YL_REG equ 6
YH_REG equ 7
K_REG equ 8
L_REG equ 9
M_REG equ 10
N_REG equ 11
PORTC equ 95
numA: db 9
numB: db 11
numC: db 0
# EXAB A <-> B
# SBM [P] - A -> [P]
# ANMA [P] and A -> [P]
# ORMA [P] or A -> [P]
# PUSH push A onto the stack
# POP pop A from the stack
start: lp B_REG # point P to the B register
lidp numA # (not a & b)
ldd # A = numA
lib 255
sbm # B = 255 - numA
lidp numB # A = numB
ldd
anma # B = 255-numA & numB
exab # swap A and B to store result on the stack
push # push A (result) to the stack
lidp numB # (a & not b)
ldd
lib 255
sbm # B = 255 - numB, B = not b
lidp numA
ldd
anma # B = numA & (255 - numB)
pop # grab the first result
orma # B = final result
lidp numC
exab
std # numC = numA XOR numB
end: rtn
按位或也可以用以下运算代替
a ^ b = (a + b) - 2*(a & b)
如此 stackoverflow answer 中对类似问题的解释。
这里是一个实现的代码示例(未经测试)。
org &C030
jp start
start: lp B_REG # point P to regB
lidp numA # load A
ldd # regA=A
push
exab # regB=A regA=?
lidl <numB # load B
ldd # regB=A regA=B
anma # regB=A&B regA=B
ldm # regB=A&B regA=A&B
adm # regB=2*A&B regA=A&B
pop # regB=2*A&B regA=A
exab # regB=A regA=2*A&B
push
ldd # regB=A regA=B
adm # regB=A+B regA=B
pop # regB=A+B regA==2*A&B
sbm # regB=A+B-2*A&B regA==2*A&B
exab # regB=2*A&B regA==A+B-2*(A&B)
lidl <numC # save result C
std
end: rtn