如何在没有 XOR 指令的 CPU 上进行 XOR

问题描述 投票:0回答:3

这只是一个有趣的问题。我正在开发 SC61860 CPU,它是 1987 年生产的 Sharp PC-1360 掌上电脑(也用于 PC-1401 和 1403)的 8 位 CPU。它的指令集实际上并不包含 XOR。它确实有 AND、OR、比较、减法和加法指令。

我尝试了 AND 和 ORing 值的一些变体来获得 XOR 产生的结果,但没有运气。我本来希望避免比较,但看起来我别无选择。

有兴趣的话可以查看指令集

顺便说一句,这款 CPU 非常适合学习汇编。漂亮、简单,而且足够慢(768kHz),机器语言明显比使用 BASIC 内置的计算机快;)我通常用 C/C++/Java 编程。大会让人呼吸新鲜空气。

assembly bit-manipulation bitwise-operators bitwise-xor
3个回答
11
投票

从布尔代数我们知道:

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)。


0
投票

光滑!谢谢,效果非常好。

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

0
投票

按位或也可以用以下运算代替

 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                                                                       
© www.soinside.com 2019 - 2024. All rights reserved.