共2条
1/1 1 跳转至页
3qxj 3qxj大侠,请教移位除法!
问
原来我用浮点数做除法,但是发现浮点数运算程序长速度慢且有时候达不到精度要求,就考虑用2进制除法,但是现在不知道什么原理,按刘斑竹给推荐的例子看了半天,一头雾水,试了试,结果也不对,帮忙看一下!
32位/16位无符号除法子程序:
clr r14
mov.w #17,r10
div1 cmp.w r11,r10
jlo div2
sub r11,r13
div2 rlc r14
jc div4
dec r10
jz div4
rla r12
rlc r13
jnc div1
sub r11,r13
setc
jmp div2
div4 ret:o 答 1: 如果你提醒我一下,我明天就从家里带来发给你,不然就不一定是明天,我也是用汇编编的,那是两年前的了. 答 2: 引用: 答 3: 一会儿再说,他是用移位减的方法实现32/16位的整数除法,但好像没有判断数据的大小范围,因为32/16位的结果不一定是16位,可能大于16位呢,还有除数为0最好先判断 答 4: 以前我用汇编时做一个要求低功耗的东西,感觉该程序有点浪费功耗,我就自己编了一个,也没比较谁的效率更高,自我感觉应该我的效率高一些.因为德州仪器的程序它不管除数的大小用移位16次相减的方法,周期比较固定,有时就显得浪费,我先判断大小,再处理,可能会好一些.我模拟手工除发开算式的方法,有点像小学里教小孩的算法.现在我贴在下面:
1.用C编译后的汇编输出方案
入口:R13R12/R15R14->R15R14
调用形式:
CLR.W R15
CALL #DIV_32
RET
DIV_32
PUSH.W R9
PUSH.W R8
PUSH.W R10
PUSH.W R11
MOV.W R14,R10
MOV.W R15,R11
CLR.W R14
CLR.W R15
MOV.W #00001H,R9
CLR.W R8
DIV3
BIT.W #00001H,R9
RLC.W R12
RLC.W R13
RLC.W R14
RLC.W R15
CMP.W R11,R5
JNC DIV1
SETC
JNE DIV2
CMP.W R10,R14
JNC DIV1
DIV2
SUB.W R10,R14
SUBC.W R11,R15
DIV1
RLC.W R9
RLC.W R8
JNC DIV3
RRA R9
RLC.W R12
RLC.W R13
POP.W R11
POP.W R10
POP.W R8
POP.W R9
RET
2.我的方法:
;以下是32/16位程序,入口R5R4/R6→R8R7
DIV32 CLR R7;清结果
CLR R8
MOV #17,R9
DIV1 CMP R6,R5;比较被除数高位和除数的大小
JLO DIV2
SUB R6,R5;被除数高位大于除数则减
ADC R7
JMP DIV1
DIV3 CMP R6,R5
JLO DIV2
SUB R6,R5
DIV2 RLC R7
RLC R8
DEC R9
JZ DIV4
RLA R4
RLC R5
JNC DIV3
SUB R6,R5
SETC
JMP DIV2
DIV4 RRA R8
RET 答 5: 谢谢3qxj大侠!我先试了一下您给我发的那两个子程序。
发现第一个结果是对的,既有商又有余数,就是结果的出口不对,商应该在R15里,却跑到R12里了,这到没有关系!
第二个的结果是只有商,没有余数。
我想用一个在增长的数X/1.924,发现这个程序不太适合我啊,1.924没法用2进制表示,再一个除完后的余数是一个相对1.924的数,我怎么把它转换过来啊!还请3qxj大侠务必再帮帮忙!:o 答 6: 请问你能用C写程序吗,最好用C写,维护容易啊,现在我就很难看懂以前用汇编编的程序了 答 7: 一会儿我吃完中饭再回来聊,否则食堂就没菜了.哈哈 答 8: 好的,大侠,能告诉我你是做什么的吗?怎么还吃食堂啊?---再次谢谢! 答 9: 不吃食堂的话,我还不知怎样来解决温饱问题了. 答 10: 引用: 答 11: 就用小数扩大后运算,或用TI的例程:定点小数运算做,运行速度很快的,例程在光盘上有 答 12: 3qxj大侠,TI的光盘是那张蓝色的吗?我找了!没有找到定点小数运算!能再详细点吗?:o 答 13: 所以只能建议你自己好好找找,我自己一时半会儿也找不到的.
如果不行,我就讲一下第一中方案吧,这种方法也比较快的.不过我还是建议你看看定点乘法的过程,那对所有数据都适用.
x/1.924=x*0.51975,尽量用乘法吧,乘法比除法快一点点啦.
如果你想用十六进制运算的话,那就先用0.51975*65536(10000H)=34063(850FH)
如果x=25,则x*34063=851575(cfe77),则最后的结果就是c(12),余数(相对于10000H)就是fe77H,以后随着x的增加,余数也会增加,当余数大于65536是整数部分就加1,同时余数减去65536,这是用十六进制的方法.
如果你用十进制数的方法,一样处理,不过就是吧65536换成10000而已,当然具体扩大多少倍,由自己根据精度的要求自己决定,值得注意的是在运算过程中要当心因为扩大倍率后引起的数据溢出的问题. 答 14: 非常感谢,不过这种方案对我可能不适用,要是乘100000的话,肯定溢出了,即使不溢出,计数的个数很有限,不过还是非常感谢你!我现在自己琢磨琢磨吧!要是3QXJ大侠弄明白了,别忘了告诉小弟一声,谢谢:D
32位/16位无符号除法子程序:
clr r14
mov.w #17,r10
div1 cmp.w r11,r10
jlo div2
sub r11,r13
div2 rlc r14
jc div4
dec r10
jz div4
rla r12
rlc r13
jnc div1
sub r11,r13
setc
jmp div2
div4 ret:o 答 1: 如果你提醒我一下,我明天就从家里带来发给你,不然就不一定是明天,我也是用汇编编的,那是两年前的了. 答 2: 引用: 答 3: 一会儿再说,他是用移位减的方法实现32/16位的整数除法,但好像没有判断数据的大小范围,因为32/16位的结果不一定是16位,可能大于16位呢,还有除数为0最好先判断 答 4: 以前我用汇编时做一个要求低功耗的东西,感觉该程序有点浪费功耗,我就自己编了一个,也没比较谁的效率更高,自我感觉应该我的效率高一些.因为德州仪器的程序它不管除数的大小用移位16次相减的方法,周期比较固定,有时就显得浪费,我先判断大小,再处理,可能会好一些.我模拟手工除发开算式的方法,有点像小学里教小孩的算法.现在我贴在下面:
1.用C编译后的汇编输出方案
入口:R13R12/R15R14->R15R14
调用形式:
CLR.W R15
CALL #DIV_32
RET
DIV_32
PUSH.W R9
PUSH.W R8
PUSH.W R10
PUSH.W R11
MOV.W R14,R10
MOV.W R15,R11
CLR.W R14
CLR.W R15
MOV.W #00001H,R9
CLR.W R8
DIV3
BIT.W #00001H,R9
RLC.W R12
RLC.W R13
RLC.W R14
RLC.W R15
CMP.W R11,R5
JNC DIV1
SETC
JNE DIV2
CMP.W R10,R14
JNC DIV1
DIV2
SUB.W R10,R14
SUBC.W R11,R15
DIV1
RLC.W R9
RLC.W R8
JNC DIV3
RRA R9
RLC.W R12
RLC.W R13
POP.W R11
POP.W R10
POP.W R8
POP.W R9
RET
2.我的方法:
;以下是32/16位程序,入口R5R4/R6→R8R7
DIV32 CLR R7;清结果
CLR R8
MOV #17,R9
DIV1 CMP R6,R5;比较被除数高位和除数的大小
JLO DIV2
SUB R6,R5;被除数高位大于除数则减
ADC R7
JMP DIV1
DIV3 CMP R6,R5
JLO DIV2
SUB R6,R5
DIV2 RLC R7
RLC R8
DEC R9
JZ DIV4
RLA R4
RLC R5
JNC DIV3
SUB R6,R5
SETC
JMP DIV2
DIV4 RRA R8
RET 答 5: 谢谢3qxj大侠!我先试了一下您给我发的那两个子程序。
发现第一个结果是对的,既有商又有余数,就是结果的出口不对,商应该在R15里,却跑到R12里了,这到没有关系!
第二个的结果是只有商,没有余数。
我想用一个在增长的数X/1.924,发现这个程序不太适合我啊,1.924没法用2进制表示,再一个除完后的余数是一个相对1.924的数,我怎么把它转换过来啊!还请3qxj大侠务必再帮帮忙!:o 答 6: 请问你能用C写程序吗,最好用C写,维护容易啊,现在我就很难看懂以前用汇编编的程序了 答 7: 一会儿我吃完中饭再回来聊,否则食堂就没菜了.哈哈 答 8: 好的,大侠,能告诉我你是做什么的吗?怎么还吃食堂啊?---再次谢谢! 答 9: 不吃食堂的话,我还不知怎样来解决温饱问题了. 答 10: 引用: 答 11: 就用小数扩大后运算,或用TI的例程:定点小数运算做,运行速度很快的,例程在光盘上有 答 12: 3qxj大侠,TI的光盘是那张蓝色的吗?我找了!没有找到定点小数运算!能再详细点吗?:o 答 13: 所以只能建议你自己好好找找,我自己一时半会儿也找不到的.
如果不行,我就讲一下第一中方案吧,这种方法也比较快的.不过我还是建议你看看定点乘法的过程,那对所有数据都适用.
x/1.924=x*0.51975,尽量用乘法吧,乘法比除法快一点点啦.
如果你想用十六进制运算的话,那就先用0.51975*65536(10000H)=34063(850FH)
如果x=25,则x*34063=851575(cfe77),则最后的结果就是c(12),余数(相对于10000H)就是fe77H,以后随着x的增加,余数也会增加,当余数大于65536是整数部分就加1,同时余数减去65536,这是用十六进制的方法.
如果你用十进制数的方法,一样处理,不过就是吧65536换成10000而已,当然具体扩大多少倍,由自己根据精度的要求自己决定,值得注意的是在运算过程中要当心因为扩大倍率后引起的数据溢出的问题. 答 14: 非常感谢,不过这种方案对我可能不适用,要是乘100000的话,肯定溢出了,即使不溢出,计数的个数很有限,不过还是非常感谢你!我现在自己琢磨琢磨吧!要是3QXJ大侠弄明白了,别忘了告诉小弟一声,谢谢:D
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |