Именно на асме 51 -- я когда-то в RU.EMBEDDED бросал "многоступенчатый" вариант вообще без умножений и делений (кстати, варинат "без умножения" ниже содержит взятие остатка '%', которое прожорливее по времени, чем умножение) (+)
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено ReAl 23 августа 2003 г. 16:57
В ответ на: Поделитесь плиз хорошим алгоритмом или кусочком кода функции типа IntToStr для C51 - на асм или Си отправлено Кулинар 23 августа 2003 г. 13:32

(С) ReAl 1997
Используёте как хотите, можете даже не ссылаться :-)
Одни сложения, сдвиги и маскирования/размаскирования.
Ниже использованы следующие макросы


_rlc macro dst
xch a,dst
rlc a
xch a,dst
endm

FUNC MACRO fname,used,attr
?PR?&fname SEGMENT CODE attr
RSEG ?PR?&fname
ENTRY fname,
ENDM

ENTRY MACRO fname,used
public fname
if not nul used
$RU fname used
endif
ENDM

;; table must be _after_ nxlat not more then (255-tablelen) bytes from
;; next after movc a,@a+PC location
;; IF NOT NUL maxlen
;; IF tbl-($+2+1)+(maxlen-1) > 255 ;; Повбивав би. Keil не вміє зробити
;; __error__ "nxlat range error" ;; (tbl-$), якщо tbl попереду.
;; ENDIF ;; а avocet вмів...
;; ENDIF
nxlat MACRO tbl
add a,#tbl-($+2+1)
movc a,@a+PC
ENDM

Подпрограммы, прототипы которых указаны


//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//
// FORMATTERS
void BlankSegs0(u8 idata * pb, u8 len);
void BlankAscii0(u8 idata * pb, u8 len);

void Unpack1(void idata * buf, u8 len);
void Unpack2(void idata * dst, u8 len, void idata * src);

u8 NibbleToSeg(u8); // convert one LOW nibble (masked inside)
void Nibbles2ascii(u8 idata * buf, u8 len);
void Nibbles2segs(u8 idata * buf, u8 len);

void Word2ubcd(void idata * dst, u8 len, u16 w);
void Word2ascii(void idata * dst, u8 len, u16 w);
void Word2segs(void idata * dst, u8 len, u16 w);

void Byte2ubcd(void idata * dst, u8 len, u8 b);
void Byte2ascii(void idata * dst, u8 len, u8 b);
void Byte2segs(void idata * dst, u8 len, u8 b);

void Ulong2ubcd(void idata * dst, u8 len, u32 idata * pb);
void Ulong2ascii(void idata * dst, u8 len, u32 idata * pb);
void Ulong2segs(void idata * dst, u8 len, u32 idata * pb);

void Bbb2ubcd(void idata * dst, u8 len, u8 idata * pb);
void Bbb2ascii(void idata * dst, u8 len, u8 idata * pb);
void Bbb2segs(void idata * dst, u8 len, u8 idata * pb);

- под вызов из С (кейл)
Сначала преобразуем число (u8; u16; bbb - это 3-байтовое поле из структуры, передаётся по адресу; u32)
в упакованную двоично-десятичную форму, потом распаковываем, потом преобразуем в сегменты или в
ASCII. Определения масок сегментов (SEGS_0, SEGS_1 и т.д. - в другом файле, берём по include чтобы не зависеть от индикатора).
Всё в сегменте inblock, чтобы вызовы-переходы между кусками модуля делать ajmp/acall.


?PR?FORMATTERS segment CODE INBLOCK
RSEG ?PR?FORMATTERS

; псує (a,B,c,R0-R4,R6)
cnvrtbcd:
; >* R2R3R4R1 hi..lo
; > R7->dst, R5=dstlen in digits
; >* R6=input bits
; * B -> dstend+1 (in bytes)
; * a,C,R0
mov R0,AR7
mov a,R5
add a,#1
rrc a ; len in bytes
L?clear:
mov @R0,#0
inc R0
djnz ACC,L?clear
mov B,R0 ; -> dstend+1
L?src:
_rlc R1
_rlc R4
_rlc R3
_rlc R2 ; shift src
mov R0,B
L?dst:
dec R0
mov a,@R0
addc a,@R0
da a
mov @R0,a
mov a,R0
xrl a,R7
jnz L?dst
djnz R6,L?src
ret


;;;;;;;;; WORD

ENTRY _word2ubcd,<(a,B,C,R0-R4,R6)>
_Word2ubcd:
; void word2ubcd( void idata *dst, u8 len, u16 w);
; > R7 -> dst
; R5 = len
; >* R2R3 = w
; * R6
; * B,R4,R1,R0 (in cnvrtbcd, unpack)
mov R6,#16 ; R4R1 don't care for 16 bit
w2u_1: ; was w2b1
acall cnvrtbcd ; R5 & R7 not changed
;;; _unpack1 ;(R7,R5), args not changed
ENTRY _unpack1,<(a,c,R0,R1,R3,R6)>
; unpack*
; src dst
; ab -> 0a,0b
; xa,bc -> 0a,0b,0c
; ab,cd -> 0a,0b,0c,0d
_Unpack1: ;;;;;;;;;;
; void unpack1( void idata *buf, u8 len);
; > R7 -> buf
; R5 = len
; * R3 used for 'src' pointer
; * R1,R0 work pointers
; * a,C,R6
mov R3,AR7 ; R3 ->src
ENTRY _unpack2,<(a,c,R0,R1,R6)>
_Unpack2:
; void unpack2( void idata *dst, u8 len, void idata *src)
; > R7 -> dst (unpacked BCD)
; R5 = len
; R3 -> src (packed BCD)
; * R1,R0 work pointers
; * a,C,R6
mov a,R5
mov R6,a ; save counter in R5 for nibble2ascii
add a,R7
mov R1,a ; R1 -> end_of_DST + 1
mov a,R5
add a,#1
rrc a
add a,R3
mov R0,a ; R0 -> end_of_src + 1
unp_1: ; LO nibble
dec R0
mov a,@R0
anl a,#0x0F
dec R1
mov @R1,a
djnz R6,$+2+1
ret
; HI nibble
mov a,@R0
swap a
anl a,#0x0F
dec R1
mov @R1,a
djnz R6,unp_1
ret


