打印
[AVR单片机]

电工常识之(4):用AVR汇编 编写的8字节16进制转十进制程序

[复制链接]
5552|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xuyiyi|  楼主 | 2010-8-14 12:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在论坛上,看到某网友发了个贴子,详见:

[PIC 单片机] 主题:求救啊 8字节16进制转十进制 大侠们给看看啊 搞不出来了


由于飞船大力推广AVR汇编,要将本论坛打造成最强单片机“汇编”与“C”的混编论坛,让世人重新定位8位单片机---> AVR

俺响应飞船斑竹的号召,试用AVR汇编指令编写了这个8字节16进制数转10字节十进制数程序。

感兴趣用的着的网友们,在编程时可参考一下。
评分
参与人数 1威望 +1 收起 理由
123jj + 1

相关帖子

来自 2楼
xuyiyi|  楼主 | 2010-8-14 12:34 | 只看该作者
;-------------------------------------------------------------
;
;
;           8字节十六进制数转换成10字节十进制数
;
;
;
;     输入:R18R19R20R21R22R23R24R25(高在先,8字节十六进制数)
;
;     输出:R6R7R8R9R10R11R12R13R14R15(高在先,10字节十进制数)
;
;
;
;
;
;        作者:许意义
;
;        版本:Ver 1.0.0
;
;        日期:2010年8月14日
;
;-------------------------------------------------------------


.include <m16def.inc>

;--------------------------------------------------------------

;    输入8字节十六进制数预定义(高在先)

       .EQU   var1 = 0x12
       .EQU   var2 = 0x34
       .EQU   var3 = 0x56
       .EQU   var4 = 0x78
       .EQU   var5 = 0x9a
       .EQU   var6 = 0xbc
       .EQU   var7 = 0xde
       .EQU   var8 = 0xf0

;--------------------------------------------------------------


.CSEG

.org 0

         RJMP  START

START:
         LDI   R28,0x00      
         LDI   R29,0x01        
         OUT   0x3E,R29      
         OUT   0x3D,R28        

         LDI   R18,var1  
         LDI   R19,var2  
         LDI   R20,var3  
         LDI   R21,var4  
         LDI   R22,var5  
         LDI   R23,var6  
         LDI   R24,var7  
         LDI   R25,var8  

;-------------------------------------------------------------

         RCALL CONV10

;-------------------------------------------------------------

         NOP
         NOP
STARTEND:
         RJMP  STARTEND


;--------------------------------------------------------------
;
;
;           8字节十六进制数转换成10字节十进制数
;
;
;
;     输入:R18R19R20R21R22R23R24R25(高在先,8字节十六进制数)
;
;     输出:R6R7R8R9R10R11R12R13R14R15(高在先,10字节十进制数)
;

;--------------------------------------------------------------

CONV10:  LDI    R17,64   ; R6R7R8R9R10R11R12R13R14R15<--(R18R19R20R21R22R23R24R25)左移64次
       MOV    R3,R17     
       CLR    R6
       CLR    R7
       CLR    R8
       CLR    R9
       CLR    R10
       CLR    R11
       CLR    R12
       CLR    R13      
       CLR    R14      
       CLR    R15          ; 十进制数存储区预清除
CV1:   LSL    R25
       ROL    R24
       ROL    R23
       ROL    R22
       ROL    R21
       ROL    R20
       ROL    R19
       ROL    R18          ; 二进制数整体左移一位
       MOV    R16,R15
       RCALL  LSDAA
       MOV    R15,R16
       MOV    R16,R14
       RCALL  LSDAA
       MOV    R14,R16
       MOV    R16,R13
       RCALL  LSDAA
       MOV    R13,R16  
       MOV    R16,R12
       RCALL  LSDAA
       MOV    R12,R16
       MOV    R16,R11
       RCALL  LSDAA
       MOV    R11,R16
       MOV    R16,R10
       RCALL  LSDAA
       MOV    R10,R16
       MOV    R16,R9
       RCALL  LSDAA
       MOV    R9,R16
       MOV    R16,R8
       RCALL  LSDAA
       MOV    R8,R16
       MOV    R16,R7
       RCALL  LSDAA
       MOV    R7,R16
       MOV    R16,R6
       RCALL  LSDAA       ; 十进制数左移并调整
       MOV    R6,R16
       DEC    R3
       BRNE   CV1
       RET

