;******************************************************************
; Convert 32-bit binary number in REGA into a bcd number
; at <bcd>. Uses Mike Keitz's procedure for handling bcd
; adjust; Modified Microchip AN526 for 32-bits.
b2bcd
btfss rega3,7 ;Check if egative
goto positive ; No
xorlw 0xff ; Yes, make positive
movwf rega3
movf rega2,W
xorlw 0xff
movwf rega2
movf rega1,W
xorlw 0xff
movwf rega1
movf rega0,W
xorlw 0xff
incf W
movwf rega0
movlw '-' ; and et sign
movwf sign
goto positive1
positive
movlw '+'
movwf sign
positive1
movlw .32 ; 32-bits
movwf mcount ; make cycle counter
clrf bcd ; clear result area
clrf bcd+1
clrf bcd+2
clrf bcd+3
clrf bcd+4
b2bcd2
movlw bcd ; make pointer
movwf fsr
movlw .5
movwf cnt
; Mike's routine:
b2bcd3 movlw 0x33
addwf indf,f ; add to both nybbles
btfsc indf,3 ; test if low result > 7
andlw 0xf0 ; low result >7 so take the 3 out
btfsc indf,7 ; test if high result > 7
andlw 0x0f ; high result > 7 so ok
subwf indf,f ; any results <= 7, subtract back
incf fsr,f ; point to next
decfsz cnt
goto b2bcd3
rlf rega0,f ; get another bit
rlf rega1,f
rlf rega2,f
rlf rega3,f
rlf bcd+4,f ; put it into bcd
rlf bcd+3,f
rlf bcd+2,f
rlf bcd+1,f
rlf bcd+0,f
decfsz mcount,f ; all done?
goto b2bcd2 ; no, loop
return ; yes
Noterade att raden "incf W" rör ett helt annat register, 0x55? wrwg är 00 före och efter instruktionen?? Vad katten är fel?
Den där första delen av koden är egendomlig. Först så var hämtas värdet som förutsätts finnas i W vid ingång ifrån?
Antar det är tänkt att föreställa en 2-komplement, men hur tusan skall det fungera utan att göra en riktig multibyte addition av 1 efter att ha vänt på bitarna? Eller rättare en multibyte increment som är lite enklare att göra.
incf W
är inte en giltig instruktion, det måste finnas ett register att ta värdet från.
Dessutom verkligt klumpig kod för att invertera, det som görs i 3 instruktioner kan göras i 1 efter att W laddats med 0xff.
Någonting är mycket fel, var kommer denna kod från?
I så fall är "INCF WREG" helt OK, W är mappat som en SFR på PIC18.
Väldigt användbart, eftersom alla instruktioner som på PIC16 bara
fungerar mot ett "file register", på PIC18 även fungerar direkt mot W...
Bara "W" ser dock lite lustigt ut, W (och F) brukar vara definierat som "1"
resp "0" (eller tvärtom, men det spelar ingen roll...)
Tänkte samma sak ett ögonblick, men som Du säger så heter det WREG då. Dessutom borde negf ha använs för 2-komplement följt av kod för att propagera carryn om det varit för en 18.
Fast koden är ju egendomlig så då går det inte att dra några slutsatser alls. Det är därför jag undrar varifrån den kommer, om det kan vara manipulerat för att någon vill "roa sig"...
Sorry, det var sent i går... PIC16. Koden kommer givetvis från PIClist: http://www.piclist.com/tecHREF/microchi ... 32b10d.htm
men med tillägg. Dvs för att förvandla negativt till positivt, genom att XORa alla med 0xFF och sedan öka med ett, men där blev det fel...
Nåväl, hela rasket var klippt från gammal kod, enklare att stryka hela rasket och helt sonika kalla "negatea" från Peter Helmsleys kod:
Vi var nog alla lite trötta i går och skrev lite blaj.
Anledningen till att ett helt annat register ändrades är att konstanten w=0, därför addreserades SFR 0, som är indirekt data, med följd att instruktionen opererade på det register dit FSR händelsevis råkade peka.
De två raderna efter nega1 i den nya koden är irrelevanta i sammanhanget, allt blir rätt även om -2G ger overflow.. Byt bara ut koden från goto positive fram till movlw '-' mot något som först vänder bitarna och sedan inkrementerar talet på ett korrekt sätt.
Lite långsammare, men alltid samma tid, och det blir ingen goto med tillhörande skräplabel. Kan vara väl så viktigt i en assembler med bara globala labels.
Där drar man helt enkelt talet ifrån noll. Skall det räknas mycket är det en stor fördel att välja 18, där det inte behövs en massa krångel för att propagera carry.
OK. Noterat. Skall leka litet med PIC18 senare då jag får detta projekt klart.
edit: Vad jag borde ha gjort är naturligtvis att kika i listfilen vad som eg genererades av den instruktionen, men det kom jag på först efter att ha sovit på saken.
29.6 Design Tips
Question 1: How can I modify the value of W directly? I want to decrement W.
Answer 1:
There are a few possibilities, two are:
1. For the midrange devices, there are several instructions that work with a literal and W.
For instance, if it were desired to decrement W, this can be done with an ADDLW 0xFF.