【问题标题】:Bitwise operations in subleqsubleq 中的按位运算
【发布时间】:2015-12-06 17:02:59
【问题描述】:

许多页面展示了如何从单个 subleq 指令中合成更复杂的算术和逻辑运算。我还没有找到任何讨论按位运算实现的页面,例如 NAND、XOR ... 等

就我个人而言,我还没有找到不使用循环来实现任何这些操作(NOT 除外)的方法。有没有一种简洁的方法?

【问题讨论】:

  • Hacker's Delight 不是真正的解决方案,但可以从中获得灵感,它进一步引用了实现按位运算的各种方法。还有一篇论文 Bit Copying 使用了 Oleg Mazonka 的循环,他实现了 C 的 HSQ 子集。

标签: assembly bitwise-operators cpu-architecture


【解决方案1】:

我写了一个小演示程序。我确实使用循环来实现一些运算符。

"""
This program demonstrates that you can write the bit operators AND, OR and XOR
in terms of the subtract and branch if equal or lower (subleq) operator.
https://en.wikipedia.org/wiki/One_instruction_set_computer

C.M. Punter 2016
"""
import random


def my_sub(a: int, b: int) -> int:
    return a - b


def my_leq(a: int, b: int) -> bool:
    return a <= b


# now we write all other functions in terms of the above two functions

def my_add(a: int, b: int) -> int:
    return my_sub(a, my_sub(0, b))


def my_mul(a: int, b: int) -> int:

    c = 0

    while my_leq(1, b):
        c = my_add(c, a)
        b = my_sub(b, 1)

    return c


def my_div(a: int, b: int) -> int:

    c = 0

    while my_leq(b, a):
        c = my_add(c, 1)
        a = my_sub(a, b)

    return c


def my_mod(a: int, b: int) -> int:

    while my_leq(b, a):
        a = my_sub(a, b)

    return a


def my_and(a: int, b: int) -> int:

    c = 0
    d = 1

    while my_leq(1, my_mul(a, b)):

        # we look at the first bit of a and b by checking if the number is odd or even
        # for this we use the modulo operator (a mod 2 and b mod 2)
        # this results in a 1 if the number is odd (which means the first bit is 1)
        # and 0 if the number is even (which means the first bit is 0)
        # multiplying those two numbers gives the and-operator for the first bit of a and b
        # the other bits are handled by bit-shifting a and b
        # this is equivalent to multiplying (left-shift) or dividing (right-shift) by 2

        c = my_add(c, my_mul(my_mul(my_mod(a, 2), my_mod(b, 2)), d))
        d = my_mul(d, 2)
        a = my_div(a, 2)
        b = my_div(b, 2)

    return c


def my_or(a: int, b: int) -> int:

    c = 0
    d = 1

    while my_leq(1, my_add(a, b)):
        if my_leq(1, my_add(my_mod(a, 2), my_mod(b, 2))):
            c = my_add(c, d)

        d = my_mul(d, 2)
        a = my_div(a, 2)
        b = my_div(b, 2)

    return c


def my_xor(a: int, b: int) -> int:

    c = 0
    d = 1

    while my_leq(1, my_add(a, b)):
        e = my_add(my_mod(a, 2), my_mod(b, 2))
        if my_leq(e, 1):
            c = my_add(c, my_mul(e, d))

        d = my_mul(d, 2)
        a = my_div(a, 2)
        b = my_div(b, 2)

    return c


def test(a: int, b: int):
    assert a & b == my_and(a, b)
    assert a | b == my_or(a, b)
    assert a ^ b == my_xor(a, b)

for i in range(1000):
    test(random.randint(0, 1024), random.randint(0, 1024))