LSDAA: ADC    R16,R16     ; 十进制数(在R16中)左移调整子程序
ADDAA: IN     R2,SREG     ; bcd码相加调整子程序,先保存相加后的
       LDI    R17,$66     ; 状态the old status
       ADD    R16,R17     ; 再将和预加立即数$66
       IN     R17,SREG    ; 输入相加后新状态(the new status)
       OR     R2,R17      ; 新旧状态相或
       SBRS   R2,0        ; 相或后进位置位则跳行
       SUBI   R16,$60     ; 否则减去$60(十位bcd不满足调整条件)
       SBRS   R2,5        ; 半进位置位则跳行
       SUBI   R16,6       ; 否则减去$06(个位bcd不满足调整条件)
       ROR    R2          ; 向高位字节BCD返还进位位!
       RET

;---------------------END-------------------------------------

.EXIT

使用特权

评论回复
板凳
xuyiyi|  楼主 | 2010-8-14 12:38 | 只看该作者
------如何用AVR汇编 编写一个8字节16进制数 转 10字节十进制数 程序------

------连载完,谢谢关注------

使用特权

评论回复
地板
123jj| | 2010-8-14 12:40 | 只看该作者
沙发!

使用特权

评论回复
5
粉丝| | 2010-8-14 16:07 | 只看该作者
没有转换算法流程,没有给出算法透导数学公式,楼主这是在打击初学汇编算法的新手!
看过楼主写的乘法器和加法器,既没有给出逻辑表达达,又没有给出逻辑图,只贴出一些让人摸不着头脑的汇编代码。

使用特权

评论回复
6
xuyiyi|  楼主 | 2010-8-14 17:31 | 只看该作者
呵呵!

不好意思,因为这种程序太简单了,俺只是随手写写的,什么转换算法流程,什么算法透导数学公式,什么逻辑表达式,什么逻辑图,俺这个初中生实在文采太差,有劳 粉丝大师 帮忙写一下。

原想 粉丝大师 能发起PK命题:
用AVR的布尔提供的功能实现4*4的硬件乘法器功能。语言---AVR汇编。编译器avrstudio ,即日起生效!

粉丝大师 的AVR汇编一定运用如神,比俺这个初中生不知强多少倍,俺也实在没能力有你师傅那种本事,一句话就将这么个简单程序说明白,要么这样,俺将这简单的AVR汇编改写成AVRGCC,  请 粉丝大师 过目指导,不知俺用C,  你师傅是否会同意。

使用特权

评论回复
7
宇宙飞船| | 2010-8-14 17:42 | 只看该作者
飞船看过现在市面上的一些所谓《汇编子程序大全》的书,全是网上下载的资料整理打印,既没有数学诱导公式,也没有流程图,若果哪位不幸汇编初学者刚好看中买下,那注定了他这一生会恐惧并放弃汇编程序。
这种书不出还好,流通到市场上就是害人。

使用特权

评论回复
8
xuyiyi|  楼主 | 2010-8-14 17:54 | 只看该作者
飞船大仙 啥时和匠人一样,也出本书,计划今年还是明年?

不管啥书,俺一定买本收藏。支持一下!

使用特权

评论回复
9
123jj| | 2010-8-15 09:01 | 只看该作者
以下内容摘自网上 highgear大师的**,写的非常整齐规范,思路清晰,是数制转换原理最经典的范例,供有心者学习时参考。

-----------------------------------------------------------------------------------------------------------------

转换原理以及 C 演示代码, 很容易转到汇编。

The Basic Idea
To do the conversion faster, what we'll do is look at our binary number as a base 16 number and then do the conversion in terms of the base 16 digits. Consider a 16 bit number n. This can be broken into 4 fields of 4 bits each, the base 16 digits; call them n3, n2, n1 and n0.

                    n
    |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
    |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
    |   n   |   n   |   n   |   n   |
         3       2       1       0

