打印

STM32中用C语言进行2个32位有符号数相乘问题

[复制链接]
10752|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chinhj|  楼主 | 2011-7-27 21:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
向大家请教一个32位有符号数相乘的问题。

代码如下:
s32 a,b;//定义两个有符号的32位变量
u32 c;
__int64 d;//定义一个有符号的64位变量

a = 0x70000000;//赋一个正数
b = 2;
d = a * b;

if(d>0)  c = 1;
else c = 0;
结果c=0

按道理,两个正数相乘,d>0才对,但实际不是。

以下为 KEIL 编译后的汇编代码
;;;864     a = 0x70000000;
000992  f04f44e0          MOV      r4,#0x70000000

;;;865     b = 2;
000996  2502              MOVS     r5,#2

;;;866     d = a * b;
000998  fb04f005          MUL      r0,r4,r5  ;此处就不对,看不出有64位结果
00099c  17c1              ASRS     r1,r0,#31
00099e  e9cd0100          STRD     r0,r1,[sp,#0]

;;;867     if(d>0)  c = 1;
0009a2  a00b              ADR      r0,|L1.2512|
0009a4  c80c              LDM      r0!,{r2,r3}
0009a6  e9dd0100          LDRD     r0,r1,[sp,#0]
0009aa  1a12              SUBS     r2,r2,r0
0009ac  418b              SBCS     r3,r3,r1
0009ae  da01              BGE      |L1.2484|
0009b0  2601              MOVS     r6,#1
0009b2  e000              B        |L1.2486|
                  |L1.2484|

;;;868     else c = 0;
0009b4  2600              MOVS     r6,#0

有人知道这问题出在哪里吗?
沙发
上官金虹| | 2011-7-28 08:11 | 只看该作者
本帖最后由 上官金虹 于 2011-7-28 10:02 编辑
d = a * b;
按道理,两个正数相乘,d>0才对,但实际不是。

d = a * b;   
不要被d的类型所迷惑。

a*b;
a是int型,b是int型,
根据C标准,int与int进行运算,结果类型还是int。
(int)(0x70000000)*(int)(2)
结果为(int)(0xE0000000)即10进制 -536870912
d=-536870912;

所以最后d的结果小于0。






使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
sxhhhjicbb + 1 支持.
板凳
上官金虹| | 2011-7-28 08:32 | 只看该作者
本帖最后由 上官金虹 于 2011-7-28 08:34 编辑

这种问题是没有理解C语言运算符的规则。

再给几个个例子: 8位机上,int是16位,long是32位。

long a=10000*10; //结果并不是100000
long a=1<<16       //结果并不是0x00010000

使用特权

评论回复
地板
caner_hn| | 2011-7-28 09:11 | 只看该作者
long a=10000L*10;
long a=(1L<<16);

使用特权

评论回复
5
byeyear| | 2011-7-28 09:53 | 只看该作者
d = a * b;
=> d = (__int64 )a*b;

使用特权

评论回复
6
desomond| | 2011-7-28 16:47 | 只看该作者
一个int型的数据它的第32位是正负位

使用特权

评论回复
7
原野之狼| | 2011-7-28 17:06 | 只看该作者
顶3楼~

使用特权

评论回复
8
chinhj|  楼主 | 2011-7-28 19:53 | 只看该作者
谢谢各位的回答。3楼的解释让我又长见识了,他说的很对,所以代码改成6楼写的那样结果就对了。
d = (__int64 )a*b;  
编译后的汇编代码为
;;;866            d =  (__int64)a *b;
000998  fb840105          SMULL    r0,r1,r4,r5   ;;结果就是64位的了[r1, r0]
00099c  e9cd0100          STRD     r0,r1,[sp,#0]

使用特权

评论回复
9
90chinazhu| | 2014-5-28 20:31 | 只看该作者
mark一下

使用特权

评论回复
10
gilberth| | 2019-3-3 10:10 | 只看该作者
本帖最后由 gilberth 于 2019-3-3 10:56 编辑

楼主遇到问题应该是两数相乘结果超出了int32的最大范围0x7FFFFFFF, 因为开始没有用强制转换,C编译器还是用了32位乘法指令,采用6楼的方法后,汇编指令应改用了结果64位的有符号乘法指令,最终结果就是对的了。若只是这两个32位正数相乘,如果采用无符号数(unint32_t),结果并没有超出0xFFFFFFFF, 那么结果也应该是正确的,且不牵扯到64位指令,不知我的理解对不对。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

5

帖子

0

粉丝