数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 1119|回复: 18

[C51] KEIL C51的ldivt实现

[复制链接]
发表于 2024-9-27 12:20:49 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
KEIL C51中没有实现ldivt,所以有时做BCD码处理时的除法和取模效率不高,要无谓的计算两次,研究了一下,用了在线汇编把结果直接取出来,比较方便,实现如下:

typedef struct {
        long quot;
        long rem;
} ldiv_t;       

ldiv_t ldiv(long numer, long denom) {
        ldiv_t result;
        result.quot = numer / denom;
//        result.rem = numer % denom;  //此行用于校验result的地址
        __asm MOV        ?_ldiv?BYTE+8+4,R0
        __asm MOV        ?_ldiv?BYTE+8+5,R1
        __asm MOV        ?_ldiv?BYTE+8+6,R2
        __asm MOV        ?_ldiv?BYTE+8+7,R3
        return result;
}


使用:
ldiv_t  test = ldiv(0x12345678, 0x98765);

以上文件可以单独放在一个C文件里实现,这样变量一般不会出错,否则要自行修改以上的汇编中的局部变量引用.
最后C文件属性中注意勾选src两项!

打赏

参与人数 1家元 +15 收起 理由
不长叶子的树 + 15

查看全部打赏

 楼主| 发表于 2024-9-27 12:31:48 | 显示全部楼层
此操作不局限KEIL C51,理论上适用于所有非标C(只需遵守各自嵌入汇编标准即可),因为底层调用除法子程序后,商和余数肯定是都存在的,只需取出即可.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-27 16:07:41 | 显示全部楼层
mmxx2015 发表于 2024-9-27 15:02
用C51测试,这种做法虽然可以避免2次除法,但效率还可以进一步提高。
Keil C51对余数的处理是这样的:8位 ...

这个写法是实现标准ldiv_t结构及其函数ldiv(),这个是标准C库里面已有的,不过C51里面就没有这个
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-27 16:09:27 | 显示全部楼层
inthsunshine 发表于 2024-9-27 15:17
我在stm32上测试分别求商和求余数,如果优化级别选o3, 将只有1次除法,编译器会自动优化

...

ARM上的话不存在这个问题,它支持ldiv_t结构
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-27 21:13:12 | 显示全部楼层
inthsunshine 发表于 2024-9-27 16:20
改玩stm32吧,g0系列也很便宜,不比51贵多少,却好用很多

玩和做项目区别很大!!!做项目,客户对一个bit的资源都会计较,一个uA的功耗可能就丢了单子
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-27 21:16:42 | 显示全部楼层
mmxx2015 发表于 2024-9-27 20:59
在Keil MDK上测试发现实现的效率很低。
C程序:
汇编程序:

视平台而定,long型一般是4bytes长度,unsigned int有可能编译成4bytes长,有可能2bytes长,如果要确保2bytes,你要的是短整型short int
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-27 21:19:28 | 显示全部楼层
mmxx2015 发表于 2024-9-27 20:59
在Keil MDK上测试发现实现的效率很低。
C程序:
汇编程序:

代码看起来长,但是都是执行一次即可,这个并不会占用太多运算时间,耗时间的是乘除运算里面的循环,在ARM上,带硬件除法指令那这个时间无所谓,如果不带硬件除法器,那就很耗时间了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-27 21:49:58 | 显示全部楼层
mmxx2015 发表于 2024-9-27 21:35
我想说的是在STM32平台依次做32位无符号数除法、取余数运算用ldiv()实现比直接做一次32位无符号数除法和 ...

如果芯片带硬件除法器,效率应该是低一些,视情况来用吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-9-27 22:04:45 | 显示全部楼层
mmxx2015 发表于 2024-9-27 22:03
我是用M3内核芯片试的,M3内核是有硬件除法器的,不熟悉ARM汇编,没看明白编译器怎么算的。
...

我看了下你上面的汇编,你这个M3核应该是性能很强的,mls指令应该是扩展的DSP指令,一般的M3可没有这些指令
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-7-19 05:27 , Processed in 0.093600 second(s), 10 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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