【讨论】:

    【解决方案2】:

    有一种更有效的方法来执行此操作,这需要使用循环运算符并构造一个小于(但不等于)零的函数,您必须自己提供这些函数。这个想法是您可以检查单个位(最高位)是否为负,然后您可以使用它来构造 OR、AND 或 XOR。

    /* Author: Richard James Howe
     * Email:  howe.r.j.89@gmail.com 
     * Using primitives available in SUBLEQ to perform bitwise operations */
    #include <stdio.h>
    #include <stdint.h>
    #include <stdlib.h>
    
    #define N   (16)
    #define TST (9999)
    
    typedef int16_t uword_t;
    typedef int16_t  word_t;
    
    static uword_t zlt(uword_t z) {
        return ((word_t)z) < 0 ? 0xFFFFu : 0;
    }
    
    static uword_t add(uword_t a, uword_t b) {
        return a - (uword_t)((uword_t)0 - b);
    }
    
    static uword_t lshift1(uword_t a) {
        return add(a, a);
    }
    
    static uword_t b_or(uword_t a, uword_t b) {
        uword_t r = 0;
        for (size_t i = 0; i < N; i++) {
            r = lshift1(r);
            if ((uword_t)(zlt(a) + zlt(b)) != (uword_t)0u)
                r++;
            a = lshift1(a);
            b = lshift1(b);
        }
        return r;
    }
    
    static uword_t b_xor(uword_t a, uword_t b) {
        uword_t r = 0;
        for (size_t i = 0; i < N; i++) {
            r = lshift1(r);
            if ((uword_t)(zlt(a) + zlt(b)) == (uword_t)0xFFFFu)
                r++;
            a = lshift1(a);
            b = lshift1(b);
        }
        return r;
    }
    
    static uword_t b_and(uword_t a, uword_t b) {
        uword_t r = 0;
        for (size_t i = 0; i < N; i++) {
            r = lshift1(r);
            if ((uword_t)(zlt(a) + zlt(b)) == (uword_t)0xFFFEu)
                r++;
            a = lshift1(a);
            b = lshift1(b);
        }
        return r;
    }
    
    static uword_t rnd(void) {
        return rand();
    }
    
    int main(void) {
        int pass_or = 1, pass_xor = 1, pass_and = 1;
        for (long i = 0; i < TST; i++) {
            uword_t a = rnd(), b = rnd();
            uword_t rn = a | b;
            uword_t rb = b_or(a, b);
            if (rb != rn) {
                printf("or fail %x %x -- expected %x got %x\n", a, b, rn, rb);
                pass_or = 0;
            }
        }
        printf("or %s\n", pass_or ? "pass" : "FAIL");
        for (long i = 0; i < TST; i++) {
            uword_t a = rnd(), b = rnd();
            uword_t rn = a ^ b;
            uword_t rb = b_xor(a, b);
            if (rb != rn) {
                printf("xor fail %x %x -- expected %x got %x\n", a, b, rn, rb);
                pass_xor = 0;
            }
        }
        printf("xor %s\n",  pass_xor ? "pass" : "FAIL");
        for (long i = 0; i < TST; i++) {
            uword_t a = rnd(), b = rnd();
            uword_t rn = a & b;
            uword_t rb = b_and(a, b);
            if (rb != rn) {
                printf("and fail %x %x -- expected %x got %x\n", a, b, rn, rb);
                pass_and = 0;
            }
        }
        printf("and %s\n",  pass_and ? "pass" : "FAIL");
        printf("done %s\n", pass_or && pass_xor && pass_and ? "pass" : "FAIL");
        return 0;
    }
    

    另见:

    【讨论】:

    • ((word_t)z) &lt; 0 不是小于等于操作吗?我想有一些众所周知的方法来实现它,== 0xFFFEusubleq 而言,但你没有在你的回答中提到它。
    • 是的,你必须自己实现,相等和不等式很容易实现,循环也是如此,大多数 SUBLEQ 汇编器已经实现了这样的结构。所以我把它们排除在外。然而,小于零(并且不等于)有点棘手,但它是可能的。我将开始添加“
    猜你喜欢
    • 2021-12-20
    • 2011-02-26
    • 2021-10-14
    • 2011-08-25
    • 2011-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多