;;;;;;;;; BYTE

ENTRY _byte2ubcd,<(a,B,C,R0-R4,R6)>
_Byte2ubcd:
; void byte2ubcd( void idata *dst, u8 len, u8 b);
; > R7 -> dst
; R5 = len
; >* R3 = b
; * R6,R2
; * B,R4,R1,R0 (in cnvrtbcd, unpack)
mov R2,AR3
mov R6,#8 ; R3R4R1 don't care
ajmp w2u_1


ENTRY _Byte2ascii,<(a,B,C,R0-R6)>
_Byte2ascii:
; void byte2ascii( void idata *dst, u8 len, u8 b);
acall _Byte2ubcd ; R7,R5 not changed by unpack1
ajmp _Nibbles2ascii ; (R7,R5)

ENTRY _byte2segs,<(a,B,C,R0-R6)>
_Byte2segs:
acall _byte2ubcd
ajmp _Nibbles2segs


;;;;;;;;; ULONG

ENTRY _Ulong2ubcd,<(a,B,C,R0-R4,R6)>
_Ulong2ubcd:
; void ulong2ubcd( void idata *dst, u8 len, u32 idata *pb);
; > R7 -> buf
; R5 = len, R3->ulong
mov R6,#32
Ulong2u1:
mov R0,AR3
mov AR2,@R0
inc R0
mov AR3,@R0
inc R0
mov AR4,@R0
inc R0
mov AR1,@R0
ajmp w2u_1


ENTRY _Ulong2ascii,<(a,B,C,R0-R6)>
_Ulong2ascii: ;;;;;;;;;;;;;;;
; void ulong2ascii( void idata *dst, u8 len, u32 idata *pb);
acall _ulong2ubcd
ajmp _Nibbles2ascii


ENTRY _Ulong2segs,<(a,B,C,R0-R6)>
_Ulong2segs: ;;;;;;;;;;;;;;;
; void ulong2ascii( void idata *dst, u8 len, u32 idata *pb);
acall _Ulong2ubcd
ajmp _Nibbles2segs

;;;;;;;;; BBB - 24-bits numbers (3 bytes)

ENTRY _Bbb2ubcd,<(a,B,C,R0-R4,R6)>
_Bbb2ubcd:
; void bbb2ubcd( void idata *dst, u8 len, u8 idata *pb);
; R5 = len, R7->bbb
mov R6,#24
sjmp Ulong2u1 ; R1 will be loaded but don't care for 24 bit


ENTRY _Bbb2ascii,<(a,B,C,R0-R6)>
_Bbb2ascii: ;;;;;;;;;;;;;;;
; void bbb2ascii( void idata *dst, u8 len, u8 idata *pb);
acall _Bbb2ubcd
ajmp _Nibbles2ascii


ENTRY _Bbb2segs,<(a,B,C,R0-R6)>
_Bbb2segs: ;;;;;;;;;;;;;;;
; void Bbb2segs( void idata *dst, u8 len, u8 idata *pb);
acall _Bbb2ubcd
ajmp _Nibbles2segs


ENTRY _Word2ascii,<(a,B,C,R0-R6)>
_Word2ascii:
; void word2ascii( void idata *dst, u8 len, u16 w);
; > R7 -> dst
; >* R5 = len (destroyed in 2ascii)
; >* R2R3 = w
; * B
; used in cnvrtbcd, _unpack1
acall _Word2ubcd ; R7,R5 not changed
;;; ajmp _Nibbles2ascii
ENTRY _Nibbles2ascii,<(a,c,R0,R5)>
_Nibbles2ascii: ;;;;;;;;;;;;;;;
; void nibble2ascii( u8 idata *buf, u8 len);
; > R7 -> buf
; >* R5 = len
; * R0,a,C
mov R0,AR7
n2a_1:
mov a,@R0
add a,#0x90
da a
addc a,#0x40
da a
mov @R0,a
inc R0
djnz R5,n2a_1
ret


ENTRY _Word2segs,<(a,B,C,R0-R6)>
_Word2segs:
acall _Word2ubcd
;;; ajmp _Nibbles2segs
ENTRY _Nibbles2segs,<(a,c,R0,R5)>
_Nibbles2segs: ;;;;;;;;;;;;;;;
; void nibble2segs( u8 idata *buf, u8 len);
; > R7 -> buf
; >* R5 = len
; * R0,a,C
mov R0,AR7
n2s_1:
mov a,@R0
nxlat n2s_table
mov @R0,a
inc R0
djnz R5,n2s_1
ret

ENTRY _NibbleToSeg,<(a,C,R7)>
; u8 NibbleToSeg(u8);
_NibbleToSeg:
mov a,R7
anl a,#0x0F
nxlat n2s_table
mov R7,a
ret
n2s_table:
db SEGS_0,SEGS_1,SEGS_2,SEGS_3,SEGS_4,SEGS_5
db SEGS_6,SEGS_7,SEGS_8,SEGS_9,SEGS_A,SEGS_b
db SEGS_C,SEGS_d,SEGS_E,SEGS_F

Вот так. А то делить, понимашли... Это же долго и по коду реально не короче :-)

Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru