some #asm handling

Other misc things
Post Reply
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

some #asm handling

Post by cborn »

Hello
I try to connect a asm piece with my circle routine which give variables in C.
i just read the "newbie question" and found the remark about direct value in hl from calling the void? or popping into registers.
what is the correct and hopefully complete way to do this? i found somelinks but a did not find a clear explain or some like a table to check. perhaps i should seperate asm and c? then i need it as global, is that correct?
well, this one just crashes after plotting a single dot on the left side. the C plot command starts at the rightside of the screen

Code: Select all


// zcc +zx -vn -lm plotcircle07_8.c -o ZXplotcircle07_8 -lndos -create-app

#include <stdio.h>
#include <math.h>       /* zcc and gcc NEEDS -lm now */
#include <graphics.h>
#include <spectrum.h>

//actualy i just brutaly copy/past like a ...
#include <sys/types.h>
#include <conio.h>

void __CALLEE__ plotz( uchar _x, _y) __naked {


#asm
//; plot d = x-axis, e = y-axis

pop hl
pop de  // wild guess to fetch x and y
ld d,l  // is d=x, e=y ??
//PLOT:
//  push hl           //11t

  ld a,d            // 4t
  cpl               // 4t
  and 7             // 7t

  rlca              // 4t
  rlca              // 4t
  rlca              // 4t
  or 198            // 7t

  ld hl,bits+1      //10t
  ld (hl),a         // 7t

  ld a,e            // 4t
  rra               // 4t
  scf               // 4t
  rra               // 4t

  or a              // 4t
  rra               // 4t
  ld l,a            // 4t
  xor e             // 4t
  and 248           // 7t

  xor e             // 4t
  ld h,a            // 4t
  ld a,l            // 4t
  xor d             // 4t
  and 7             // 7t

  xor d             // 4t
  rrca              // 4t
  rrca              // 4t
  rrca              // 4t
  ld l,a            // 4t
bits:
  set 0,(hl)        // 8t  0xCB %11bbb110
//  pop hl            //10t
//  ret               //10t

#endasm

return 0 ;
}


void plotcircle(int r, s, float x , y ){
int  f ;
float xr , yr , p ;

for (f=0 ; f<=s ; f++ )
  {
   p= 2*f*M_PI/s ;
   xr=x+r*cos(p) ;
   yr=y+r*sin(p) ; 

   //   plot(xr,yr) ;
   plotz(xr,yr);
  }
return 0 ;
}

void main (){

//EXTERN _x
//EXTERN _y

char key ;
int f ;
float r, s, x, y ;

printf("\xCplot a circle, first enter value's\neg r=50 , s=36 , x=127.5 , y=87.5\n\n");

enter_value:
printf("Enter r : ") ;
scanf("%f", &r ) ;
printf("Enter s : ") ;
scanf("%f", &s ) ;
printf("Enter x : ") ;
scanf("%f", &x ) ;
printf("Enter y : ") ;
scanf("%f", &y ) ;

printf("\xC");

draw(  0, 0, 255,  0);
draw(255, 0, 255,191);
draw(255,191,  0,191);
draw(  0,191,  0,  0);

plotcircle( r, s, x , y );

printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

printf(" Press 'y' to plot again, 'n' will quit");
getakey:
key = getchar() ;
switch(key) {
case 'y' : goto enter_value ;
           break ;
case 'n' : return 0 ;
           break ;
default  : goto getakey ;
            }
}

cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: some #asm handling QUESTION

Post by cborn »

sorry that i did not mentio "question" in the tilte. can that be changed since i do not have those asm handlings!, sorry
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: some #asm handling

Post by jorgegv »

First, I'd recommend you to compile with --list --c-code-in-asm when compiling mixed C and ASM. It's very useful to see what ASM is being generated:

Code: Select all

zcc +zx -vn -lm plotcircle07_8.c -o ZXplotcircle07_8 -lndos -create-app --list --c-code-in-asm
Then your code: the declaration for plotz is wrong, you must specify type for both params, otherwise the second one is silently promoted to 16bit int (you can see that in the generated .c.lis file):

Code: Select all

