woshigeshuai 发表于 2020-3-6 12:40:39

51单片机汇编 3个字节乘3个字节得6个字节 用C该怎么实现

最近在研究一段51汇编程序,3个字节乘以3个字节得到结果6个字节
还有6个字节的除法

我在把这段计算通过C语言实现,现在问题来了,51 C乘法最大结果是4个字节,不知道如何实现
想嵌入汇编的方式实现,不管怎么计算,知道最后结果就行。
或者 把汇编语言一些计算制作成lib ,然后C来调用,但没操作过,问问大家
我现在正在研究制作lib

takashiki 发表于 2020-3-6 12:44:50

数组、结构体、指针...

1a2b3c 发表于 2020-3-6 13:56:51

本帖最后由 1a2b3c 于 2020-3-6 13:58 编辑


看错了,重新编辑

不知道有没有标准的分散的整数表示方法,就是超过4个字节的方式,

woshigeshuai 发表于 2020-3-6 14:06:42

有没有可能有什么官方的库
例如 intrins.h,直接包含就可以使用

ztrx 发表于 2020-3-6 14:08:26

long         

1a2b3c 发表于 2020-3-6 14:11:44

其实我才想起我好多年前就处理过超过32bit long的乘法,只是现在压根不记得了,简单的思路是这样的,
先判断乘法的结果不会不会溢出4个字节,然后溢出的话再自己添加高位字节的内容即可,
或者根据基本的乘法原理(都是加法实现好像),对不断溢出的部分重新累计到新的字节作为更高的字节即可,这样即使32bit,64bit,100bit又何妨?

祝早日搞定!{:lol:}

1a2b3c 发表于 2020-3-6 14:17:53

晕,还是没有看明白你的目的,
原来你是要在C里面调用你的>32bit结果,
这样就简单多了
因为C51好像没有longlong格式,那么你既然都是自己定义的结构,就很好办啊,完全用汇编的思路呗,参数就是6个(8个)字节的返回值,输入就是两个3个字节,输入可以用标准的long,输出就是自定义的一个数组(6/8个字节)或者指针,这样行么?

vuo50z 发表于 2020-3-6 14:19:10

1a2b3c 发表于 2020-3-6 14:11
其实我才想起我好多年前就处理过超过32bit long的乘法,只是现在压根不记得了,简单的思路是这样的,
先判 ...

说白了就是竖式
用计算机的语言把竖式的计算过程写出来

1a2b3c 发表于 2020-3-6 14:21:45

vuo50z 发表于 2020-3-6 14:19
说白了就是竖式
用计算机的语言把竖式的计算过程写出来

恩,你说的专业术语,我没搞懂{:lol:}

就是这个意思,不断的累积进位就完了,和位数有什么关系,一点都没有,哈哈

FireBrain 发表于 2020-3-6 14:23:09

乘法用循环左移位即可实现,具体既可以看用c写好然后变成asm的代码是如何实现的

ztrx 发表于 2020-3-6 14:38:10

vuo50z 发表于 2020-3-6 14:43:13

1a2b3c 发表于 2020-3-6 14:21
恩,你说的专业术语,我没搞懂

就是这个意思,不断的累积进位就完了,和位数有什么关系,一点都 ...

就是小学学的竖式啊
把十进制换成一个字节的256进制,方法不变
效率高不高不知道,但肯定可行
我写过任意字节长度的加法和减法,乘法类似,但除法差别有点大

mcu5i51 发表于 2020-3-6 14:50:27

用C写个指针参数返回的函数,编译时生成汇编,再修改这个汇编代码,使用时把这个文件加入工程;
怎么用自己定,可以用数组,指针,结构体等

cqfeiyu 发表于 2020-3-6 15:54:43

乘法转换为加法计算,除法转换为减法计算

zhugean 发表于 2020-3-6 16:06:53

51的话嵌入汇编是最好的办法

鲜衣怒马 发表于 2020-3-6 18:12:56

用竖式写过长数的乘法,计算100以上的阶乘之类,用256字节的数组存储,纯属闲的蛋疼

dongwang_fl 发表于 2020-3-6 18:16:13

这种应该有专门 的算法吧。

our2008 发表于 2020-3-6 20:44:47

本帖最后由 our2008 于 2020-3-6 20:50 编辑

用C了,内存大就没必要在考虑3字节啦!
直接用四字节计算,取三字节的结果就可以了。
汇编用三字节是因为节约资源的写法。

所以别人用汇编写出来的功能,你用C实现还不一定能装得回原来的片子。

chenchaoting 发表于 2020-3-6 21:35:36

KEIL C调用ASM 很容易啊,注意参数传递就行了

woshigeshuai 发表于 2020-3-7 09:22:03

our2008 发表于 2020-3-6 20:44
用C了,内存大就没必要在考虑3字节啦!
直接用四字节计算,取三字节的结果就可以了。
汇编用三字节是因为节 ...

但是结果是6个字节,C计算结果只有4个字节

woshigeshuai 发表于 2020-3-7 09:23:27

chenchaoting 发表于 2020-3-6 21:35
KEIL C调用ASM 很容易啊,注意参数传递就行了

我也在想这个问题 结果怎么传递,正在找资料

our2008 发表于 2020-3-7 10:42:41

woshigeshuai 发表于 2020-3-7 09:22
但是结果是6个字节,C计算结果只有4个字节

只是取值范围问题!
那c就用long,取6个字节的结果就行了。

woshigeshuai 发表于 2020-3-7 10:49:10

