ror rol 就是了 x86或者大多數處理器的asm 標準指令

TOP

本帖最後由 speedrider 於 2024-4-24 09:25 編輯

你其實已經寫出了解答方向:
「一個數的其中一部份搬去另外一個數」是等同於「把2個數同時一加一減」。

電路上只要有2組ALU,是可以實現把2個數同時一加一減的,只是大多數CPU未有這個設計。

因此我們需要想方法,只用1個加法指令,同時做一加一減。

思路是我們可以把要減的數寫成二補數 (2s complement) 格式,就可在一條加法指令做埋減法,達成同時一加一減。

至於要同時對2個數做操作,我們只需用bitwise OR把它們組合成1個數處理就可。

例如 5, 7,同時相加減2,結果是3, 9。

1. 以4-bit為例,先把5, 7分別寫成4-bit:

5 => 0101
7 => 0111

2. 把相加減數 2 寫成 -2, 2,其中-2用二補數格式:

-2 => 1110
2 => 0010

3. 把減數 5 放到頭 4bit,加數 7 放到尾4bit,用 bitwise OR 組合起來。
相加減數 2 也是這樣,-2 放到頭 4bit,2 放到尾 4bit):

5 | 7  =>   0101  0111
-2 | 2  =>  1110  0010

4. 把以上2數直接相加:

(5 | 7) + (-2 | 2)
= 0101  0111   +  1110  0010
= 10011  1001   (頭多出1bit)
= 0011  1001     (丟棄它就可)
= 3  9

為示範以上思路,我寫了一段C程式:
(為求簡單,我無處理overflow、相減後可能會負數等問題,勿插)

#include <stdio.h>

int main(void) {
    // 用 8-bit 表示加減數
    unsigned char x_sub = 5;
    unsigned char y_add = 7;
    unsigned char n = 2;

    // 頭 8-bit 放減數,尾 8-bit 放加數
    unsigned short x_and_y = (x_sub << 8) | y_add;
    unsigned short neg_n_and_n = ((~n + 1) << 8) | n;

    // 加法
    unsigned short result = x_and_y + neg_n_and_n;

    // 取出加、減數結果,減數在頭 8-bit,加數在尾 8-bit
    unsigned char add = (unsigned char) result;
    unsigned char sub = (unsigned char) (result >> 8);

    // 印出結果
    printf("Sub: %d\n", sub);
    printf("Add: %d\n", add);

    return 0;
}

* 如果我們直接用電路 (IC, FPGA) 實現,會簡單好多。最直接做法是用2個 Adder 加法電路,其中一個前面加二補數轉換電路。或是更直接,1個 Adder 加一個 Subtractor 就得。

kong@upo

TOP

本帖最後由 speedrider 於 2022-12-25 13:40 編輯

剛剛再想到,其實可以用數學對映方法把 x, y 合併計算,這個方法可計算任意的加減數,加減的值可以不相同。

例如,以下假設我們限制 x, y, 及運算後的數值必須在 1000 以下,可以用 x*1000 + y 把2數合併成1個,原理是把 x 對映到 1000 以上,y 對映到 1000 以下。

設 x, y = 5, 7 ;  nx, ny = -2, 3 ;
(預期結果是 x+nx, y+ny = 3, 10)

1.  把 x, y 用方程式 x*1000 + y 合併起來:
5*1000 + 7 = 5007

2.  把 nx, ny 用方程式 nx*1000 + ny 合併起來:
-2*1000 + 3 = -1997

3.  把2數相加:
5007 + (-1997) = 3010

4. 用整數除法 (Floor after division) 和取餘數把X, Y取回:

X = 3010 // 1000 = 3
Y =  3010 % 1000 = 10

和預期結果相同。

再寫了一段C程式示範這點:
(為求簡單,程式只能處理 x, y 為1000以下。另外如果是相減,相減後不能為負數,勿插)

*** 同樣原理可延伸到計算3個或更多的數,例如 x*10000 + y*1000 + z   (不過留意 y 不可大於 9,不然會覆蓋到 x 值,應該可以找到更好的對映方程式來解決這個問題。)

#include <stdio.h>

// 計算 x+nx, y+ny
int main(void) {
    int x, y, nx, ny;

    // 輸入參數
    printf("Input x: ");
    scanf("%d", &x);
    printf("Input y: ");
    scanf("%d", &y);
    printf("Input nx: ");
    scanf("%d", &nx);
    printf("Input ny: ");
    scanf("%d", &ny);

    // 把 x, nx 數值對映到 1000 以上,y, ny 數值對映到 1000 以下
    int x_and_y = x*1000 + y;
    int nx_and_ny = nx*1000 + ny;

    // 相加
    int result = x_and_y + nx_and_ny;

    // 運用整數除法取回 1000 以上的 X 數值
    // 運用餘數取回 1000 以下的 Y 數值
    int result_x = result / 1000;
    int result_y = result % 1000;
    printf("X: %d\n", result_x);
    printf("Y: %d\n", result_y);

    return 0;
}

TOP

邏輯閂唔係好簡單就做到?

TOP

瞬間轉移? 咁 幾多秒 內 就是 瞬間/同時?

提示: 作者被禁止或刪除 內容自動屏蔽

TOP