Inline ASM - a Copy & Write Cell Problem

ZX80, ZX 81, ZX Spectrum, TS2068 and other clones
Post Reply
Zetr0
Member
Posts: 33
Joined: Mon Aug 22, 2011 12:38 pm

Inline ASM - a Copy & Write Cell Problem

Post by Zetr0 »

Hello my fellow z88dk'ers!

I am currently in a conundrum with a bit of ASM that should be working but... isn't

Code: Select all

void asm_CopyWriteCell( void *scr_ptr, void *copy_cell, void *source)                //HL / BC / DE
{
      #asm

         ; load positions from stack

         ld HL, 6        ; get the source cell data address
         add HL, SP      ;

         ld E, (HL)      ; store ( data source location ) in DE
         inc HL
         ld D, (HL)

         ld HL, 4        ; get the copy cell address
         add HL, SP      ;

         ld C, (HL)      ; store in BC
         inc HL
         ld B, (HL)

         ld HL, 2        ; get the screen pointer address
         add HL, SP


         ; Processing TIME! 
         ; P0

         ld A, (HL)       ; get the byte from the screen file
         ld (BC), A       ; store in Copy Cell
         ld A, (DE)       ; get byte to write to screen file

         ld (HL),A        ; test

         inc H            ; next byte line data in screen file *CELL
         inc BC           ; next byte in Copy Cell
         inc DE           ; next byte in Source Cell

         ; P1

         ld A, (HL)       ; get the byte from the screen file
         ld (BC), A       ; store in Copy Cell
         ld A, (DE)       ; get byte to write to screen file
         ld (HL),A        ; save to screen file

         inc H            ; next byte line data in screen file *CELL
         inc BC           ; next byte in Copy Cell
         inc DE           ; next byte in Source Cell

         ; P2

         ld A, (HL)       ; get the byte from the screen file
         ld (BC), A       ; store in Copy Cell
         ld A, (DE)       ; get byte to write to screen file
         ld (HL),A        ; save to screen file

         inc H            ; next byte line data in screen file *CELL
         inc BC           ; next byte in Copy Cell
         inc DE           ; next byte in Source Cell

         ; P3

         ld A, (HL)       ; get the byte from the screen file
         ld (BC), A       ; store in Copy Cell
         ld A, (DE)       ; get byte to write to screen file
         ld (HL),A        ; save to screen file

         inc H            ; next byte line data in screen file *CELL
         inc BC           ; next byte in Copy Cell
         inc DE           ; next byte in Source Cell

         ; P4

         ld A, (HL)       ; get the byte from the screen file
         ld (BC), A       ; store in Copy Cell
         ld A, (DE)       ; get byte to write to screen file
         ld (HL),A        ; save to screen file

         inc H            ; next byte line data in screen file *CELL
         inc BC           ; next byte in Copy Cell
         inc DE           ; next byte in Source Cell

         ; P5

         ld A, (HL)       ; get the byte from the screen file
         ld (BC), A       ; store in Copy Cell
         ld A, (DE)       ; get byte to write to screen file
         ld (HL),A        ; save to screen file

         inc H            ; next byte line data in screen file *CELL
         inc BC           ; next byte in Copy Cell
         inc DE           ; next byte in Source Cell

         ; P6

         ld A, (HL)       ; get the byte from the screen file
         ld (BC), A       ; store in Copy Cell
         ld A, (DE)       ; get byte to write to screen file
         ld (HL),A        ; save to screen file

         inc H            ; next byte line data in screen file *CELL
         inc BC           ; next byte in Copy Cell
         inc DE           ; next byte in Source Cell

         ; P7

         ld A, (HL)       ; get the byte from the screen file
         ld (BC), A       ; store in Copy Cell
         ld A, (DE)       ; get byte to write to screen file
         ld (HL),A        ; save to screen file

         ret
      #endasm
}

Code: Select all

CALL:
asm_CopyWriteCell( scr_ptr, &Tile[4].byte, &Tile[0].byte);

Code: Select all

ELEMENTS:

struct ZX_UDG
{
       unsigned char byte[8];
};