plotcircle07_8.c:
    11                          ;void __CALLEE__ plotz( uchar _x, _y) __naked {
    11                                  C_LINE  13,"plotcircle07_8.c"
    13                                  C_LINE  13,"plotcircle07_8.c"
    13                                  SECTION code_compiler
    13                          
    13                          ; Function plotz flags 0x00000a40 __smallc __z88dk_callee __naked
    13                          ; void plotz(unsigned char _x, int _y)
    13                          ; parameter 'int _y' at sp+2 size(2)
    13                          ; parameter 'unsigned char _x' at sp+4 size(1)
    13                                  C_LINE  13,"plotcircle07_8.c::plotz::0::0"
...
When entering your asm function, the first 16 bit word on the stack is the return address. Since you declared your function as __CALLEE__ you must remove the params from the stack in your code. You can do this by saving the return address, pop the parameters, and then push again the return address:

Code: Select all

#asm
//; plot d = x-axis, e = y-axis

pop bc  // save ret addr

pop de
pop hl  // wild guess to fetch x and y
ld l,d  // is d=x, e=y ??

push bc // put ret addr again on the stack

//PLOT:
//  push hl           //11t

(you guessed the params right, they are pushed on the stack right to left)

With this changes at least the code does not hang or reset the machine, but it does not draw a circle.... (?)
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: some #asm handling

Post by jorgegv »

I see your declaration for function plotcircle has the same problems (implicit types for arguments):

Code: Select all

void plotcircle(int r, s, float x , y ){
(...)
Should be:

Code: Select all

void plotcircle(int r, int s, float x , float y ){
(...)
Timmy
Well known member
Posts: 392
Joined: Sat Mar 10, 2012 4:18 pm

Re: some #asm handling

Post by Timmy »

I see your code works if you just use the regular "plot" function instead of your "plotz".

So I guess your question is not how to draw a circle, but just how to do inline assembly?

The changes are:

Code: Select all

void __CALLEE__ plotz( uchar _x, uchar _y) __naked {
// remember to give type to every single parameter seperately.
#asm
//; plot d = x-axis, e = y-axis
pop bc
pop de
pop hl  // l = x and e = y
push bc
ld d, l
//PLOT:
and at the bottom:

Code: Select all

bits:
  set 0,(hl)        // 8t  0xCB %11bbb110
//  pop hl            //10t
  ret               //10t

#endasm

//return 0 ;
}
what is the correct and hopefully complete way to do this? i found somelinks but a did not find a clear explain or some like a table to check. perhaps i should seperate asm and c? then i need it as global, is that correct?
But since this really isn't a newbie question, I'd say you should go back using "plot()" again. :)

The answer to this question is, in your case, use an emulator and check every byte of the output if it works. There are some shortcuts, but since you're asking for "the correct and hopefully complete way"... That would take me weeks to write, and it take about even more time for you to read and understand, because there are too many options.

I might write about two or three useful cases in the future, but "the correct and hopefully complete way"? I'm not writing that even for big money. :)
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: some #asm handling

Post by cborn »

jorgegv wrote: Sat Feb 18, 2023 4:23 pm I see your declaration for function plotcircle has the same problems (implicit types for arguments):

Code: Select all

void plotcircle(int r, s, float x , y ){
(...)
Should be:

Code: Select all

void plotcircle(int r, int s, float x , float y ){
(...)
Hi, thanks, i think i read somewere that it was possible like that but the way you explain that its only valid for an INT value and not for any declaration. i changed that!

Meanwhile i did crossover some parts i think. i did try the pop bc part but probably wrong.
I removed the 'return 0' asweel like Timmy mentioned.
And indeed my momentary question is about the #asm implementation.

Actualy i have to recheck what part i clipped from the drawing routine. It should develop the screen adres

Code: Select all

//plotcircle08_4
// zcc +zx -vn -lm  plotcircle08_4.c -o plotcircle08_4 -lndos -create-app --list --c-code-in-asm
//https://www.z88dk.org/forum/posting.php?mode=quote&p=21291


#include <stdio.h>
#include <math.h>       /* zcc and gcc NEEDS -lm now */
#include <graphics.h>
#include <spectrum.h>

//actualy i just brutaly copy/past like a ...
#include <sys/types.h>
#include <conio.h>

void __CALLEE__ plotz( int x, y) __naked {
// x,y both 16bit 

#asm
//; plot d = x-axis, e = y-axis
pop bc              //10t fetch return address
pop hl              //10t fetch x
pop de              //10t   and y

push bc             //11t first restore return address

  ld d,l            // 4t fetch x lsb 8bit value from hl
                    //          y left over in reg_e
  xor a             // 4t strike carryflag if set
  ld a,d            // 4t
  cpl               // 4t
  and 7             // 7t  // select bit number to be written on screen

  rlca              // 4t
  rlca              // 4t
  rlca              // 4t  
  or 198            // 7t  part of the SET n,(HL) instruction

  ld hl,bits+1      //10t
  ld (hl),a         // 7t  rewrite SET instruction in this asm block

  ld a,e            // 4t
  rra               // 4t
  scf               // 4t
  rra               // 4t
  or a              // 4t
  rra               // 4t
  ld l,a            // 4t

  xor e             // 4t
  and 248           // 7t
  xor e             // 4t

  ld h,a            // 4t

  ld a,l            // 4t

  xor d             // 4t
  and 7             // 7t
  xor d             // 4t

  rrca              // 4t
  rrca              // 4t
  rrca              // 4t
  ld l,a            // 4t

bits:               // set n,(hl)  is rewritten with the actual BIT value n=%bbb
  set 0,(hl)        // 8t  0xCB %11bbb110

#endasm
}


void plotcircle(int r, int s, float x , float y ){

int  f ;
float xr , yr , p , xstr[512], ystr[512] ;

for (f=0 ; f<=s ; f++ )
  {
   p= 2*f*M_PI/s ;
   xr=x+r*cos(p) ;
   yr=y+r*sin(p) ; 

   xstr[f]=xr ;
   ystr[f]=yr ;

//  plot(xr,yr) ;
   plotz(xr,yr) ;  // xr,yr are float, plot(x,y)is int

   if (f>0) draw(xstr[f-1], ystr[f-1],xstr[f], ystr[f]);

  }
return 0 ;
}



void main (){

char key ;
int f ;
float r, s, x, y ;

printf("\xC\n");

draw(  0, 0, 255,  0);
draw(255, 0, 255,191);
draw(255,191,  0,191);
draw(  0,191,  0,  0);

printf("plot a circle, first enter value's\neg r=50 , s=36 , x=127.5 , y=87.5\n\n");

enter_value:
printf("Enter r : ") ;
scanf("%f", &r ) ;
printf("Enter s : ") ;
scanf("%f", &s ) ;
printf("Enter x : ") ;
scanf("%f", &x ) ;
printf("Enter y : ") ;
scanf("%f", &y ) ;

printf("\xC");


plotcircle( r, s, x , y );

printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

printf(" Press 'y' to plot again, 'n' will quit");
getakey:
key = getchar() ;
switch(key) {
case 'y' : goto enter_value ;
           break ;
case 'n' : return 0 ;
           break ;
default  : goto getakey ;
            }
}
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: some #asm handling

Post by cborn »

I wanted to link the file from which i have the plot routine but the search engine of wos is disfunctional :(

this is an asm that does NOT rewrite and it produces the same error on screen

Code: Select all

//plotcircle09_2
// zcc +zx -vn -lm  plotcircle09_2.c -o plotcircle09_2 -lndos -create-app --list --c-code-in-asm
//https://www.z88dk.org/forum/posting.php?mode=quote&p=21291


#include <stdio.h>
#include <math.h>       /* zcc and gcc NEEDS -lm now */
#include <graphics.h>
#include <spectrum.h>

//actualy i just brutaly copy/past like a ...
#include <sys/types.h>
#include <conio.h>

void __CALLEE__ plotz( int x, y) __naked {
// x,y both 16bit 

#asm
//; plot d = x-axis, e = y-axis
pop bc              //10t fetch return address
pop hl              //10t fetch x
pop de              //10t   and y

push bc             //11t first restore return address

  ld d,l            // 4t fetch x lsb 8bit value from hl
                    //          y left over in reg_e
;write 1 pixel   DE holds X,Y position left,down 0,0
pixel:     ld a,191        ; 7t 191 is working, was 175
           sub e           ; 4t y = y1 or y2
;           jr c,reit       ;10t out of screen
pixel0:     ld e,a          ; 4t e = 191-y

pixel2:    rra             ; 4t bit 7=NC=0
           scf             ; 4t set carry
           rra             ; 4t bit 7=1
           and a           ; 4t reset carry
           rra             ; 4t bit 7=0 >> a=010xxxxx

           xor e           ; 4t   y        a=101xxxxx
           and 248         ; 7t  248 =       11111000  >> factor 8, bit-wise grid Y, block off 8 lines
           xor e           ; 4t   y        a=010xx000
           ld h,a          ; 4t h points to block 0, 1 or 2 

           ld a,d          ; 4t x= x1 or x2
           rlca            ; 4t
           rlca            ; 4t
           rlca            ; 4t 3x rotate left circulair, highest 3 bit are now lowest 3 bit
           xor e           ; 4t   y
           and 199         ; 7t     B_11000111
           xor e           ; 4t   y back

           rlca            ; 4t  B_10001111
           rlca            ; 4t  B_00011111
           ld l,a          ; 4t  l = x = %000xxxxx

           ld a,d          ; 4t  x
           and 7           ; 7t  %00000111
           ld b,a          ; 4t
           inc b           ; 4t b=1 to 8 ???
           ld a,1          ; 7t  %00000001
rotate:    rrca            ; 4t  %10000000  %01000000 etc set pixel %01234567
           djnz rotate     ; ((4+13)*b)-5 = 12 to 
           or (hl)         ; 7t
           ld (hl),a       ; 7t

#endasm
}


void plotcircle(int r, int s, float x , float y ){

int  f ;
float xr , yr , p , xstr[512], ystr[512] ;

for (f=0 ; f<=s ; f++ )
  {
   p= 2*f*M_PI/s ;
   xr=x+r*cos(p) ;
   yr=y+r*sin(p) ; 

   xstr[f]=xr ;
   ystr[f]=yr ;

//  plot(xr,yr) ;
   plotz(xr,yr) ;  // xr,yr are float, plot(x,y)is int

   if (f>0) draw(xstr[f-1], ystr[f-1],xstr[f], ystr[f]);

  }
return 0 ;
}



void main (){

char key ;
int f ;
float r, s, x, y ;

printf("\xC\n");

draw(  0, 0, 255,  0);
draw(255, 0, 255,191);
draw(255,191,  0,191);
draw(  0,191,  0,  0);

printf("plot a circle, first enter value's\neg r=50 , s=36 , x=127.5 , y=87.5\n\n");

enter_value:
printf("Enter r : ") ;
scanf("%f", &r ) ;
printf("Enter s : ") ;
scanf("%f", &s ) ;
printf("Enter x : ") ;
scanf("%f", &x ) ;
printf("Enter y : ") ;
scanf("%f", &y ) ;

printf("\xC");


plotcircle( r, s, x , y );

printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

printf(" Press 'y' to plot again, 'n' will quit");
getakey:
key = getchar() ;
switch(key) {
case 'y' : goto enter_value ;
           break ;
case 'n' : return 0 ;
           break ;
default  : goto getakey ;
            }
}

and the asm in a working routine

Code: Select all

; pasmo -d -1 -v --tap p2pd031.asm p2pd031.tap p2pd031.symbol
; quick compile in kate:
; pasmo -d  --tap %f %n.tap %n.symbol

; point to point draw, by MAARTEN uit Arnhem 1988 or 1989, or earlier
; draws a line between 2 absolute points anywhere on screen
;x 0-255
;y 0-191  > (0,0,255,191) gives a full screen diagonal
; poke 'pixel+1' with 191 for full screen to LINE 23 or poke 175 for BASIC screen to LINE 21
; use in BASIC:
; DEF FN d(x1,y1,x2,y2)= USR start
; RANDOMIZE FN d(x,y,a,b)  (= RANDOMIZE USR start !)
; (x1,y1,x2,y2)=(0,0,a,b) is Left Down Corner

;https://www.worldofspectrum.org/forums/discussion/comment/129919/#Comment_129919
;The display layout is easy to understand at the binary level:
;1. 16-bit Screen Memory Address in binary
;     010B BSSS LLLC CCCC (pixels)
;     BB = block (0-2) indicates top third, middle third or bottom third of screen
;     SSS = scan line (0-7) indicates the vertical pixel row within a character
;     LLL = vertical character line (0-7) within a block
;     CCCCC = horizontal character coordinate (0-31)
;2. 8-bit Pixel Coordinates
;     (0,0) top left corner of screen
;     X : CCCC CTTT (0-255)
;     Y : BBLL LSSS (0-191)
;     TTT is 0-7 and indicates the pixel position within a byte. 0=leftmost pixel position (bit 7)
;3. 8-bit Character Coordinates
;     X : 000C CCCC (0-31)
;     Y : 000B BLLL (0-23)
;4. 16-bit Attribute Address
;     0101 10BB LLLC CCCC

; changes by Chris Born 2016,2019
; changed vertical size from 175 to 191, poke @ A_pix   cq adres pixel+1
; Written as asm file manualy with ZX disas 'monitor25000'
; ;;;all JP commands changed in JR (except "jp c,9465"), for speed some could be changed back
; removed a single call, saving 4 bytes and 27 tstate.
; moved the storing of HL' and removed 2 'exx' saving 2 bytes and 8 tstate per line
; ;;;chanced 'ld b,255, xor b for CPL, saving 2 bytes and 7t
; changed 'bit-tractor' reg value reg A from 254 to 1 and removed al 'manual CPL' stuff saving 7byte totaly in that part and 7+4+4+4+7+4=30t per pixel draw
;moved       ld (kstate),bc so its set before the decision and needed only once thus saving 4 byte, no tstate

; removed leftover opcodes

DEF_ADR    equ  23563        ; sysvar DEF_ADR, points to needed value's

;temporair sysvars  used as temp storage
kstate     equ  23556        ;sysvar 2nd key-buffer
kstate2    equ  23558
xptr       equ  23647        ; sysvar used while editing line
seed       equ  23670        ; used for RND, set with RANDOMIZE so, probably over written by "randomize usr start"

start      equ  60700

           org start         ;

           di                ; faster without interrupts
           exx
           push hl           ;st0>st1
           ld (kstate2),sp   ; store StackPointer 

           ld hl,(DEF_ADR)   ; hl = actual RAM location in BASIC listing at position off the DEF FN
           ld bc,4           ;
           add hl,bc         ; adres+4
           ld d,(hl)         ; var x1
           ld c,8            ;
           add hl,bc         ; adres+4+8
           ld e,(hl)         ; var y1

           ld a,191          ; 7t 191 is working, was 175, 'just poke it' C.B.
           cp e              ; 4t y = y1
           jp c,reit         ; 7t out of screen

; how to use ex af,af' here  ; ld a,191
                             ; sub e
                             ; jp c,reit
                             ; ex af,af'    reversed y1 stored

           ld (seed),de      ; store adres of FN value's x1 and y1

           add hl,bc         ; adres+4+8+8
           ld d,(hl)         ; var x2
           add hl,bc         ; adres+4+8+8+8
           ld e,(hl)         ; var y2
 
;           ld a,191          ; 7t 191 is working, was 175, 'just poke it' C.B.
           cp e              ; 4t a=191   y = y2
           jp c,reit         ; 7t out of screen  error trap is done now

;2 bytes longer, but 10 tstate faster pixelroutine
           push de
           ld de,(seed)
;           push hl           ;st1>st2
;           push bc           ;st2>st3
           call pixel        ; check max 191 and write pixel_1 , cq plot 1st pixel
reloc1     equ $-2

;           pop bc             ;st3>st2  , obsolete after error-return
;           pop hl             ;st2>st1  , obsolete after error-return
           pop de            ; never obsolate sinc error trap is past by already

           ld hl,(seed)      ;  fetch start h=x1, l=y1 , d=x2, e=y2
           ld bc,257         ; b=1 c=1     direction vector cq quadrant ++
           ld a,d
           sub h             ; x2-x1
           jr nc,ad60742
           ld b,255          ; 'right to left' start point off drawing is biggest x
           neg               ; a=-a
ad60742    ld d,a            ;amount pixels horizontal

           ld a,e
           sub l             ; y2-y1
           jr nc,ad60752
           ld c,255          ;
           neg               ;bc is 'direction' relative to actual cq last pixel
ad60752    ld e,a            ;amount pixels vertical

           ld (kstate),bc    ; bc=0x0101 or 01FF or FF01 or FFFF
           ld a,d
           cp e              ; compare len x with len y ax
           jr nc,ad60767     ; if y longest , jump

           ld l,d
           xor a
           ld b,a
           jr ad60779

ad60767    or d              ; a=d already, zero check
           jr z,restoreSP
           ld l,e
           ld e,d
           ld c,0            ;

ad60779    ld h,e
           ld a,e
           rra



; pixel loop
nextpix    add a,l         ; 4t
           jp c,ad60790    ;10t

           cp h            ; 4t
           jp c,ad60800    ;10t

ad60790    sub h           ; 4t
           ld d,a          ; 4t
           exx             ; 4t  swop 1a
           ld de,(kstate)  ;20t  0101  01ff  ff01  ffff
           jp ad60804      ;10t

ad60800    ld d,a          ; 4t
           push bc         ;11t st up   bc=??
           exx             ; 4t swop1b
           pop de          ;10t st down = equal

ad60804    ld hl,(seed)    ;20t  fetch start
           ld a,e          ; 4t 0,1 or 255 
           add a,l         ; 4t +y
           ld e,a          ; 4t e=y
           ld a,d          ; 4t 0,1 or 255 
           inc a           ; 4t
           add a,h         ; 4t   max 255+1 amount, 255+1 = Carry AND 0
           jr c,ad60836    ; 7+5t  >= C+ ( Z or NZ)
           jr z,restoreSP  ; 7t    >= NC+Z = exit

ad60819    dec a           ; 4t NC+NZ
           ld d,a          ; 4t
           ld (seed),de    ;20t write start



           call pixel      ;17+pixel
reloc2     equ $-2
           exx             ; 4t  swop 
           ld a,d          ; 4t
           dec e           ; 4t
           jp nz,nextpix   ; here 2t per PIXEL can be won Back for 1 byte, the relocate list becomes 1 adres longer
           jr restoreSP    ; last jump can be 2t faster but 1 byte longer

ad60836    jr z,ad60819    ; >= C+Z  (or nc+nz), 

restoreSP  ld sp,(kstate2) ; C+NZ (or nc+z) , any obsolete value will be dismissed
           pop hl
           exx             ; restore HL' value for BASIC
           ei
           ret

reit       ei              ; dont di-halt
           jp 9465         ;rom routine REPORT-B 'out of range'


;value x=255 always fits on screen, but y must be y <= 191  B_10111111
pixel_af   ex af,af'
pixel      ld a,191        ; 7t 191 is working, was 175
           sub e           ; 4t y = y1 or y2
;           jr c,reit       ;10t out of screen
pixel0      ld e,a          ; 4t e = 191-y

pixel2     rra             ; 4t bit 7=NC=0
           scf             ; 4t set carry
           rra             ; 4t bit 7=1
           and a           ; 4t reset carry
           rra             ; 4t bit 7=0 >> a=010xxxxx

           xor e           ; 4t   y        a=101xxxxx
           and 248         ; 7t  248 =       11111000  >> factor 8, bit-wise grid Y, block off 8 lines
           xor e           ; 4t   y        a=010xx000
           ld h,a          ; 4t h points to block 0, 1 or 2 

           ld a,d          ; 4t x= x1 or x2
           rlca            ; 4t
           rlca            ; 4t
           rlca            ; 4t 3x rotate left circulair, highest 3 bit are now lowest 3 bit
           xor e           ; 4t   y
           and 199         ; 7t     B_11000111
           xor e           ; 4t   y back

           rlca            ; 4t  B_10001111
           rlca            ; 4t  B_00011111
           ld l,a          ; 4t  l = x = %000xxxxx

           ld a,d          ; 4t  x
           and 7           ; 7t  %00000111
           ld b,a          ; 4t
           inc b           ; 4t b=1 to 8 ???
           ld a,1          ; 7t  %00000001
rotate     rrca            ; 4t  %10000000  %01000000 etc set pixel %01234567
           djnz rotate     ; ((4+13)*b)-5 = 12 to 
           or (hl)         ; 7t
           ld (hl),a       ; 7t
           ret             ;10t      7+4+7+4 +4+4+4+4+4+4 +7 +4+4+4+4+4+4+4 +7 +4+4+4+4+4 +7 +4+4 +7 +4 +((4+13)*1)-5 +7+7+10
                           ;=170 minimum tstate and +((4+13)*7) = 289 tstate max per pixel draw

; only 3 adresses to be recalculated for an relocation, from which only TWO needs to be rewritten
rel_1      equ reloc1-start
           defw rel_1
rel_2      equ reloc2-start
           defw rel_2
relpix     equ pixel+1-start
A_pix      equ relpix
ent        equ $
len        equ ent-start

the        end

;cleaned rewrite from MAARTENS point2point draw


User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: some #asm handling

Post by jorgegv »

Hi cborn,

sorry, when copying/pasting your code for fixes, I introduced an errata myself, and that's why my fixed code did not work. Here is the correct code, with my minimal fixes:

Code: Select all


// zcc +zx -vn -lm plotcircle07_8.c -o ZXplotcircle07_8 -lndos -create-app
// zcc +zx -vn -lm plotcircle07_8.c -o ZXplotcircle07_8 -lndos -create-app --list --c-code-in-asm

#include <stdio.h>
#include <math.h>       /* zcc and gcc NEEDS -lm now */
#include <graphics.h>
#include <spectrum.h>

//actualy i just brutaly copy/past like a ...
#include <sys/types.h>
#include <conio.h>

void __CALLEE__ plotz( uchar _x, uchar _y) __naked {


#asm
//; plot d = x-axis, e = y-axis

pop bc  // save ret addr

pop de
pop hl  // wild guess to fetch x and y
ld d,l  // is d=x, e=y ??

push bc // put ret addr again on the stack

//PLOT:
//  push hl           //11t

  ld a,d            // 4t
  cpl               // 4t
  and 7             // 7t

  rlca              // 4t
  rlca              // 4t
  rlca              // 4t
  or 198            // 7t

  ld hl,bits+1      //10t
  ld (hl),a         // 7t

  ld a,e            // 4t
  rra               // 4t
  scf               // 4t
  rra               // 4t

  or a              // 4t
  rra               // 4t
  ld l,a            // 4t
  xor e             // 4t
  and 248           // 7t

  xor e             // 4t
  ld h,a            // 4t
  ld a,l            // 4t
  xor d             // 4t
  and 7             // 7t

  xor d             // 4t
  rrca              // 4t
  rrca              // 4t
  rrca              // 4t
  ld l,a            // 4t
bits:
  set 0,(hl)        // 8t  0xCB %11bbb110
//  pop hl            //10t
  ret               //10t

#endasm

//return 0 ;
}


void plotcircle(int r, int s, float x , float y ){
int  f ;
float xr , yr , p ;

for (f=0 ; f<=s ; f++ )
  {
   p= 2*f*M_PI/s ;
   xr=x+r*cos(p) ;
   yr=y+r*sin(p) ; 

   //   plot(xr,yr) ;
   plotz(xr,yr);
  }
return 0 ;
}

void main (){

//EXTERN _x
//EXTERN _y

char key ;
int f ;
float r, s, x, y ;

printf("\xCplot a circle, first enter value's\neg r=50 , s=36 , x=127.5 , y=87.5\n\n");

enter_value:
printf("Enter r : ") ;
scanf("%f", &r ) ;
printf("Enter s : ") ;
scanf("%f", &s ) ;
printf("Enter x : ") ;
scanf("%f", &x ) ;
printf("Enter y : ") ;
scanf("%f", &y ) ;

printf("\xC");

draw(  0, 0, 255,  0);
draw(255, 0, 255,191);
draw(255,191,  0,191);
draw(  0,191,  0,  0);

plotcircle( r, s, x , y );

printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

printf(" Press 'y' to plot again, 'n' will quit");
getakey:
key = getchar() ;
switch(key) {
case 'y' : goto enter_value ;
           break ;
case 'n' : return 0 ;
           break ;
default  : goto getakey ;
            }
}
This code works and plots a circle.
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: some #asm handling

Post by jorgegv »

Oh, I realized another mistake in my previous answers: function call parameters are pushed on the stack left to right (it's __smallc convention), so they must be popped right to left when receiving them in the asm code.
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: some #asm handling

Post by cborn »

jorgegv wrote: Tue Feb 21, 2023 7:49 am Hi cborn,

sorry, when copying/pasting your code for fixes, I introduced an errata myself, and that's why my fixed code did not work. Here is the correct code, with my minimal fixes:

Code: Select all


// zcc +zx -vn -lm plotcircle07_8.c -o ZXplotcircle07_8 -lndos -create-app
// zcc +zx -vn -lm plotcircle07_8.c -o ZXplotcircle07_8 -lndos -create-app --list --c-code-in-asm

#include <stdio.h>
#include <math.h>       /* zcc and gcc NEEDS -lm now */
#include <graphics.h>
#include <spectrum.h>

//actualy i just brutaly copy/past like a ...
#include <sys/types.h>
#include <conio.h>

void __CALLEE__ plotz( uchar _x, uchar _y) __naked {


#asm
//; plot d = x-axis, e = y-axis

pop bc  // save ret addr

pop de
pop hl  // wild guess to fetch x and y
ld d,l  // is d=x, e=y ??

push bc // put ret addr again on the stack

//PLOT:
//  push hl           //11t

  ld a,d            // 4t
  cpl               // 4t
  and 7             // 7t

  rlca              // 4t
  rlca              // 4t
  rlca              // 4t
  or 198            // 7t

  ld hl,bits+1      //10t
  ld (hl),a         // 7t

  ld a,e            // 4t
  rra               // 4t
  scf               // 4t
  rra               // 4t

  or a              // 4t
  rra               // 4t
  ld l,a            // 4t
  xor e             // 4t
  and 248           // 7t

  xor e             // 4t
  ld h,a            // 4t
  ld a,l            // 4t
  xor d             // 4t
  and 7             // 7t

  xor d             // 4t
  rrca              // 4t
  rrca              // 4t
  rrca              // 4t
  ld l,a            // 4t
bits:
  set 0,(hl)        // 8t  0xCB %11bbb110
//  pop hl            //10t
  ret               //10t

#endasm

//return 0 ;
}


void plotcircle(int r, int s, float x , float y ){
int  f ;
float xr , yr , p ;

for (f=0 ; f<=s ; f++ )
  {
   p= 2*f*M_PI/s ;
   xr=x+r*cos(p) ;
   yr=y+r*sin(p) ; 

   //   plot(xr,yr) ;
   plotz(xr,yr);
  }
return 0 ;
}

void main (){

//EXTERN _x
//EXTERN _y

char key ;
int f ;
float r, s, x, y ;

printf("\xCplot a circle, first enter value's\neg r=50 , s=36 , x=127.5 , y=87.5\n\n");

enter_value:
printf("Enter r : ") ;
scanf("%f", &r ) ;
printf("Enter s : ") ;
scanf("%f", &s ) ;
printf("Enter x : ") ;
scanf("%f", &x ) ;
printf("Enter y : ") ;
scanf("%f", &y ) ;

printf("\xC");

draw(  0, 0, 255,  0);
draw(255, 0, 255,191);
draw(255,191,  0,191);
draw(  0,191,  0,  0);

plotcircle( r, s, x , y );

printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

printf(" Press 'y' to plot again, 'n' will quit");
getakey:
key = getchar() ;
switch(key) {
case 'y' : goto enter_value ;
           break ;
case 'n' : return 0 ;
           break ;
default  : goto getakey ;
            }
}
This code works and plots a circle.

Hi jorgegv, thank you very very much
and may i explain that the RET you put back was removed entirly and only by my self?
There are plenty asm snippets with out ret and i had in mind i had to cut it, but that was before you corrected the retADRES error.

so you realy repaired a mistake !!!
jippy!
User avatar
jorgegv
Well known member
Posts: 287
Joined: Wed Nov 18, 2020 5:08 pm

Re: some #asm handling

Post by jorgegv »

cborn wrote: Tue Feb 21, 2023 11:49 am Hi jorgegv, thank you very very much
and may i explain that the RET you put back was removed entirly and only by my self?
There are plenty asm snippets with out ret and i had in mind i had to cut it, but that was before you corrected the retADRES error.

so you realy repaired a mistake !!!
jippy!
Yes, the __naked function decorator tells the compiler to not generate any of the entry/exit code for the function, and this code includes the RET instruction.

So when using __naked you must include the RET in your #asm
cborn
Well known member
Posts: 267
Joined: Tue Oct 06, 2020 7:45 pm

Re: some #asm handling

Post by cborn »

jorgegv wrote: Tue Feb 21, 2023 12:22 pm
Yes, the __naked function decorator tells the compiler to not generate any of the entry/exit code for the function, and this code includes the RET instruction.

So when using __naked you must include the RET in your #asm
Then the name makes sense aswell

for now this is my working version:

Code: Select all

// plotcircle10_4
// zcc +zx -vn -lm  plotcircle10_4.c -o ZXplotcircle10_4 -lndos -create-app --list --c-code-in-asm

// https://www.z88dk.org/forum/posting.php?mode=quote&p=21291


#include <stdio.h>
#include <math.h>       /* zcc and gcc NEEDS -lm now */
#include <graphics.h>
#include <spectrum.h>

                    // ( 2nd,    1st )
void __CALLEE__ plotz( uchar x, uchar y) __naked {

#asm                 // plot d = x-axis, e = y-axis
 pop bc              //10t fetch return address
 pop de              //10t   and y
 pop hl              //10t fetch x

 push bc             //11t first restore return address

//---set (0,0) at top of screen, SUB will change top, while CP will only check top
   ld a,191          // 7t   max y value %10101111     ( or  %10111111 for 191)
   sub e             // 4t   current y value
   jr c,done         // 7+5t if e bigger then max then jump out
   ld e,a            // 4t   store new value
//-----
  
  ld d,l            // 4t store x lsb 8bit value from hl
                    //          y left over in reg_e
//---set bit ready
  ld a,d            // 4t
  cpl               // 4t
  and 7             // 7t select bit number to be written on screen, NoCarry

  rlca              // 4t
  rlca              // 4t
  rlca              // 4t  
  or 198            // 7t  fill in the SET n,(HL) instruction

  ld hl,bits+1      //10t   !! hl CHANGED !!
  ld (hl),a         // 7t  rewrite SET instruction in this asm block  4+4+7 +4+4+4+7 +10+7
//-----


//--- screen base
  ld a,e            // 4t
  rra               // 4t
  scf               // 4t
  rra               // 4t
  or a              // 4t
  rra               // 4t
//-----

  ld l,a            // 4t store temporair

  xor e             // 4t
  and 248           // 7t
  xor e             // 4t

  ld h,a            // 4t msb complete

  ld a,l            // 4t 

  xor d             // 4t
  and 7             // 7t
  xor d             // 4t

  rrca              // 4t
  rrca              // 4t
  rrca              // 4t
  ld l,a            // 4t lsb complete

bits:               // set n,(hl)  is rewritten with the actual BIT value n=%bbb
  set 0,(hl)        // 8t  0xCB %11bbb110
done:
  ret               //10t
#endasm
}


void plotcircle(float r, float s, float x , float y ){

int  f ;
float xr , yr , p , xstr[512], ystr[512] ;

for (f=0 ; f<=s ; f++ )
  {
   p= 2*f*M_PI/s ;
   xr=x+r*cos(p) ;
   yr=y+r*sin(p) ; 

   xstr[f]=xr ;
   ystr[f]=yr ;

   plotz(xr,yr) ;  // xr,yr are float

//   if (f>0) draw(xstr[f-1], ystr[f-1],xstr[f], ystr[f]);

  }
return 0 ;
}

void main (){

char key ;
int f ;
float r, s, x, y ;

enter_value:
printf("\xC\n");

//draw(  0, 0, 255,  0);
//draw(255, 0, 255,191);
//draw(255,191,  0,191);
//draw(  0,191,  0,  0);

printf(" plot a circle, first enter value's\neg r=50 , s=36 , x=127.5 , y=95.5\n\n");

printf("Enter r (max 95): ") ;
scanf("%f", &r ) ;
printf("Enter s (max512): ") ;
scanf("%f", &s ) ;
printf("Enter x : ") ;
scanf("%f", &x ) ;
printf("Enter y : ") ;
scanf("%f", &y ) ;

printf("\xC");
plotcircle( r, s, x , y );

printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("'y' plot\n'n' quit");
getakey:
key = getchar() ;
switch(key) {
case 'y' : goto enter_value ;
           break ;
case 'n' : return 0 ;
           break ;
default  : goto getakey ;
            }
}
One step closer to
https://worldofspectrum.org/forums/disc ... -its-tesla
and
https://www.theproblemsite.com/vortex/b ... multiplier
if you fill in multiplier 20 and amount on 23 you get a nice 3-D like grid !!
vortex 20-23
vortex 19-40


thank you !!
Post Reply