chonganget 发表于 2010-9-11 12:28:20

版主,关于多线程下的浮点库使用(比如sprintf格式化浮点输出)!

版主,对于多线程下浮点库的使用论坛上有很多讨论,比如UCOS下sprintf格式化浮点时数据不对等,其解决的办法都是堆栈8字节对齐。却没有人给出根本的原因。
还有有些atan2等函数有时在多任务下也有问题。

对于sprintf格式化浮点要求任务堆栈8字节对齐有些不解,堆栈的8字节对齐和调用此函数表面上好像没有直接的联系,就算任务的堆栈是8字节对齐的可调用sprintf
时的堆栈未必也是8字节对齐的。但是事实上大多数人确实通过任务8字节对齐解决了sprintf格式化浮点输出的问题,包括我在内!但至今不明白其中的原因!

望版主和各位高手能给出答案!

djyos 发表于 2010-9-11 15:15:31

如果我没有猜错,你说的是arm系列的cpu,该cpu的ldrd和strd指令需要8字节对齐的操作数,否则会出错。
正常的函数调用中,只要你栈顶是8字节对齐的,则调用函数时,编译器自动回完成栈的8字节对齐。
但是浮点库往往用异常调用来实现,此时如果栈不是8字节对齐的,编译器就不管了,可能造成出错。
djyos代码中对此是做了处理的,在异常向量入口处就有这样一句:
    push    {r0,lr}                                ;r0只是为了满足栈指针8字节对齐的填充物
该函数实际上并不需要在栈中保护r0,但只执行 push{lr}的话,栈就不是8字节对齐了。
因此,相信在djyos中,浮点库是不会出问题的。

chonganget 发表于 2010-9-11 18:06:47

版主说的对,是CORTEM-M3系列的。
不过还有点不明白,就算8字节堆栈对齐的函数调用,对内部使用像ldrd和strd指令需要8字节对齐的操作数又有什么作用呢?
浮点库往往用异常调用来实现?如何理解使用异常调用实现浮点库函数!或者说为何要使用异常调用来实现浮点函数库!这样
做有什么优势吗?

djyos 发表于 2010-9-11 21:45:18

用异常来实现浮点库只是浮点库的一种实现方法之一,并不一定是这样。
局部变量是以栈顶为基地址编排的,只有栈顶保持8字节对齐,编译器才能却白ldrd和strd指令操作局部变量时,该变量地址是8字节对齐的。

chonganget 发表于 2010-9-13 14:59:35

非常感谢问题决解了,不过对于浮点库使用异常来做持怀疑态度!
因为对于开发者来说,mcu的所有中断一般是由用户来做管理的,
编译器如何能够绕过用户程序?

djyos 发表于 2010-9-13 17:03:01

用异常实现浮点库的说法,确实有些不准确,准确地说,是用异常实现浮点指令仿真。
有些拥有专用编译器的操作系统,可以采用这个方法。
有些种类的cpu,可能A型号具有浮点指令,而B则没有,其他则相同。使用异常来仿真浮点指令的话,可以保持A和B程序的二进制级兼容。

cheerday 发表于 2010-9-13 19:41:31

记得要给编译器传个参数,编译软件浮点库吧,为什么还需要异常呢,效率不就下降了?
页: [1]
查看完整版本: 版主,关于多线程下的浮点库使用(比如sprintf格式化浮点输出)!