The value of the number can be expressed in terms of these 4 fields as follows:

n = 4096 n3 + 256 n2 + 16 n1 + 1 n0

In the same way, if the value of n, expressed in decimal, is d4d3d2d1d0, where each of d4, d3, d2, d1 and d0 are decimal digits, the value of n can be expressed as:

n = 10000 d4 + 1000 d3 + 100 d2 + 10 d1 + 1 d0

Our problem then, is to compute the di from the ni without dealing directly with the larger number n.

To do this, we first note that the factors used in combining the values of ni can themselves be expressed as sums of multiples of powers of 10. Therefore, we can rewrite the original expression as:

n =
  n3( 4×1000 + 0×100 + 9×10 + 6×1 ) +
  n2( 2×100 + 5×10 + 6×1 ) +
  n1( 1×10 + 6×1 ) +
  n0( 1×1 )

If distribute the ni over the expressions for each factor, then factor out the multiples of 100, we get the following:

n =
  1000 (4n3) +
  100 (0n3 + 2n2) +
  10 (9n3 + 5n2 + 1n1) +
  1 (6n3 + 6n2 + 6n1 + 1n0)

We can use this to arrive at first approximations ai for d3 through d0:

a3 = 4 n3
a2 = 0 n3 + 2 n2
a1 = 9 n3 + 5 n2 + 1 n1
a0 = 6 n3 + 6 n2 + 6 n1 + 1 n0

The values of ai are not proper decimal digits because they are not properly bounded in the range 0 < ai < 9. Instead, given that each of ni is bounded in the range 0 < ni < 15, the ai are bounded as follows:

0 < a3 < 60
0 < a2 < 30
0 < a1 < 225
0 < a0 < 285

This is actually quite promising because a3 through a1 are less than 256 and may therefore be computed using an 8 bit ALU, and even a0 may be computed in 8 bits if we can use the carry-out bit of the ALU to hold the high bit. Furthermore, if our interest is 2's complement arithmetic where the high bit is the sign bit, the first step in the output process is to print a minus sign and then negate, so the constraint on n3 becomes 0 < n3 < 8 and we can conclude naively that

0 < a0 < 243

Note that we said n3 < 8 and not n3 < 8; this is because of the one negative number in the 2's complement system that cannot be properly negated, -32768. If we exclude this number from the range of legal values, the upper bound is reduced to 237; in fact, this is the overall upper bound, because in the one case where n3 is 8, all of the other ni are zero, so we can assert globally that

0 < a0 < 237

Even with our naive bound, however, it is easy to see that we can safely use 8 bit arithmetic to accumulate all of the ai.

Given that we have computed the ai, we can push them into the correct ranges by a series of 8-bit divisions and one 9-bit division, as follows:

c1 = a0 / 10
d0 = a0 mod 10

c2 = (a1 + c1) / 10
d1 = (a1 + c1) mod 10

c3 = (a2 + c2) / 10
d2 = (a2 + c2) mod 10

c4 = (a3 + c3) / 10
d3 = (a3 + c3) mod 10

d4 = c4

In the above, the ci terms represent carries propagated from one digit position to the next. The upper bounds on each of the ci can be computed from the bounds given above for the ai:

c1 < 28 [ = 285 / 10 ]
c2 < 25 [ = (28 + 225) / 10 = 253 / 10 ]
c3 < 5 [ = (25 + 30) / 10 = 55 / 10 ]
c4 < 6 [ = (5 + 60) / 10 = 65 / 10 ]

In computing the bound on c2, we came within 2 of to 255, the maximum that can be represented in 8 bits, so an 8 bit ALU is just barely sufficient for this computation. Again, if we negate any negative numbers prior to output, so that the maximum value of n3 is 8, the bound on c1 becomes 23 instead of 28.

