0

我正在为具有 32kb ram 和高达 2.5mbytes 数据/代码 rom 的旧 8 位微处理器(Hu6280 - 旧 NEC PC-Engine 控制台中的 WDC 65C02 衍生产品)编写一些代码。该语言是 Small-C 的一种变体,但仅限于以下两种基本类型:

char (1 byte)
int (2 byte)

它没有struct支持,也没有 long int 支持。

我正在编写一个 FAT 文件系统库来与主要为加载游戏 ROM 映像而开发的 SD 卡读卡器接口,但是一个有进取心的黑客编写了一些程序集以允许从控制台端读取原始扇区。他通过将 32 位扇区地址的 4 个 8 位值填充到 4 个连续的内存地址(字符地址 [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;
    }

}

在搜索了一些之后,我还在一些 PIC 控制器上找到了一些对 32 位算法的引用:

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

虽然在他们的加/减代码中有一些内联的 PIC 汇编,但那里有一些有用的平台无关的基于字符的 C 函数,它们已经实现了移位、比较、递增/递减等,这将非常有用。接下来我将研究减法和乘法 - 感谢您提供信息;我想我当时在看东西,并认为它们比需要的要难得多。

4

1 回答 1

1

我知道你知道该怎么做。回到你的小学数学...

当你乘以数字时,以 10 为底

 12
x34
====

你做四次乘法,然后把四个数字加在一起,对吗?

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

然后

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

现在添加呢

 12
+34
===

我们学会了把它分解成两个附加部分

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

有了你从小就已经拥有的知识,然后你就可以简单地应用它。请记住,无论我们是对 2 位数字运算 2 位数字还是对 200 万位数字运算 200 万位数字,基本数学都是有效的。

以上使用单个十进制数字,但如果它是单个基数 16 数字或单个位或八进制或字节等,则数学有效。

您的 C 编译器应该已经为您处理了这些事情,但是如果您需要合成它们,您可以使用最简单的数字乘法形式是使用位。

使用汇编的字节加法更容易,因为进位就在那里,C 没有进位,所以你必须使用 8 位数学(可以确定)来计算进位而不需要第 9 位. 或者你可以做一些少于 8 位数学,7 或 4 或其他的事情。

正如 Joachim 指出的那样,这个话题在几十年/几个世纪前就已经被打死了。同时它是如此简单,以至于它通常不会引起很多讨论。StackOverflow 肯定多次讨论过这个主题。

于 2014-01-07T14:46:09.580 回答