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.
Code:
;---------------------------------------
; 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 )
;---------------------------------------
_trap15_F:
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
ConvLoop:
even
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
JobDone:
even
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
;----
NumbIsZero:
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
;----
InvalidDiv:
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 )
RTE
;----
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.
Again:
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
done:
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.
ClearMore:
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