有 8-bit 硬件除法
void putdec( uint16_t n )
    {
        uint8_t d4, d3, d2, d1, q;
        uint16_t d0;

        d0 = n       & 0xF;
        d1 = (n>>4)  & 0xF;
        d2 = (n>>8)  & 0xF;
        d3 = (n>>12) & 0xF;

        d0 = 6*(d3 + d2 + d1) + d0;
        q = d0 / 10;
        d0 = d0 % 10;

        d1 = q + 9*d3 + 5*d2 + d1;
        q = d1 / 10;
        d1 = d1 % 10;

        d2 = q + 2*d2;
        q = d2 / 10;
        d2 = d2 % 10;

        d3 = q + 4*d3;
        q = d3 / 10;
        d3 = d3 % 10;

        d4 = q;

        putchar( d4 + '0' );
        putchar( d3 + '0' );
        putchar( d2 + '0' );
        putchar( d1 + '0' );
        putchar( d0 + '0' );
    }

有 8-bit 硬件乘法:
    void putdec( int16_t n )
    {
        uint8_t d4, d3, d2, d1, d0, q;

        if (n < 0) {
            putchar( '-' );
            n = -n;
        }

        d1 = (n>>4)  & 0xF;
        d2 = (n>>8)  & 0xF;
        d3 = (n>>12) & 0xF;

        d0 = 6*(d3 + d2 + d1) + (n & 0xF);
        q = (d0 * 0xCD) >> 11;
        d0 = d0 - 10*q;

        d1 = q + 9*d3 + 5*d2 + d1;
        q = (d1 * 0xCD) >> 11;
        d1 = d1 - 10*q;

        d2 = q + 2*d2;
        q = (d2 * 0x1A) >> 8;
        d2 = d2 - 10*q;

        d3 = q + 4*d3;
        d4 = (d3 * 0x1A) >> 8;
        d3 = d3 - 10*d4;

        putchar( d4 + '0' );
        putchar( d3 + '0' );
        putchar( d2 + '0' );
        putchar( d1 + '0' );
        putchar( d0 + '0' );
    }

使用特权

评论回复
10
highgear| | 2010-8-24 23:47 | 只看该作者
声明:
以上内容不是我写的, 是我摘录 Douglas W. Jones 的**。原文在此:
http://www.cs.uiowa.edu/~jones/bcd/decimal.html#basic

这个原理似乎最早由一个印度人提出来的。

使用特权

评论回复
11
xuyiyi|  楼主 | 2010-8-25 07:04 | 只看该作者
印度人聪明,其软件水平世界一流,这是公认的。

使用特权

评论回复
12
宇宙飞船| | 2010-8-25 11:06 | 只看该作者
11楼 对印度的软件业一知半解!
印度的软件管理,是禁止使用指针,提倡用巨大数组写程序,因此虽然程序BUG少,维护管理方便,但是RAM开销大,执行速度慢,这是印度人程序的通病。在PC上执行倒不打紧,放在单片机上或嵌入式产品系统中应用,那就是垃圾。

使用特权

评论回复
13
粉丝| | 2010-8-25 12:01 | 只看该作者
没有实力就来装逼!11楼 一下子就被截穿了!
//luan3703发表于 2010-8-25 11:50
//33楼:
//这年头流行装逼啊。

使用特权

评论回复
14
xuyiyi|  楼主 | 2010-8-26 08:12 | 只看该作者
这年头流行装逼啊。
粉丝 发表于 2010-8-25 12:01



粉丝正解,这年头流行装逼。。。

使用特权

评论回复
15
宇宙飞船| | 2010-8-26 19:10 | 只看该作者
高手过招,实力不足,马脚尽露。

使用特权

评论回复
16
xuyiyi|  楼主 | 2010-8-27 09:35 | 只看该作者
呵呵!

刚才从二姨家左右两大护法处学到“民科”一词,

俺觉得,用在飞船、粉丝、潜艇身上最合适啦~~~    ;P

“民科”......... 中国的民间科学家,中国实行四个现在化的领路人。也是中国最后的希望之星 ---------飞船、粉丝、潜艇。


俺还有一点不明白,作为中国“民科”的领路人。
不搞自家的四个现在化,怎么老是抢人家美国人十几年前的东东当宝贝?

使用特权

评论回复
17
forsli| | 2013-12-7 18:21 | 只看该作者
正在下载解决问题,注册进来感谢一下

使用特权

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

本版积分规则

55

主题

2448

帖子

6

粉丝