our2008 发表于 2020-3-7 10:42
只是取值范围问题!
那c就用long,取6个字节的结果就行了。

51单片机 long只有4字节

our2008 发表于 2020-3-7 11:04:47

woshigeshuai 发表于 2020-3-7 10:49
51单片机 long只有4字节

那c只能使用结构体,用指针操作!

要不就还是用汇编了!

rtems 发表于 2020-3-7 15:16:19

本帖最后由 rtems 于 2020-3-7 15:19 编辑

大数乘法?看看我儿子写的公众号上的一篇。
https://mp.weixin.qq.com/s?__biz=MzU2MTM1MjQ3MA==&mid=2247483663&idx=1&sn=3abe070075c2de3593d96e762b200aac&chksm=fc7b5b76cb0cd260110f12d64baf419220af84f67e41cdb35a35d25df87f9ee541137fb153fb&mpshare=1&scene=1&srcid=&sharer_sharetime=1583565491431&sharer_shareid=4ce3e219fa04e77c012e5031977237c9&key=8935aba84ca9348a94d766008a03042f1168628f3d435f0d8f41b7daf1b6d546bcc1b4b0e356c5ca5f9e235299b38a0c873dbfb2d29343f2aab0afe3f67e283623a460347e2136a5bc8116cf388d8ce5&ascene=1&uin=MTIyMzMwMDg4NA%3D%3D&devicetype=Windows+10&version=62080079&lang=zh_CN&exportkey=AdYtihWfsb6FHMuaryuEbYY%3D&pass_ticket=ZF00dQv%2BOWOklhiqq7Znuw2iFjz9TmzpHVPlb3diPxdpwxKrg%2FgJt95AVcTEaJBC

算法2: 高精度乘法
何长青 智子笔记 2月19日
题目描述:给出两个整数(a、b),计算它们的积。

输入:一行两个整数(1 < a,b < 10^1000)

输出:一行一个整数,表示a*b



因为上限还是1000位,所以照样还是高精度。。。

一样,乘法也需要手写竖式,但是与加法不同的是,乘法需要将第二个数的每一位都乘一遍第一个数。

是不是很懵。。。

没事,一步一步来

我们平时算乘法时要列的竖式长这个样子:



            55

x            55

——————

          275

      275

——————

      3025



分解一下(以下文字需要很深的思考,需要读者慢慢阅读、思考)



第一步,把第一个55的每一位都乘以第二个55的个位,也就是5,得到积275。

第二步,把第一个55的每一位都乘以第二个55的十位,也就是5,得到积275。(实际上这个275代表着2750)

第三步,将275与2750相加,得到答案3025

是不是还是很懵。。。



继续拆解第一步

首先,我们将第一个55的个位5乘以第二个55的个位5,得到25,存在答案的个位,进位给答案的十位,很正常对吧

其次,我们将第一个55的十位5乘以第二个55的个位5,得到25,存在答案的十位,进位给答案的百位

我们发现在乘法中,第二个55的个位5乘的不是5,而是50,也就是5 * 5 *(10^1)。得到的应该是250



继续找规律,第二步

首先,我们将第一个55的个位5乘以第二个55的十位5,得到25,存在答案的十位,进位给答案的百位

这里,第一个55的个位5乘的不是5,而是50,也就是5 * 5 *(10^1)。得到的应该是250

其次,我们将第一个55的十位5乘以第二个55的十位5,得到25,存在答案的百位,进位给答案的千位

这里,第二个55的十位5乘的不是5,而是50;第一个55的十位乘的也不是5,而是50,也就是5 * 5 * (10^2),得到的是2500



这时,规律已经找出了

我们不妨把个位设为0位,十位设为1位,百位设为2位,以此类推。。。

每一次相乘,得到的结果(25)都存在答案的 位数 + 位数 位。

用编程语言表示:ans += a * b (i和j分别表示第二个数的位数和第一个数的位数)



其余的需要注意点就是,需要在最后处理的时候去掉首位的0。

在处理进位的时候,要注意乘法中的进位可能不止19,所以不是一个简单的-10就可以搞定的。。。

#include <iostream>
#include <cstring>
using namespace std;

#define MAXLEN 1005
#define MAXLEN2 1000005

string la, lb; // 用字符串输入两个数
int a, b, ans; // a是第一个数,b是第二个数, ans是积(这里长度要单独处理,以免RE)
int len; // 积的长度

void MULTIPLICATION()
{
    for (int i = 0; i < la.length(); i++)
    {
      for (int j = 0; j < lb.length(); j++)
      {
            ans += (a * b); // 将第一个数的第i位与第二个数的第j位的积存到ans的i+j位
            if (ans >= 10) // 处理进位
            {
                ans += (ans / 10);
                ans %= 10;
            }
      }
    }
}

int main()
{
    cin >> la >> lb; // 输入
    memset(ans, 0, MAXLEN); // 将ans的每一位初始化为零
for (int i = 0; i < la.length(); i++) a = la - '0'; // 倒着输入第一个数
    for (int i = 0; i < lb.length(); i++) b = lb - '0'; // 倒着输入第二个数
    len = la.length() + lb.length(); // 将积的长度暂定为两个数的长度之和
    MULTIPLICATION(); // 乘法
    while (ans == 0) len--; // 去除最高位的0
    for (int i = len - 1; i >= 0; i--) cout << ans; // 输出
    return 0;
}

rom 发表于 2020-3-7 15:17:37

写个c的,然后看汇编就行了
页: [1]
查看完整版本: 51单片机汇编 3个字节乘3个字节得6个字节 用C该怎么实现