0

32kb の RAM と最大 2.5mbytes のデータ/コード ROM を備えた古い 8 ビット マイクロプロセッサ (Hu6280 - 古い NEC PC エンジン コンソールの WDC 65C02 派生品) 用のコードを書いています。この言語は Small-C のバリアントですが、次の 2 つの基本的なタイプに限定されています。

char (1 byte)
int (2 byte)

structサポートも long int サポートもありません。

私は、主にゲームの ROM イメージをロードするために開発された SD カード リーダーとインターフェイスする FAT ファイルシステム ライブラリを作成していますが、進取の気性に富んだハッカーが、コンソール側から未加工のセクターを読み取ることができるアセンブリを作成しました。彼は、32 ビット セクター アドレスの 4 つの 8 ビット値を 4 つの連続するメモリ アドレス (char address[4];) に詰め込むことによってこれを実現します。私の C コードは、彼の作業を活用して、SD カードから dos MBR ブート セクタとパーティション タイプ情報を (今のところ) 読み取ります。MBR チェックサムの検証と FAT パーティションの検出が機能しています。

ただし、FAT32 (SD カード デバイスの FPGA がサポートするもの) をサポートする必要があるため、ディレクトリ エントリとファイルを検索するためのセクターとクラスター演算のほとんどは、32 ビット LBA セクター値に基づいています。

上記の制限に基づいて、8/16/32 ビット整数を加算/減算/乗算するために必要な簡単なメカニズムは何ですか? これを処理する既成の C ルーチンを持っている人はいますか? たぶん、次のようなものです:

char int1[4], int2[4], int3[4];

int1[0] = 1;
int1[1] = 2;
int1[2] = 3;
int1[3] = 4;

int2[0] = 4;
int2[1] = 3;
int2[2] = 2;
int2[3] = 1;

