搜索
bottom↓
回复: 25

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

[复制链接]

出0入0汤圆

发表于 2020-3-6 12:40:39 | 显示全部楼层 |阅读模式
最近在研究一段51汇编程序,3个字节乘以3个字节得到结果6个字节
还有6个字节的除法

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入93汤圆

发表于 2020-3-6 12:44:50 | 显示全部楼层
数组、结构体、指针...

出0入475汤圆

发表于 2020-3-6 13:56:51 | 显示全部楼层
本帖最后由 1a2b3c 于 2020-3-6 13:58 编辑


看错了,重新编辑

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

出0入0汤圆

 楼主| 发表于 2020-3-6 14:06:42 | 显示全部楼层
有没有可能有什么官方的库
例如 intrins.h,直接包含就可以使用

出0入4汤圆

发表于 2020-3-6 14:08:26 | 显示全部楼层
long         

出0入475汤圆

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

祝早日搞定!

出0入475汤圆

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

出0入0汤圆

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

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

出0入475汤圆

发表于 2020-3-6 14:21:45 | 显示全部楼层
vuo50z 发表于 2020-3-6 14:19
说白了就是竖式
用计算机的语言把竖式的计算过程写出来

恩,你说的专业术语,我没搞懂

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

出0入0汤圆

发表于 2020-3-6 14:23:09 | 显示全部楼层
乘法用循环左移位即可实现,具体既可以看用c写好然后变成asm的代码是如何实现的

出0入4汤圆

发表于 2020-3-6 14:38:10 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2020-3-6 14:43:13 | 显示全部楼层
1a2b3c 发表于 2020-3-6 14:21
恩,你说的专业术语,我没搞懂

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

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

出0入0汤圆

发表于 2020-3-6 14:50:27 | 显示全部楼层
用C写个指针参数返回的函数,编译时生成汇编,再修改这个汇编代码,使用时把这个文件加入工程;
怎么用自己定,可以用数组,指针,结构体等

出0入0汤圆

发表于 2020-3-6 15:54:43 | 显示全部楼层
乘法转换为加法计算,除法转换为减法计算

出0入0汤圆

发表于 2020-3-6 16:06:53 | 显示全部楼层
51的话嵌入汇编是最好的办法

出50入58汤圆

发表于 2020-3-6 18:12:56 来自手机 | 显示全部楼层
用竖式写过长数的乘法,计算100以上的阶乘之类,用256字节的数组存储,纯属闲的蛋疼

出0入0汤圆

发表于 2020-3-6 18:16:13 | 显示全部楼层
这种应该有专门 的算法吧。

出50入10汤圆

发表于 2020-3-6 20:44:47 | 显示全部楼层
本帖最后由 our2008 于 2020-3-6 20:50 编辑

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

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

出20入25汤圆

发表于 2020-3-6 21:35:36 | 显示全部楼层
KEIL C调用ASM 很容易啊,注意参数传递就行了

出0入0汤圆

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

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

出0入0汤圆

 楼主| 发表于 2020-3-7 09:23:27 | 显示全部楼层
chenchaoting 发表于 2020-3-6 21:35
KEIL C调用ASM 很容易啊,注意参数传递就行了

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

出50入10汤圆

发表于 2020-3-7 10:42:41 | 显示全部楼层
woshigeshuai 发表于 2020-3-7 09:22
但是结果是6个字节,C计算结果只有4个字节

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

出0入0汤圆

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

51单片机 long只有4字节

出50入10汤圆

发表于 2020-3-7 11:04:47 | 显示全部楼层
woshigeshuai 发表于 2020-3-7 10:49
51单片机 long只有4字节

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

要不就还是用汇编了!

出0入0汤圆

发表于 2020-3-7 15:16:19 来自手机 | 显示全部楼层
本帖最后由 rtems 于 2020-3-7 15:19 编辑

大数乘法?看看我儿子写的公众号上的一篇。
https://mp.weixin.qq.com/s?__biz ... rg%2FgJt95AVcTEaJBC

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

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

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



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

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

是不是很懵。。。

没事,一步一步来

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



              5  5

x            5  5

——————

          2  7  5

      2  7  5

——————

      3  0  2  5



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



第一步,把第一个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[i+j] += a[j] * b (i和j分别表示第二个数的位数和第一个数的位数)



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

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

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

#define MAXLEN 1005
#define MAXLEN2 1000005

string la, lb; // 用字符串输入两个数
int a[MAXLEN], b[MAXLEN], ans[MAXLEN2]; // 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[i+j] += (a * b[j]); // 将第一个数的第i位与第二个数的第j位的积存到ans的i+j位
            if (ans[i+j] >= 10) // 处理进位
            {
                ans[i+j+1] += (ans[i+j] / 10);
                ans[i+j] %= 10;
            }
        }
    }
}

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

出0入0汤圆

发表于 2020-3-7 15:17:37 | 显示全部楼层
写个c的,然后看汇编就行了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 06:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表