Parameterising USR calls

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
Post Reply
sirmorris
Posts: 2811
Joined: Thu May 08, 2008 5:45 pm

Parameterising USR calls

Post by sirmorris »

It's often useful to pass a parameter to a machine code function. The usual way is to POKE it into memory before calling. I remember some time another cool technique that allowed you to tack extra data on to the USR call. I'm sure of it.

Code: Select all

PRINT USR nnnnn;"parameter data in here"
was one way. The machine-code routine would somehow fool the interpreter into ignoring the following string, so no actual print output occurred.

Is there a way to pass data into M/C and still use the return value? I.E.

Code: Select all

LET X = USR nnnnn + (something that's ignored)
??
User avatar
siggi
Posts: 990
Joined: Thu May 08, 2008 9:30 am
Location: Wetterau, Germany
Contact:

Re: Parameterising USR calls

Post by siggi »

sirmorris wrote: Wed Jun 14, 2017 3:56 pm It's often useful to pass a parameter to a machine code function. The usual way is to POKE it into memory before calling. I remember some time another cool technique that allowed you to tack extra data on to the USR call. I'm sure of it.
No, the usr-call does not allow parameters

Code: Select all

PRINT USR nnnnn;"parameter data in here"
was one way. The machine-code routine would somehow fool the interpreter into ignoring the following string, so no actual print output occurred.
From the point of view of the syntax checker, those "parameter data" were parameters of the PRINT command, which allows an unlimited number of arguments, while USR dos not allow any. The usr-program then takes the PRINT-parameters for its own usage ....
Is there a way to pass data into M/C and still use the return value? I.E.

Code: Select all

LET X = USR nnnnn + (something that's ignored)
No, that is not possible. The syntax checker will not allow entry of that line.

But you could also use PRINT as written before: use
PRINT USR nnn, param1, param2, ...., E

and let your usr-program write the return value into e. g. the last given paramater (e.g. BASIC variable E) and then cancel the PRINT statement as usual (RST 08, $FF).

Regards
Siggi
My ZX81 web-server: online since 2007, running since dec. 2020 using ZeddyNet hardware
http://zx81.ddns.net/ZxTeaM
sirmorris
Posts: 2811
Joined: Thu May 08, 2008 5:45 pm

Re: Parameterising USR calls

Post by sirmorris »

That's just the ticket. Thanks Siggi!
User avatar
PokeMon
Posts: 2264
Joined: Sat Sep 17, 2011 6:48 pm

Re: Parameterising USR calls

Post by PokeMon »

Maybe this helps - this is a (relocatable) driver to handle VDRIVE commands and is usually called with PRINT USR 8129;"COMMAND XY"

The program has 3 different entry points to be used either from command line, BASIC program or another machine code program. The register A is used a bit strange to minimize this code in size to handle all. Feel free to use for your purpose or parts of it. ;)

The first RST $20 just skips one byte (";") and the following CALL to $0F55 calculates any following expression and give the result, can be a string or a numeric value and stored either as 5 byte numeric value on stack or as string. $0F55 will give as return the final expression result from stack and A/BC/DE contain the 5 byte FP value or a pointer to a string depending on the A register and BC contains length of string and DE contains the address of the string. $0F55 is quite powerful function allowing weirdest set of parameters and calculations.

Code: Select all

format zx81 as 'rom'
;LISTON
                                // driver code for using vdrive software with ZXmaster
                                // usually loaded at 8192 ($2000) but relocatable code for any address
vdrive:
        XOR     A               // entry point for command line usage (default entry point 8192)
        JR      .basic
        XOR     A               // entry point for BASIC program usage (default entry point 8195)
        JR      .basicp
        NOP                     // version coding of vdrive driver code (version 0)
        LD      A,$FE           // entry point for assembly program usage (default entry point 8198)
.basicp:
        INC     A               // coded entry point in A, 0=command line, 1=basic program, -1=assembly program
.basic:
        PUSH    AF              // save entry point
        RST     $20             // read parameters
        CALL    $0F55           // calculate expression of parameters
        LD      A,($4001)
        ADD     A,A             // check bit 6, result type, 0=string, 1=numeric
        JP      M,$0D9A         // stop with error
        JR      $FE             // endless loop till command is processed from ZXmaster
        POP     AF
        RLCA                    // copy bit 7 into carry
        LD      A,($4000)       // get already error code but keep flag register :-)
        JR      NZ,.basip       // jump if basic/assembly program entry for quite output
        INC     A               // check if error occured and get correct error code
        JR      NZ,.baserr
        RST     $08             // success message and back to BASIC
        db      $FF
.basip:
        JR      C,.mcode        // jump if assembly program option
        INC     A               // retrieve error code
        LD      ($4032),A       // and store in SEED variable (16434)
        RST     $08             // return to BASIC with no error (hidden in variable)
        db      $FF
.mcode:
        INC     A               // retrieve error code
        LD      ($4032),A       // and store in SEED variable (16434)
        LD      A,$FF           // clear system error code for continue assembly program (hidden error)
        LD      ($4000),A
        RET                     // return to calling program
.baserr:
        LD      B,0             // just cleared as BC is used for string length while not more than 255 bytes
        CALL    $0AC8           // get runtime address through calling official ZX81 BASIC routine
.bascalc:
        LD      DE,errnodisk-.bascalc   // get offset to error message
        CP      $07
        JR      Z,@f                    // no disk error
        LD      DE,errnofile-.bascalc
        CP      $03
        JR      Z,@f                    // no file error
        LD      DE,errsyntax-.bascalc   // offset to syntax error (default)
@@:     ADD     HL,DE           // calculate real address from runtime address and offset
        LD      C,(HL)          // read length of string
        INC     HL
        EX      DE,HL           // start address of string in DE, length in BC
        CALL    $0B6B           // official print string routine from ZX81 BASIC rom
        EX      DE,HL           // get back address to return to BASIC with error code
        JP      (HL)            // finish
errsyntax:
.cnt:   db      .end-.beg       // size of message
.beg:
        dbzx    'SYNTAX ERROR'  // message
.end:
        RST     $08             // return to BASIC
        db      $00             // BASIC error code 1
errnofile:
.cnt:   db      .end-.beg
.beg:
        dbzx    'FILE NOT FOUND'
.end:
        RST     $08
        db      $02             // BASIC error code 3
errnodisk:
.cnt:   db      .end-.beg
.beg:
        dbzx    'DISK NOT FOUND'
.end:
        RST     $08
        db      $06             // BASIC error code 7
dr beep
Posts: 2076
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Parameterising USR calls

Post by dr beep »

On the ZX Spectrum I always undid the call of USR by taking registers/pointers of the stack,then scanned for parameters and always ended with a ; so on normal RET the interpreter would think it is at the ; after USR. Program continued without error/OK.
User avatar
XavSnap
Posts: 1941
Joined: Sat May 10, 2008 4:23 pm
Location: 'Zx81 France' Fb group.

Re: Parameterising USR calls

Post by XavSnap »

Xavier ...on the Facebook groupe : "Zx81 France"(fr)
sirmorris
Posts: 2811
Joined: Thu May 08, 2008 5:45 pm

Re: Parameterising USR calls

Post by sirmorris »

I think I see what is being done there. I think I would like a more general approach, the ability to use any variable as the destination for a command. Things get tricky when you have to rely on order of allocation or ensuring that only a particular variable is used. That's a nice technique though!
Post Reply