struct ZX_UDG Tile[5];
The code itself copies 8 bytes from the Screen File (HL) to the Copy Cell location (BC)
During this process, it also writes a byte (each itteration) to the Screen File [SCR PTR (HL) ] from the [ SOURCE (DE) ]

Sadly when I inspect the retainers and print them to the screen I get a complete mess - so I have clearly missed something fundemental - my hope (and its most likely )that I missed something blindingly obvious - so any ideas of the above - what little is left of my hair - appreciates you =)

__________________________________________________________________________________


Interestingly the above is an extrapolation of another ASM function I wrote that works as expected -

Code: Select all

void asm_CopyClearCell( void *dest, void *source)
{
      #asm
         ld hl,2         ; jump the return address of the stack
         add hl,sp       ; by incrementing the stack ptr by 2

         ld c,(hl)         ; load the address of the *byte ptr from the stack to bc
         inc hl          ; "" *Remember Least Significant Byte First
         ld b,(hl)         ; ""
         ld a,(bc)         ; store the value of BC in a      "source"

         ld hl,4         ; add a four byte jump to the stack
         add hl,sp       ; getting to "dest"

         ld e,(hl)           ; get the address
         inc hl           ; of the
         ld d,(hl)       ; *dest

         ex de,hl        ; exchange registers

         ; unpacked for speed

         ld (hl), a     ; put the byte from the screen file to the copy cell

         inc hl         ; add 1 to get to the next row in the cell
         xor a
         ld (bc), a     ; empty the byte from the screen file 
         inc b          ; add 256 to the address ( next data line within the CELL of the Screen File)
         ld a,(bc)      ; put the value of the pointer of BC into A
         ld (hl), a     ; put the byte in the screen file

         inc hl          ; add 1 to get to the next row in the cell
         xor a          ; Empty A register
         ld (bc), a     ; empty the byte
         inc b           ; add 256 to the address of the byte
         ld a,(bc)      ; put the value of the pointer of BC into A
         ld (hl), a     ; put the byte in the screen file

         inc hl          ; add 1 to get to the next row in the cell
         xor a
         ld (bc), a     ; Zero the byte within the Screen File
         inc b           ; add 256 to the address of the byte
         ld a,(bc)      ; put the value of the pointer of BC into A
         ld (hl), a     ; put the byte from the screen file to the copy cell

         inc hl          ; add 1 to get to the next row in the cell
         xor a
         ld (bc), a     ; empty the byte
         inc b           ; add 256 to the address of the byte
         ld a,(bc)      ; put the value of the pointer of BC into A
         ld (hl), a     ; put the byte in the screen file

         inc hl          ; add 1 to get to the next row in the cell
         xor a
         ld (bc), a     ; empty the byte
         inc b           ; add 256 to the address of the byte
         ld a,(bc)      ; put the value of the pointer of BC into A
         ld (hl), a     ; put the byte in the screen file

         inc hl          ; add 1 to get to the next row in the cell
         xor a
         ld (bc), a     ; empty the byte
         inc b           ; add 256 to the address of the byte
         ld a,(bc)      ; put the value of the pointer of BC into A
         ld (hl), a     ; put the byte in the screen file

         inc hl          ; add 1 to get to the next row in the cell
         xor a
         ld (bc), a     ; empty the byte
         inc b           ; add 256 to the address of the byte
         ld a,(bc)      ; put the value of the pointer of BC into A
         ld (hl), a     ; put the byte in the screen file

         xor a
         ld (bc), a

         ret
      #endasm
}

Code: Select all

ELEMENTS:

struct ZX_UDG
{
       unsigned char byte[8];
};

struct ZX_UDG Tile[5];

Code: Select all

CALL:
 asm_CopyClearCell( &Tile[4].byte, scr_ptr );
The above copies a line of screen data cell data into a retainer [ *dest ( HL ) ] and then Zero's the data held within the Screen File [ *scr_ptr ( BC ) ]


So slowly slowly getting there.... soo slowly.... but hey... picked up my set of glasses today, only been waiting 3 weeks - whom know's I may, (although unlikely) figure this mess out....


