简体   繁体   English

C-8位微处理器上的32位和16位算术

[英]C - 32bit & 16bit arithmetic on 8bit microprocessor

I'm writing some code for an old 8-bit microprocessor (the Hu6280 - a WDC 65C02 derivative in the old NEC PC-Engine console) with 32kb of ram and up to 2.5mbytes of data/code rom. 我正在为旧的8位微处理器(Hu6280-旧的NEC PC-Engine控制台中的WDC 65C02衍生物)编写一些代码,该文件具有32kb的ram和高达2.5mbytes的数据/代码rom。 The language is a variant of Small-C but is limited to just the two following basic types: 该语言是Small-C的一种变体,但仅限于以下两种基本类型:

char (1 byte)
int (2 byte)

It has no struct support and no long int support. 它没有struct支持,也没有长期的int支持。

I'm writing a FAT filesystem library to interface with a SD card reader that was primarily developed for loading game ROM images, however an enterprising hacker has written some assembly to allow raw sector reading from the console side. 我正在编写一个FAT文件系统库,以便与主要用于加载游戏ROM映像的SD卡读卡器接口,但是,一个进取的黑客编写了一些程序集,以允许从控制台端读取原始扇区。 He achieves this by stuffing the 4 8bit values of a 32bit sector address into 4 consecutive memory addresses (char address[4];). 他通过将32位扇区地址的4个8位值填充到4个连续的内存地址(字符地址[4];)中来实现此目的。 My C code leverages his work to read (for the moment) the dos MBR boot sector and partition type information off the SD card. 我的C代码利用他的工作(暂时)从SD卡读取dos MBR引导扇区和分区类型信息。 I've got MBR checksum verifcation and FAT partition detection working. 我已经进行了MBR校验和验证和FAT分区检测。

However, as I need to support FAT32 (which is what the FPGA on the SD card device supports), most of the sector and cluster arithmetic to look up directory entries and files will be based on 32bit LBA sector values. 但是,由于我需要支持FAT32(这是SD卡设备上的FPGA支持的功能),因此用于查找目录条目和文件的大多数扇区和群集算法将基于32位LBA扇区值。

What easy mechanisms do I have to do add/subtract/multiply 8/16/32bit integers, based on the above limitations? 基于上述限制,我有什么简单的机制可以对8/16/32位整数进行加/减/乘运算? Does anyone have any ready made C routines to handle this? 有没有人有现成的C例程来处理这个问题? Maybe something along the lines of: 也许是这样的:

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);`

EDIT: Based on the above replies, this is what I've come up with so far - this is untested as yet and I'll need to do similar for multiplication and subtraction: 编辑:根据以上答复,这是我到目前为止提出的-尚未经过测试,我需要对乘法和减法进行类似的操作:

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;
}

}

EDIT 2: Here's an updated and tested version of the emulated 32bit + 32bit integer add code. 编辑2:这是仿真的32位+ 32位整数添加代码的更新和测试的版本。 It works with all values I've tried so far. 它适用于到目前为止我尝试过的所有值。 Overflow for values bigger than a 32bit unsigned integer is not handled (will not be required for my purposes): 大于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;
    }

}

I also found some references to 32bit arithmetic on some PIC controllers after searching SO a bit more: 在搜索了更多内容之后,我还在一些PIC控制器上找到了一些对32位算术的引用:

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

Although there is some PIC assembly inline in their add/subtract code, there are some useful platform agnostic char-based C functions there that have already implemented shifts, comparisons, increment/decrement etc, which will be very useful. 尽管在它们的加/减代码中有一些PIC汇编内联函数,但是那里有一些有用的基于平台不可知论的基于C的C函数,这些函数已经实现了移位,比较,递增/递减等功能,这将非常有用。 I will look into subtract and multiply next - thanks for the info; 我将研究减法和乘以下一步-感谢您提供的信息; I guess I was looking at things and thinking they were much harder than they needed to be. 我想我正在看事物并认为它们比所需的要难得多。

I know you know how to do this. 我知道你知道该怎么做。 go back to your grade school math... 回到你的小学数学...

When you multiply to numbers, base 10 乘以数字时,以10为底

 12
x34
====

You do four multiplications right and then add four numbers together right? 您正确执行四个乘法,然后将四个数字相加对吗?

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

then 然后

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

Now what about addition 现在怎么样

 12
+34
===

We learned to break that down into two additions 我们学会了将其分解为两个附加项

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

With that knowledge that you already have from childhood, you then simply apply that. 有了从童年时代就已经掌握的知识,那么您就可以简单地应用它。 remember that basic math works whether we have 2 digits operated on 2 digits or 2 million digits operated on 2 million digits. 请记住,无论我们是将2位数字用2位数字运算还是2百万位数字用2百万位数字运算,基本数学运算都是有效的。

The above uses single decimal numbers, but the math works if it were single base 16 numbers or single bits or octal or bytes, etc. 上面使用的是一个十进制数字,但是如果它是单个基数16个数字或单个位或八进制或字节等,则该数学运算有效。

Your C compiler should already be handling these things for you but if you need to synthesize them you can, multiplication at the easiest form for digital is to use bits. 您的C编译器应该已经为您处理了这些事情,但是如果您需要对其进行合成,则数字的最简单形式就是使用位。

addition is easier with bytes using assembly because the carry out is right there, C does not have a carry out so you have to do the exercise of figuring out the carry out using 8 bit math (it can be determined) without needing a 9th bit. 使用汇编使用字节进行加法比较容易,因为进位就在那儿,C没有进位,因此您必须使用8位数学运算(可以确定)来练习执行进位,而无需第9位。 or you can just do something less than 8 bit math, 7 or 4 or whatever. 或者您可以做少于8位数学,7或4或其他任何事情。

As Joachim pointed out, this topic hsa been beat to death decades/centuries ago. 正如约阿希姆(Joachim)所指出的那样,这个主题在几十个世纪之前就被打死了。 At the same time it is so simple that it often doesnt warrent a lot of discussion. 同时,它是如此简单,以至于经常不引起很多讨论。 StackOverflow certainly has this topic covered several times over. 当然,StackOverflow已经多次讨论了该主题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM