hex to number in any base...
Page 1 of 1

Author:  Span [ Sat Nov 17, 2018 9:33 am ]
Post subject:  hex to number in any base...

Hi all,
I am a tad confused,

I am slowly implementing the easy68k traps in my bios rom mostly as a learning aid.
I have just done the trap print a hex number in any base using the divide and conquer method
To test it i call it 4 times and ask it to display the number 0x1234 1st as decimal then octal then hex and finally binary
( tests chosen as there the bases supported by my on screen calculator )
i get the correct result for decimal/octal and binary but the wrong result for hex!
So the question is have i mucked it up or is this method not able to display the result in the same base as the source number ?

Posted the code below , Without doubt there will be possible improvments that could be made
but i am pleased that it seems to be okay for any base but hex which has me baffled.
below the code i have cut and pasted the result after calling in assorted bases.

; 15   ; Display the unsigned number in D1 converted to number base (2 through 36) contained in D2
;   For example, to display D1 in base16 put 16 in D2.B
;    Values of D2 outside the range 2 to 36 inclusive are ignored.
;   Note only good for values up to FFFF ( word size )
   even            ; Ensure compiler places entry point word alignment
               ; D2 = divisor ( number base )
               ; D1 = number to convert.
   cmp   #$0,D1         ; compare target with zero
   beq   NumbIsZero      ; Bail out.
   cmp   #$2,D2         ; Compare D2 ( divisor ) with 2
   blo   InvalidDiv      ; if divisor is less than 2 it's stupid ( 2 for basic binary )

               ; if we get here we have at least somethiong to do
               ; Start by clearing the buffer space.
   jsr   ClearWorkBuff      ; clears 1024 bytes
   lea   WorkBuff,A1      ; Move pointer back to start of now cleared and nulled buffer buffer.
   ; Okay cleared a buffer, Sanity checked inputs D2 = divisor, D1 = number to convert.
   ; Now convert hex number to

   move.l   #$0,D0         ; Clear D0
   move.l   #$0,D3         ; Clear D3
   move.l   #$0,D4         ; Clear D4

   divu.w   D2,D1         ; Divide D1 by the divisor(D2)--> D1 now contains lowword=quotent, highword remainder
   move.w   D1,D4         ; D3 now holds the Quotent
   swap   D1         ; Swap remainder into low word
   move.w   D1,D3         ; D4 now holds the remainder.
   move.l   #$0,D1         ; D1 = empty, D4 = remainder, D3 = quotent, D2 divisor
   move.l   D3, D0         ; copy D3 to D0

   lea   msgTable,A2
   add.l   D0, A2         ; add the offset
   move.b   (A2),D0         ;
   move.b   D0,(A1)+      ; save to buffer.

   move.w   D4,D1         ;
   cmp.w   #$0,D1         ; is remainder is 0 then were done.
   beq   JobDone         ; bail out were all done.
   bra   ConvLoop      ; else go round again

   lea   WorkBuff,A1
   ; We should now have the result in buffer BUT
   ; The string is reversed in the buffer.
   bra   ReverseString      ; This actually prints the string to screen in reverse.

   MOVEM.L (A7)+,D0-D7/A0-A6    ; POP ALL REGISTERS ( saved in base trap ) ( 14 )
   RTE            ; Return from exception

   move.b   #'0',(A1)+
   move.b   #$0,(A1)
   MOVEM.L (A7)+,D0-D7/A0-A6    ; POP ALL REGISTERS ( saved in base trap ) ( 14 )
   RTE            ; Return from exception
   lea   msgDivError,A0      ; CR,LF,'Invalid Divisor must be in the range 2 - 36',CR,LF,0
   jsr   PrintString      ; Print error message and return.
   MOVEM.L (A7)+,D0-D7/A0-A6    ; POP ALL REGISTERS ( saved in base trap ) ( 15 )

ReverseString:            ; Assumes the string is at WorkBuff and is
   lea   WorkBuff,A1      ; in reverse order
   move.l   A1,A2         ; make a copy
   jsr   GetStrLength      ; Checks length of string pointed to by A1 len is returned in D2 includes null
   sub.b   #$1,D2         ; Ignore the null byte
   add.l   D2,A1         ; make A1 point at end of string.
   move.b   (A1),D0         ; get char
   jsr   OutChar         ; print it
   sub.l   #$1,A1         ; move pointer back 1 char
   cmp.l   A1,A2         ; check if we have reached the start
   beq   done         ; do the end routine
   bra   Again         ; else do another char
   move.b   (A1),D0         ; get char
   jsr   OutChar         ; print it
   MOVEM.L (A7)+,D0-D7/A0-A6    ; POP ALL REGISTERS ( saved in base trap ) ( 14 )
   RTE            ; Return from exception

; Returns the length of an ascii string.
; On entry A1 points at start of string.
; On exit D2 holds the length of the -
; string including the terminating null.
; On exit only D2 is changed...
GetStrLength:            ;
   move.l   D0,-(A7)      ; Save D0
   move.l   A1,-(A7)      ; Save A1
   move.l   #$0,D2         ; Zero D2
Back:               ;
   move.b   (A1)+,D0      ; Get char from buffer.
   add   #$1,D2         ; add 1 to length.
   cmp.b   #$0,D0         ; Is it a NULL.
   beq   DoneIt         ; yes so return.
   bra   Back         ; No so return and do it again.
DoneIt:               ; Bail out routine.
   move.l   (A7)+,A1      ; Restore A1
   move.l   (A7)+,D0      ; Restore D0
   rts            ;   

; Clear the supervisors temp work buffer.
; 1024 bytes ( 0x400 ) cleared to null bytes.
; No registers changed.
ClearWorkBuff:            ;
   move.l   A0,-(A7)      ; save A0
   move.l   A1,-(A7)      ; save A1
   lea   WorkBuff,A0      ; Get address of work buffer.
   move.l   A0,A1         ; Copy start address to A1.
   add.l   #$400,A1      ; Add 400h or 1024 decimal.
   move.b   #$0,(A0)+      ; Save a null byte and bump ptr.
   cmpa.l   A0,A1         ; compare address start with end.
   beq   BuffDone      ; All done.
   bra   ClearMore      ; Do some more.
BuffDone:            ;
   move.l   (A7)+,A1      ; Restore A1
   move.l   (A7)+,A0      ; Restore A0
   rts            ; return whence we came.
(Admin: Added code tags.)
test results
About to ask for the number $1234 via trap 15 F thrice!
Once as a decimal number and once as an octal number and finaly a hex number
The result should be 4660, 11064, 1234, 1001000110100
Calling for decimal 1st and the result is >4660
Calling for octal 2nd and the result is >11064
Calling for hex last and the result is >15AA
Calling for hex last and the result is >1001000110100

Author:  profkelly [ Sun Nov 18, 2018 1:14 pm ]
Post subject:  Re: hex to number in any base...

A quick test reveals many assembly errors in the code.

Page 1 of 1 All times are UTC
Powered by phpBB® Forum Software © phpBB Group