int3 = mul_32(int1, int2);
int3 = add_32(int1, int2);
int3 = sub_32(int1, int2);`

編集:上記の返信に基づいて、これは私がこれまでに思いついたものです-これはまだテストされておらず、乗算と減算についても同様のことを行う必要があります:

char_to_int32(int32_result, int8)
char* int32_result;
char int8;
{
/* 
    Takes an unsigned 8bit number
    and converts to a packed 4 byte array
*/
int32_result[0] = 0x00;
int32_result[1] = 0x00;
int32_result[2] = 0x00;
int32_result[3] = int8;

return 0;
}

int_to_int32(int32_result, int16)
char*   int32_result;
int         int16;
{
/* 
    Takes an unsigned 16bit number
    and converts to a packed 4 byte array
*/

int32_result[0] = 0x00;
int32_result[1] = 0x00;
int32_result[2] = (int16 >> 8);
int32_result[3] = (int16 & 0xff);

return 0;
}


int32_is_zero(int32)
char*   int32;
{
/* 
    Is a packed 4 byte array == 0
    returns 1 if true, otherwise 0
*/

if ((int32[0] == 0) & (int32[1] == 0) & (int32[2] == 0) & (int32[3] == 0)) {
    return 1;
} else {
    return 0;
}

}

add_32(int32_result, int32_a, int32_b)
char*   int32_result;
char*   int32_a;
char*   int32_b;
{
/* 
    Takes two 32bit values, stored as 4 bytes each - 
    adds and stores the result.

    Returns 0 on success, 1 on error or overflow.
*/

int         sum;
char    i;
char    carry;

carry = 0x00;
/* loop over each byte of the 4byte array */
for (i = 4; i != 0; i--) {
    /* sum the two 1 byte numbers as a 2 byte int */
    sum = int32_a[i-1] + int32_b[i-1] + carry;
    /* would integer overflow occur with this sum? */
    if (sum > 0x00ff) {
        /* store the most significant byte for next loop */
        carry = (sum >> 8);
    } else {
        /* no carry needed */
        carry = 0x00        
    }
    /* store the least significant byte */
    int32_result[i+1] = (sum & 0xff);
}

/* Has overflow occured (ie number > 32bit) */
if (carry != 0) {
    return 1;
} else {
    return 0;
}

}

編集 2: これは、エミュレートされた 32 ビット + 32 ビット整数の追加コードの更新およびテスト済みバージョンです。これまでに試したすべての値で機能します。32 ビット符号なし整数より大きい値のオーバーフローは処理されません (私の目的では必要ありません)。

add_int32(int32_result, int32_a, int32_b)
char*   int32_result;
char*   int32_a;
char*   int32_b;
    {
    /* 
        Takes two 32bit values, stored as 4 bytes each - 
        adds and stores the result.
        Returns 0 on success, 1 on error or overflow.
    */

    int     sum;
    char    i, pos;
    char    carry;

    zero_int32(int32_result);

    carry = 0x00;
    /* loop over each byte of the 4byte array from lsb to msb */
    for (i = 1; i < 5; i++) {
        pos = 4 - i; 
        /* sum the two 1 byte numbers as a 2 byte int */
        sum = int32_a[pos] + int32_b[pos] + carry;
        /* would integer overflow occur with this sum? */
        if (sum > 0x00ff) {
            /* store the most significant byte for next loop */
            carry = (sum >> 8);
        } else {
            /* no carry needed */
            carry = 0x00;   
        }
        /* store the least significant byte */
        int32_result[pos] = (sum & 0x00ff);
    }

    /* Has overflow occured (ie number > 32bit) */
    if (carry != 0) {
        return 1;
    } else {
        return 0;
    }

}

SOをもう少し検索した後、一部のPICコントローラーで32ビット演算への参照もいくつか見つけました。

http://web.media.mit.edu/~stefanm/yano/picc_Math32.html

加算/減算コードにはインラインのPICアセンブリがいくつかありますが、シフト、比較、インクリメント/デクリメントなどをすでに実装している、プラットフォームに依存しない便利なcharベースのC関数がいくつかあり、非常に便利です。次に減算と乗算を調べます-情報をありがとう; 私は物事を見て、必要以上に難しいと思っていたと思います。

4

1 に答える 1

1

私はあなたがこれを行う方法を知っていることを知っています. 小学校の数学に戻って...

数を掛けるときは10を底とする

 12
x34
====

4 つの乗算を正しく行ってから、4 つの数値を足し合わせますよね?

4x2 = 8
4x1 = 4
3x2 = 6
3x1 = 3

それから

   12
  x34
 ====
 0008
 0040
 0060
+0300
======

では追加はどうでしょうか

 12
+34
===

それを2つの追加に分解することを学びました

2+4 = 6 carry a zero
1+3+carryin of 0 = 4

子供の頃からすでに持っている知識があれば、あとはそれを適用するだけです。基本的な数学は、2 桁を 2 桁で操作する場合でも、200 万桁を 200 万桁で操作する場合でも機能することを覚えておいてください。

上記は単一の 10 進数を使用していますが、それが単一の基数 16 の数値、単一のビット、8 進数、またはバイトなどである場合、数学は機能します。

あなたのCコンパイラはすでにこれらのものを処理しているはずですが、それらを合成する必要がある場合は、デジタルの最も簡単な形式での乗算はビットを使用することです.

キャリーアウトがすぐそこにあるため、アセンブリを使用してバイトを使用すると加算が簡単になります.Cにはキャリーアウトがないため、9番目のビットを必要とせずに8ビット数学を使用してキャリーアウトを計算する演習を行う必要があります(決定できます) . または、8ビット未満の数学、7または4、または何でも行うことができます。

ヨアヒムが指摘したように、この話題は何十年も何世紀も前に打ちのめされてきました。同時に、それは非常に単純であるため、あまり議論する必要はありません。StackOverflow では、このトピックが何度も取り上げられています。

于 2014-01-07T14:46:09.580 に答える