A huge thanks for reading.
Zetr0
Member
Posts: 33
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

Just some notice of dependencies as there is a some speed / menory trade offs

Code: Select all

unsigned int ScreenBitmap[24];              // a collection of base pointer address (in INT) for the row of the screen file data (store 48 bytes)

void InitScreen( void );                                    // initializes an array of Screen File pointer address in the Y dimension
                                                            // Array size is 24 bytes, reduces add and offset opps by half
void InitScreen( void )
{
     register unsigned int index = 0, row = 0;              // this implementation divies up the screen into 32 cells wide ( 0 - 31 ) and 24 Cells long ( 0 - 23 )
                                                            // As the spectrum doens't have a linear bitmap to the screen a small translation of cell location
                                                            // based on the tirciary of the screen with a Y lookup table
     while ( index < 24 )
     {
          ScreenBitmap[ index ] = ScreenFile;

          if( index > 7 )                                   // if index is in the 2nd or 3rd bank of the screen file
          {
              if( index > 15 )
              {
                  ScreenBitmap[ index ] = ScreenBitmap[ index ] + 3584;       // the third bank offset of the screen file  (less 256)
              }
              else
              {
                  ScreenBitmap[ index ] = ScreenBitmap[ index ] + 1792;       // the second bank offset of the screen file (less 256)
              }
          }
          ScreenBitmap[ index ] = ScreenBitmap[ index ] + ( index * 32 );     // the Y cell location of the Screen File Bank
          index = index +1;
     };
}


void *GetScreenCell( unsigned char row, unsigned char col);        // returns the address of the cell of the screen file

void *GetScreenCell( unsigned char row, unsigned char col)
{
     return (void *) ScreenBitmap[ row ] + col;
}
Such that in the use of say "asm_CopyClear( )"

Code: Select all

    // set up scr_ptr Y (row) position / address(s)
    ZX_Tile_UDG_Init();

    // Which CELL to opperate on -
    scr_ptr = GetScreenCell( 10, 10 );
   
    // Write a CELL data to the screen
    asm_CopyClearCell( &Tile[4].byte, scr_ptr );
Zetr0
Member
Posts: 33
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

I should of added these to the above post

Code: Select all

#define ScreenFile 16384;
#define AttribFile 22528;
User avatar
dom
Well known member
Posts: 1314
Joined: Sun Jul 15, 2007 10:01 pm

Post by dom »

I can see a couple of problems:

It looks like you've got the parameters back-to-front if you're working with sccz80. For sccz80 parameters are pushed l->r by default (see the calling conventions wiki page: https://github.com/z88dk/z88dk/wiki/CallingConventions) so your offsets are wrong.

The pickup of the screen pointer is wrong, you've got hl = &screen_pointer_address - so it points to somewhere on the stack.

So I think you want:

Code: Select all

   ld   hl,2
   add  hl,sp
   ld   e,(hl)   ;source
   inc  hl
   ld   d,(hl)
   inc  hl
   ld   c,(hl)   ; copy cell
   inc  hl
   ld   b,(hl)
   inc  hl
   ld   a,(hl)   ;screen pointer
   inc  hl
   ld   h,(hl)
   ld   l,a
An alternate (slower, but shorter) intro for this function might be:

Code: Select all

  pop  af ; return
  pop  de ; source
  pop  bc ; copy cell
  pop  hl ; screen pointer
  push hl
  push bc
  push de
  push af
You might want to consider making it __z88dk_callee so that you don't have to push the parameters again in which case this way would be preferred.
Zetr0
Member
Posts: 33
Joined: Mon Aug 22, 2011 12:38 pm

Post by Zetr0 »

I cannot thank you enough DOM, I had been banging my head for a few hours on that one!

the moment I read that I had be trying to collect the pointer address as opposed to what it was pointing too... well I am surprised that you didn't hear the thump of my head hitting the desk this morning!!!

A huge thanks - this is all starting to come together and make some sense..... and for that as well as your efforts with Z88dk, I do hope there is a time I can can get you and Sefano a beer for your help, continued support of z88dk =)

Thanks for the heads up
Post Reply