from Tony Kübek tony.kubek at flintab.com
...it's for 24 bit signed variable, then I cannot output a variable at a time ( supposed to go inside an int handler ), therefore I'm using a 9 byte string to store the result, furthermore for the decimal point and supressing of leading zeroes I needed 1 byte and 2 bit variables. ... Its a bit of 'bloatware', requires about 290 ! instructions but thats efficient enough for me, I might get back to hammer on it when I've finished off the other bits I'm starting with now. I think it goes around 480 instruction executed worst case, and all the way down to 250 something for best case. Also I added a minor conditional that makes execution a tad faster for 20 bit numbers ( as my app will have about 99 % in this range ) to the expence of more code and additional execution for larger numbers.
;********************************************************************** ; This file is a basic code template for assembly code generation * ; on the PICmicro PIC16F877. This file contains the basic code * ; building blocks to build upon. * ; * ; If interrupts are not used all code presented between the ORG * ; 0x004 directive and the label main can be removed. In addition * ; the variable assignments for 'w_temp' and 'status_temp' can * ; be removed. * ; * ; Refer to the MPASM User's Guide for additional information on * ; features of the assembler (Document DS33014). * ; * ; Refer to the respective PICmicro data sheet for additional * ; information on the instruction set. * ; * ; Template file assembled with MPLAB V4.00 and MPASM V2.20.00. * ; * ;********************************************************************** ; * ; Filename: MathTest.asm 24bit signed binary->ASCII w. dp * ; Date: 2000-03-31 * ; File Version: 0.1B * ; * ; Author: Tony Kübek * ; Company: * ; * ; * ;********************************************************************** ; * ; Files required: * ; * ; * ; * ;********************************************************************** ; * ; Notes: Tests of binary to ASCII coversion * ; Routines from techref.massmind.org * ; Originators(16bit): Scott Dattalo and Nikolai Golovchenko* ; Routine takes 24 bit signed binary number and coverts to * ; 8/9 byte ASCII(true!) decimal string with decimal point * ; and minus sign as the first byte ( if negative ). * ; 24 bit variabel is stored in last three string bytes * ; These are 'destroyed' during processing * ; Leading zeroes are surpressed (conv. to space) * ; Resources needed: * ; DpPlacement 1 byte + 1 bit * ; PrevIsChar 1 bit ,prev. zero was surpressed* ; ASCII string of 9 bytes * ;********************************************************************** list p=16f877 ; list directive to define processor #include <p16f877.inc> ; processor specific variable definitions __CONFIG _CP_OFF & _WDT_ON & _BODEN_ON & _PWRTE_ON & _RC_OSC & _WRT_ENABLE_ON & _LVP_OFF& _DEBUG_OFF & _CPD_OFF ; '__CONFIG' directive is used to embed configuration data within .asm file. ; The lables following the directive are located in the respective .inc file. ; See respective data sheet for additional information on configuration word. #define TEST_SMALL_NUMBER ; if defined then tests are performed ; to see number is less than +/-1048575 ( 20 bit ) ; makes routine a little faster for thoose numbers ; to the expence of more code ; and adds some cycles to all numbers above if used ; but can deduct upto 62 cycles on smaller numbers #define DECIMAL_POINT 0x2E ; '.' #define BYTE_OFFSET 0x30 ; start decimal ASCII numbers #define SIGN_NEGATIVE 0x2D ; '-' ;***** VARIABLE DEFINITIONS CBLOCK 0x20 ; start userram bank 0 BitVars:1 ; used for dp-bit variable OutPut:9 ; 8 used if no dp, else 9 DpPlacement:1 ; where to put dp, counted from start, min=1 ; note an added bonus here ! as this var is ; located directly after the string and will ; 'always' be = 0x00(after conversion), ; you have an 'free' null terminator ENDC w_temp EQU 0x70 ; variable used for context saving status_temp EQU 0x71 ; variable used for context saving #define _DpUsed BitVars,0 ; decimal point has been placed #define _PrevIsSpace BitVars,1 ; previous byte/digit is 'converted' to space #define Sample OutPut+6 ; Note !! to save ram, 24 bit variable is stored ; in highest three byte in 9 byte string ;********************************************************************** ORG 0x000 ; processor reset vector clrf PCLATH ; ensure page bits are cleared goto MAIN ; go to beginning of program ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register ; isr code can go here or be located as a call subroutine elsewhere movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie ; return from interrupt MAIN ;************************ Tony test 24 bit->8/9 digit ASCII with decimal point ; code with TEST_SMALL_NUMBER: (about)290 instructions ( excluding variable setup code ) ; ; True ASCII conversion, variable decimalpoint, surpress leading zeroes ; 24 bit variable is handled as SIGNED! ;************************************ CLRF BitVars ; dp=1->dp=7(no dp), adds approx 50 cycles, i.e. dp=1 least cycles MOVLW 1 ; note dp = 1 = between first and second digit ; dp = 7 between the last and second last digit ; if dp >= 7, dp = 0 then last digit is = 0x00 MOVWF DpPlacement MOVLW BYTE_OFFSET ; preset with ASCII offset MOVWF OutPut MOVWF OutPut+1 MOVWF OutPut+2 MOVWF OutPut+3 MOVWF OutPut+4 MOVWF OutPut+5 BCF OutPut,4 ; clear bit, makes first char 'space' ; OutPut+6 - OutPut+8 will contain 24 bit sample, LSB in OutPut+8 ; ** NOTE ** Sample = OutPut+6, Sample+1 = OutPut+7, Sample+2 = OutPut+8 ; Sample is defined as a separate name as it makes the code easier to read ; test number : 1235783 = 0x12DB47 - ok ! cycles approx: 301 -350 depending on dp placment ; Note ! This with TEST_SMALL_NUMBER, without deduct 10 cycles ; MOVLW 0x47 ; MOVWF Sample+2 ; MOVLW 0xDB ; MOVWF Sample+1 ; MOVLW 0x12 ; MOVWF Sample ; test number : -1235783 = 0xED24B9 - ok ! cycles approx: 311 -360 depending on dp placment ; Note ! This with TEST_SMALL_NUMBER, without deduct 10 cycles ; MOVLW 0xB9 ; MOVWF Sample+2 ; MOVLW 0x24 ; MOVWF Sample+1 ; MOVLW 0xED ; MOVWF Sample ; test number : 60900 = 0x00EDE4 - ok ! cycles approx: 315 -371 depending on dp placment ; Note ! This with TEST_SMALL_NUMBER, without add 63 cycles ; MOVLW 0xE4 ; MOVWF Sample+2 ; MOVLW 0xED ; MOVWF Sample+1 ; MOVLW 0x00 ; MOVWF Sample ; test number : -60900 = 0xFF121C - ok ! cycles approx: 325 -381 depending on dp placment ; Note ! This with TEST_SMALL_NUMBER, without add 56 cycles ; MOVLW 0x1C ; MOVWF Sample+2 ; MOVLW 0x12 ; MOVWF Sample+1 ; MOVLW 0xFF ; MOVWF Sample ; test number : 231 = 0xE7 - ok !, cycles approx 244-302 depending on dp placement ; NOTE ! With TEST_SMALL_NUMBER, without add 62 cycles ; MOVLW 0xE7 ; MOVWF Sample+2 ; MOVLW 0x00 ; MOVWF Sample+1 ; MOVLW 0x00 ; MOVWF Sample ; test number : -1 = 0xFFFFFF - ok !, cycles approx:262-326 depending on dp placement ; This with TEST_SMALL_NUMBER, without add 62 cycles ; ; MOVLW 0xFF ; MOVWF Sample+2 ; MOVLW 0xFF ; MOVWF Sample+1 ; MOVLW 0xFF ; MOVWF Sample ; test number : 1048575 = 0x0FFFFF - ok !, cycles approx: 297-348 depending on dp placement ; this with TEST_SMALL_NUMBER, without add 8 cycles ; MOVLW 0xFF ; MOVWF Sample+2 ; MOVLW 0xFF ; MOVWF Sample+1 ; MOVLW 0x0F ; MOVWF Sample ; test number : 1000000 = 0x0F4240 - ok !, cycles approx: 291-350 depending on dp placement ; this with TEST_SMALL_NUMBER, without add 8 cycles ; MOVLW 0x40 ; MOVWF Sample+2 ; MOVLW 0x42 ; MOVWF Sample+1 ; MOVLW 0x0F ; MOVWF Sample ; test number : 8388607 = 0x7FFFFF - ok !, cycles approx: 394-445 depending on dp placement ; this with TEST_SMALL_NUMBER, without add 8 cycles ; MOVLW 0xFF ; MOVWF Sample+2 ; MOVLW 0xFF ; MOVWF Sample+1 ; MOVLW 0x7F ; MOVWF Sample ; test number : -7099999 = 0x93A9A1 - ok !, cycles approx:429-480 depending on dp placement ; this with TEST_SMALL_NUMBER, without add 8 cycles MOVLW 0xA1 MOVWF Sample+2 MOVLW 0xA9 MOVWF Sample+1 MOVLW 0x93 MOVWF Sample TEST_NEGATIVE BTFSS Sample,7 ; test if negative IFDEF TEST_SMALL_NUMBER GOTO TEST_TOPNIBBLE ; nope ELSE GOTO SUB4M ; nope ENDIF ; sample is negative ; make two's complement COMF Sample+2,F COMF Sample+1,F COMF Sample,F MOVLW 1 ADDWF Sample+2,F SKPNC ADDWF Sample+1,F SKPNC ADDWF Sample,F MOVLW SIGN_NEGATIVE MOVWF OutPut ; first digit minus sign IFDEF TEST_SMALL_NUMBER ; test for small numbers and skips some loops ; use if number is often in 0-1048575 range ( negative or not) ; i.e. 0x000000 - 0x0FFFFF ( 2.5 bytes 20 bits ) TEST_TOPNIBBLE ; test if top nibble is zero, i.e. number less than 1048575 ( decimal ) ; if so we can skip to sub300k routine MOVF Sample,w ANDLW 0x70 ; Mask out top three bits BNZ SUB4M ; nope do full conversion ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF OutPut+1,4 GOTO SUB300k ; continue ENDIF ; TEST_SMALL_NUMBER SUB4M: ; subtract 4 million from sample MOVLW 4 ADDWF OutPut+1, f MOVLW low(4000000) SUBWF Sample+2, f MOVLW low(4000000>>8) SKPC MOVLW low(4000000>>8)+1 SUBWF Sample+1, f MOVLW low(4000000>>16) SKPC MOVLW low(4000000>>16) + 1 SUBWF Sample, f SKPNC ; overflow, i.e. negative GOTO SUB4M ADD1M: ; add 1 million to sample DECF OutPut+1, f MOVLW low(1000000) ADDWF Sample+2, f MOVLW low(1000000>>8) SKPNC MOVLW low(1000000>>8) + 1 ADDWF Sample+1, f MOVLW low(1000000>>16) SKPNC MOVLW low(1000000>>16) + 1 ADDWF Sample, f SKPC ; done ? GOTO ADD1M ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF OutPut+1,w BNZ SUB300k ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF OutPut+1,4 SUB300k: ; substract 300 thousand from sample MOVLW 3 ADDWF OutPut+3, f MOVLW low(300000) SUBWF Sample+2, f MOVLW low(300000>>8) SKPC MOVLW low(300000>>8)+1 SUBWF Sample+1, f MOVLW low(300000>>16) SKPC MOVLW low(300000>>16) + 1 SUBWF Sample, f SKPNC GOTO SUB300k ADD100k ; add 100 thousand to sample DECF OutPut+3, f MOVLW low(100000) ADDWF Sample+2, f MOVLW low(100000>>8) SKPNC MOVLW low(100000>>8) + 1 ADDWF Sample+1, f MOVLW low(100000>>16) SKPNC MOVLW low(100000>>16) + 1 ADDWF Sample, f SKPC ; done GOTO ADD100k IFDEF TEST_SMALL_NUMBER ; if this test enabled it is possible ; to have an overflow here ; test for overflow ( Output+3 = 10 ) MOVLW BYTE_OFFSET+0x0A SUBWF OutPut+3,W BTFSS STATUS,Z ; test if non zero GOTO ADD100k_TstDp ; over flow, result is = 10, second digit = 1, third = 0 MOVLW BYTE_OFFSET MOVWF OutPut+3 BTFSS _DpUsed ; test if dp already used BSF OutPut+1,0 ; if no dp used set this digit to one BSF OutPut+2,0 ; set also third digit to 1 ( in case dp is used ) ; restore previous digit BTFSS _PrevIsSpace GOTO ADD100k_TstDp BSF OutPut+1,4 BCF _PrevIsSpace ENDIF ADD100k_TstDp: ; test for dp DECFSZ DpPlacement,F ; test for dp placement GOTO ADD100k_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF OutPut+2 ; dp is third digit ; restore zero before dp BTFSC _PrevIsSpace BSF OutPut+1,4 GOTO SUB30k ; continue ADD100k_NoDp: ; no dp copy back number MOVF OutPut+3,W MOVWF OutPut+2 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF OutPut+2,w BTFSS STATUS,Z BCF _PrevIsSpace BNZ SUB30k BTFSS _PrevIsSpace GOTO SUB30k ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF OutPut+2,4 SUB30k: ; subtract 30'000 from sample MOVLW 3 ADDWF OutPut+4, f MOVLW low(30000) SUBWF Sample+2, f MOVLW low(30000>>8) SKPC MOVLW low(30000>>8)+1 SUBWF Sample+1, f MOVLW low(30000>>16) SKPC MOVLW low(30000>>16) + 1 SUBWF Sample, f SKPNC ; negative ? GOTO SUB30k ADD10k: ; add 10'000 to sample DECF OutPut+4, f MOVLW low(10000) ADDWF Sample+2, f MOVLW low(10000>>8) SKPNC MOVLW low(10000>>8) + 1 ADDWF Sample+1, f MOVLW low(10000>>16) SKPNC MOVLW low(10000>>16) + 1 ADDWF Sample, f SKPC ; done ? GOTO ADD10k BTFSC _DpUsed GOTO SUB3k ; dp is already used continue ; test for dp DECFSZ DpPlacement,F ; test for dp placement GOTO ADD10k_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF OutPut+3 ; dp is fourth digit ; restore zero before dp BTFSS _PrevIsSpace BSF OutPut+2,4 GOTO SUB3k ; continue ADD10k_NoDp: ; no dp copy back number MOVF OutPut+4,W MOVWF OutPut+3 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF OutPut+3,w BTFSS STATUS,Z BCF _PrevIsSpace BNZ SUB3k BTFSS _PrevIsSpace GOTO SUB3k ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF OutPut+3,4 SUB3k: ; subtract 3000 from sample MOVLW 3 ADDWF OutPut+5, f MOVLW low(3000) SUBWF Sample+2, f MOVLW low(3000>>8) SKPC MOVLW low(3000>>8)+1 SUBWF Sample+1, f SKPNC ; negative ? GOTO SUB3k ADD1k: ; add 1000 to sample DECF OutPut+5, f MOVLW low(1000) ADDWF Sample+2, f MOVLW low(1000>>8) SKPNC MOVLW low(1000>>8) + 1 ADDWF Sample+1, f SKPC GOTO ADD1k BTFSC _DpUsed GOTO SUB300_PreLoad ; dp is already used continue ; test for dp DECFSZ DpPlacement,F ; test for dp placement GOTO ADD1k_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF OutPut+4 ; dp is fifth digit ; restore zero before dp BTFSC _PrevIsSpace BSF OutPut+3,4 GOTO SUB300_PreLoad ; continue ADD1k_NoDp: ; no dp copy back number MOVF OutPut+5,W MOVWF OutPut+4 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF OutPut+4,w BTFSS STATUS,Z BCF _PrevIsSpace BNZ SUB300_PreLoad BTFSS _PrevIsSpace GOTO SUB300_PreLoad ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF OutPut+4,4 SUB300_PreLoad MOVLW BYTE_OFFSET MOVWF OutPut+6 SUB300: ; subtract 300 from sample MOVLW 3 ADDWF OutPut+6, f MOVLW low(300) SUBWF Sample+2, f MOVLW low(300>>8) SKPC MOVLW low(300>>8)+1 SUBWF Sample+1, f SKPNC ; negative ? GOTO SUB300 MOVLW 100 ADD100: ; add 100 to sample DECF OutPut+6, f ADDWF Sample+2, f SKPC GOTO ADD100 INCF Sample+1, f BTFSC Sample+1, 7 GOTO ADD100 BTFSC _DpUsed GOTO SUB30_PreLoad ; dp is already used continue ; test for dp DECFSZ DpPlacement,F ; test for dp placement GOTO ADD100_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF OutPut+5 ; dp is sixth digit ; restore zero before dp BTFSC _PrevIsSpace BSF OutPut+4,4 GOTO SUB30_PreLoad ; continue ADD100_NoDp: ; no dp copy back number MOVF OutPut+6,W MOVWF OutPut+5 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF OutPut+5,w BTFSS STATUS,Z BCF _PrevIsSpace BNZ SUB30_PreLoad BTFSS _PrevIsSpace GOTO SUB30_PreLoad ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF OutPut+5,4 SUB30_PreLoad: MOVLW 30 SUB30: ; subtract 30 from sample INCF OutPut+7, f SUBWF Sample+2, f SKPNC GOTO SUB30 MOVFW OutPut+7 RLF OutPut+7, f ADDWF OutPut+7, f MOVLW 10 ADD10: ; add 10 to sample DECF OutPut+7, f ADDWF Sample+2, f SKPC GOTO ADD10 MOVLW BYTE_OFFSET ADDWF OutPut+7,f BTFSC _DpUsed GOTO LAST_DIGIT ; dp is already used continue ; test for dp DECFSZ DpPlacement,F ; test for dp placement GOTO ADD10_NoDp ; no dp yet ; place dp BSF _DpUsed ; dp is used MOVLW DECIMAL_POINT ; MOVWF OutPut+6 ; dp is seventh digit ; restore zero before dp BTFSC _PrevIsSpace BSF OutPut+5,4 GOTO LAST_DIGIT ; continue ADD10_NoDp ; no dp copy back number MOVF OutPut+7,W MOVWF OutPut+6 ; test for leading zeroes MOVLW BYTE_OFFSET SUBWF OutPut+6,w BNZ LAST_DIGIT BTFSS _PrevIsSpace GOTO LAST_DIGIT ; this digit is zero, and dp is not yet set ; then downshift to space BSF _PrevIsSpace BCF OutPut+6,4 LAST_DIGIT: MOVLW BYTE_OFFSET ADDWF Sample+2,w MOVWF Sample+2 BTFSS _DpUsed MOVWF OutPut+7 ; save in previous byte BTFSC _DpUsed GOTO END_CONV DECFSZ DpPlacement,F ; test for dp placement GOTO CLEAR_LAST ; no dp used at all ?? MOVLW DECIMAL_POINT ; MOVWF OutPut+7 ; dp is eigth digit ; restore zero before dp BTFSC _PrevIsSpace BSF OutPut+6,4 GOTO END_CONV CLEAR_LAST: ; no dp used copy back number, and clear last digit BTFSS _DpUsed CLRF OutPut+8 ; clear last digit no dp used END_CONV NOP ; done :-) GOTO MAIN END ; directive 'end of program'
Comments:
file: /Techref/microchip/math/radix/b2a-24b9d-lzmsdp-tk.htm, 20KB, , updated: 2003/12/16 11:03, local time: 2024/12/25 21:10,
52.15.109.209:LOG IN
|
©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/microchip/math/radix/b2a-24b9d-lzmsdp-tk.htm"> PIC Microcontoller Radix Math Method </A> |
Did you find what you needed? |