News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu

Z80 routine help

Started by kelp7, 11:51, 21 February 18

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

kelp7

Hi,


I was just wondering whether the following code could be made more compact or efficient:



PUSH DE
PUSH HL
LD HL,0D001H
LD D,2
LD A,B
LOOP1: AND 0FH
CP 0AH
JR C,ADDING
SUB 9
JR DISPCHAR
ADDING: ADD A,20H
DISPCHAR: LD (HL),A
DEC HL
LD A,B
RRA
RRA
RRA
RRA
DEC D
JR NZ,LOOP1
POP HL
POP DE



It's for my Sharp computer. It basically converts whatever hex number is in register 'B' before the routine is called and then displays each character using display codes into top-left of screen memory. (E.G. if B contains 3EH then '3E' is successfully printed to screen memory). Apologies for the non-Amstrad post. Just interested if anyone has a better take on that. The CP is just to determine whether 09H needs to be subtracted from A or whether 20H needs to be added to A to reach the correct display code.


Any help or tips greatly appreciated!


Edit : I should add a brief image of the display code table from my manual so it's easier to understand the adding / subtracting. I've just attached a snip of it.

gerald

#1
Here is what I use on CPC, with A containing the value to be displayed


DBG_puthex_A:
  push AF
  rrca
  rrca
  rrca
  rrca
  call DBG_puthex_base
  pop AF 
DBG_puthex_base:
  and #0x0F
  add #0x30  ; 0
  cp #0x3A
  jr C, puthex_AF
  add #0x07
puthex_AF:
  call _DisplayPutChar_asm
  ret


Loop is avoided by re-entering the function.
To adapt to you mapping,
- the 0 requires a add #0x20 instead of #0x30, cp #0x2A instead of #0x3A
- the adjustment for >9 be -9 (0xF7) instead of +7
- replace the call _DisplaPutChar_asm by the ld(hl), a and inc hl

andycadley


The classic way to convert the lower nibble of A into an ASCII hex code is:

and  15
add  a,90h
daa
adc  a,40h
daa



Extending that to multiple digits is a (relatively) trivial task.

kelp7

andycadley : Thanks but I'm looking really for display code instead of ASCII


gerald : That's excellent, thanks for that. The reason I need a loop is because this bit of code is not in a good place to jump in and out of. I'm writing a fast (or 'turbo') loader for tape for my machine and want to print Most Significant Byte on the screen for how many bytes are left before finishing loading. It seemed as if whenever I used the simple kernel 'print hex' subroutine the file would be corrupted when loading back in, the less time my print routine takes the less corruption. I'm printing to the screen straight after writing every byte to tape and same when loading back in (printing to screen after every byte read). It seems though.... after some more testing tonight.... even the slightest delay (I just did a simple LD ($D000),BC to put BC into screen memory) would cause corruption when loading file back in. I think I just need to re-think where to put my printing code. I would have thought that there would be no problem if size of printing routine was the same for both write-to-tape and read-from-tape but obviously it's not as simple as that.


Thanks for all your help!

Urusergi

#4
Don't you prefer a three-digit decimal counter? I think it would be easier

andycadley


The same basic principle applies even for a different encoding, it's a bit more clunky but back-of-a-fag-packet coding looks something like:

and &f
add &90
daa
jp c,letter
add &8f
letter:
inc a


kelp7

Quote from: Urusergi on 22:51, 21 February 18
Don't you prefer a three-digit decimal counter? I think it would be easier


I am coming 'round to that idea actually :)

kelp7

Quote from: andycadley on 05:56, 22 February 18
The same basic principle applies even for a different encoding, it's a bit more clunky but back-of-a-fag-packet coding looks something like:

and &f
add &90
daa
jp c,letter
add &8f
letter:
inc a



Thanks! That's very interesting indeed. I shall look into it. At the moment I have other problems, some sort of syncing thing where any slight delay after writing a byte (even just one command such as LD (D000),BC) causes corruption when loading back in (despite the same amount of code used in both write byte and read byte from tape). So I need to investigate timings first. It's kind of annoying as I have a working turbo loader, I just want a nice 'bytes left to load' display on the screen :) I'll get there....

Urusergi

@andycadley  very good idea! thanks to your code I've been able to improve it  8)

and &0f
add &90
daa
ADC &90
AND &2F


kelp7

That is some super cool coding!! Thanks :) I've tried it and it does seem to work very well.

kelp7

Quote from: Urusergi on 15:51, 22 February 18
@andycadley  very good idea! thanks to your code I've been able to improve it  8)

and &0f
add &90
daa
ADC &90
AND &2F



And then do I have to rotate the nibble to get the next character?

Urusergi

For example, like a subrutine:

                LD HL,&D001
                LD A,B
                CALL CONVDISPCHAR
                LD A,B
                RRA
                RRA
                RRA
                RRA
CONVDISPCHAR:    AND &0F
                ADD &90
                DAA
                ADC &90
                AND &2F
                LD (HL),A
                DEC HL
                RET

kelp7

Quote from: Urusergi on 16:35, 22 February 18
For example, like a subrutine:

                LD HL,&D001
                LD A,B
                CALL CONVDISPCHAR
                LD A,B
                RRA
                RRA
                RRA
                RRA
CONVDISPCHAR:    AND &0F
                ADD &90
                DAA
                ADC &90
                AND &2F
                LD (HL),A
                DEC HL
                RET



Verrrrrrry nice indeed! That's nice and compact for sure. Always appreciate the help I receive here though I know I'm a bit of an outsider :)

andycadley


Quote from: Urusergi on 15:51, 22 February 18
@andycadley  very good idea! thanks to your code I've been able to improve it  8)

and &0f
add &90
daa
ADC &90
AND &2F



Ooh, nice. I like it. :-)

Longshot

                LD HL,&D001
                LD A,B
                CALL CONVDISPCHAR
                DEC L
                LD A,B
                RRA
                RRA
                RRA
                RRA
CONVDISPCHAR:    AND &0F
                ADD &90
                DAA
                ADC &90
                AND &2F
                LD (HL),A
                RET
Rhaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!!

Longshot

Or this....

                LD HL,&D001
                LD C,&90
                LD (HL),B
                LD A,B
                AND &F
                ADD A,C
                DAA
                ADC A,C
                AND &2F
                LD B,A
                RLD
                LD (HL),B
                AND &F
                ADD A,C
                DAA
                ADC A,C
                AND &2F
                DEC L
                LD (HL),A
                RET 

Rhaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!!

kelp7

Thanks! Interesting to see some different variations. I don't want to muck about with C too much as BC contains the value I need to work on with this little routine (and is vital elsewhere in the program). Obviously I could PUSH but don't want to spend too many instructions doing things at this point :)

Urusergi

Hi @gerald

The routine that you put at the beginning of the thread can be improved from 16 to 18 µs and save 3 bytes (sorry, I didn't notice before)
or #0xF0
daa
add #0xA0
adc #0x40


instead of:

  and #0x0F
  add #0x30  ; 0
  cp #0x3A
  jr C, puthex_AF
  add #0x07
puthex_AF:



Powered by SMFPacks Menu Editor Mod