Page 1 of 3
QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Sat Aug 16, 2025 9:27 pm
by ql_freak
I have now written a strlen%() function which returns the length of a string without using CA.GTSTRING(!). Works on QPC2 and sQLux but only with string literals, expressions and variables not with string array variables (IMHO a strange behaviour).
Problem: When loading with LRESPR in a MultiBASIC I can call it with "PRINT STRLEN%('123')" and the output is 3. But if I enter NEW the STRLEN% function isn't available anymore.
Is this normal?
Is it possible to load SBASIC extensions resident in a MultiBASIC job (without loading it in job 0,0)?
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Sat Aug 16, 2025 10:07 pm
by janbredenbeek
ql_freak wrote: Sat Aug 16, 2025 9:27 pm
Is it possible to load SBASIC extensions resident in a MultiBASIC job (without loading it in job 0,0)?
Should be possible, as long as they contain
only SB extensions (not device drivers etc). They should survive a NEW, but disappear when you kill the MB job.
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Sun Aug 17, 2025 12:32 am
by ql_freak
Hi Jan,
unfortunately here not :-( I LRESPR it and after a NEW it is gone. Have not tested it on Minerva's (UQLX or sQlux) MultiBASICs, but as far as I remember extensions loaded with LRERPR are resident in a Minerva MultiBASIC job.
Here the source:
Code: Select all
; Simplified test example to get the first parameter of a SB function
; (which must be a string) without CA.GTSTR and returns length of string
BP_INIT equ $110 ;Vector BP.INIT to define MC PROC/FNs
BV_VVBAS equ $28 ;SB variables value area
BV_CHRIX equ $11a ;Vector BV.CHRIX
BV_RIP equ $58 ;BASIC storage for RI stack
NTVVAPTR equ 4 ;offset of ptr to value in VVA in nametable
QSTR equ 1 ;QDOS STRing
QINT equ 3 ;QDOS INteger (WORD, i.e. short in C!)
SVBITCLR equ $DFFF ;andi.w SVBITCLR,sr switches to User mode
bra addSBext
strlen move.l NTVVAPTR(a6,a3.l),d7 ;d7 should now point to the string
;parameter in the variables value area, i.e.
;d7(a6,BV_VVBAS.l) - which is not possible
;in 68K assmbler(!) - should point to the
;value of the string parameter
;So we must switch into Supervisor mode to calculate a (relative to a6) pointer
;to the value:
trap #0 ;switch to Supervisor mode
move.l BV_VVBAS(a6),a3 ;0(a6,a3.l) should now point to BV.VVBAS
adda.l d7,a3 ;0(a6,a3.l) should now point to the passed
;string parameter (in the VVA)
andi.w #SVBITCLR,sr ;switch back to User mode
move.w 0(a6,a3.l),d7 ;d7 should now hold string length
;Following code must be adjusted, copied from reflection.asm:
move.w BV_CHRIX,a0 ;We need space on RI stack
moveq #2,d0 ;2 bytes required for string length
move.l BV_RIP(a6),a1 ;Per says: Only QDOS needs this move
jsr (a0)
;Per says we must correct the stack pointer with:
subq.l #2,BV_RIP(a6) ;this is where the real stack top is so
;here's where we need to take the space
move.l BV_RIP(a6),a1 ;Restore RI stack pointer
move.w d7,0(a6,a1.l) ;Push line no. (short int) ...
;subq.l #2,a1 ;... on RI stack AND (don't forget!):
moveq #QINT,d4 ;... set return type (integer [short])
moveq #0,d0 ;No error
rts ;Return to SuperBASIC
addSBext lea SBext,a1 ;Load Effective Adress of SB PROC/FNs
move.w BP_INIT,a2 ;We must call SB vector BP.INIT
jmp (a2) ;DO IT!
SBext dc.w 0,0 ;No PROCs, END of PROCedure definitions
dc.w 1 ;1 FuNction
dc.w strlen-*
dc.b 7,'STRLEN%'
dc.w 0
Ciao Peter
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Sun Aug 17, 2025 11:55 am
by janbredenbeek
I see some issues in your code:
- No check if the parameter is a string, or if there's even a parameter at all
- The parameter to bv.chrix should be in d1, not d0. You're now requesting a random value, which might be negative and corrupt the system.
Also, it's not necessary to enter supervisor mode since the addresses are al relative to A6 and won't change in the same SB job.
Code: Select all
move.l 4(a6,a3.l),d7 ; offset to VVBAS of value
add.l bv_vvbas(a6),d7 ; add VVBAS, address is still relative to a6!
move.w (a6,d7.l),d7 ; now d7 holds length
I could not reproduce your symptom with NEW, a function added with lrespr remained in MB even after a NEW. Maybe it's because your wrong call to bv.chrix corrupted the system?
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Mon Aug 18, 2025 8:09 am
by ql_freak
janbredenbeek wrote: Sun Aug 17, 2025 11:55 am
I see some issues in your code:
- No check if the parameter is a string, or if there's even a parameter at all
I know, but this is just a function I have written (as simple as possible) to perhaps ask here, why I don't get the pointer to the string parameter (I had a lot of problem with that and didn't know if I will succeed) and it's primarily a benchmark, to test if fetching the parameter without CA.GETSTR will be faster (which it seems not).
- The parameter to bv.chrix should be in d1, not d0. You're now requesting a random value, which might be negative and corrupt the system.
Oops, thank you.
Also, it's not necessary to enter supervisor mode since the addresses are al relative to A6 and won't change in the same SB job.
Code: Select all
move.l 4(a6,a3.l),d7 ; offset to VVBAS of value
add.l bv_vvbas(a6),d7 ; add VVBAS, address is still relative to a6!
move.w (a6,d7.l),d7 ; now d7 holds length
Thank you, I wasn't sure. In this case I will correct the code and run the benchmark (see
here) again.
I could not reproduce your symptom with NEW, a function added with lrespr remained in MB even after a NEW. Maybe it's because your wrong call to bv.chrix corrupted the system?
Yes, this will most probably be the problem as I think I have already loaded SB extensions in QPC2s MultiBASICs which survived NEW.
EDIT (addendum):
I have now corrected strlen_asm and also the benchmark program (see
here). Albeit the switch to supervisor mode has been removed, the result is the same. The version with LEN is faster than the one with STRLEN% (which does NOT use CA.GTSTR to fetch the string parameter).
Unfortunately albeit now using D1 for BV.CHRIX (see Jans corrections) if LRESPRed in a QPC2 MultiBASIC, the extension is gone after a NEW (LOAD) here. Jan does not have this problem. Here the corrected assembler code:
Code: Select all
;Simplified test example to get the first parameter of a SB function
;(which must be a string) without CA.GTSTR and returns length of string.
;NOTE: This is just for a benchmark, to test if fetching a string parameter
; without using CA.GTSTRING is faster. Therefore absolutely no
; parameter checking. Do NOT use this function in production code!
;NOTE 2: No '.' used for e.g. BV.VVBAS but underscore, as not all assemblers
; support '.' in label names.
BP_INIT equ $110 ;Vector BP.INIT to define MC PROC/FNs
BV_VVBAS equ $28 ;SB variables value area
BV_CHRIX equ $11a ;Vector BV.CHRIX
BV_RIP equ $58 ;BASIC storage for RI stack
NTVVAPTR equ 4 ;offset of ptr to value in VVA in nametable
QSTR equ 1 ;QDOS STRing
QINT equ 3 ;QDOS INteger (WORD, i.e. short in C!)
SVBITCLR equ $DFFF ;andi.w SVBITCLR,sr switches to User mode
bra addSBext
strlen move.l NTVVAPTR(a6,a3.l),d7 ;d7 should now point to the string
;parameter in the variables value area, i.e.
;d7(a6,BV_VVBAS.l) - which is not possible
;in 68K assmbler(!) - should point to the
;value of the string parameter
;Jan Breedenbeck says it's NOT necessary to switch to SuperVisor mode:
;So we must switch into Supervisor mode to calculate a (relative to a6) pointer
;to the value:
; trap #0 ;switch to Supervisor mode
move.l BV_VVBAS(a6),a3 ;0(a6,a3.l) should now point to BV.VVBAS
adda.l d7,a3 ;0(a6,a3.l) should now point to the passed
;string parameter (in the VVA)
; andi.w #SVBITCLR,sr ;switch back to User mode
move.w 0(a6,a3.l),d7 ;d7 should now hold string length
move.w BV_CHRIX,a0 ;We need space on RI stack
moveq #2,d1 ;2 bytes required for string length
move.l BV_RIP(a6),a1 ;Per says: Only QDOS needs this move
jsr (a0)
;Per says we must correct the stack pointer with:
subq.l #2,BV_RIP(a6) ;this is where the real stack top is so
;here's where we need to take the space
move.l BV_RIP(a6),a1 ;Restore RI stack pointer
move.w d7,0(a6,a1.l) ;Push line no. (short int) ...
;subq.l #2,a1 ;... on RI stack AND (don't forget!):
moveq #QINT,d4 ;... set return type (integer [short])
moveq #0,d0 ;No error
rts ;Return to SuperBASIC
addSBext lea SBext,a1 ;Load Effective Adress of SB PROC/FNs
move.w BP_INIT,a2 ;We must call SB vector BP.INIT
jmp (a2) ;DO IT!
SBext dc.w 0,0 ;No PROCs, END of PROCedure definitions
dc.w 1 ;1 FuNction
dc.w strlen-*
dc.b 7,'STRLEN%'
dc.w 0
;END OF FILE
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Mon Aug 18, 2025 12:32 pm
by tofro
I'm confused:
Why are you calling an (apparently) SBASIC job a "Mutibasic job"? It isn't.
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Mon Aug 18, 2025 4:47 pm
by janbredenbeek
tofro wrote: Mon Aug 18, 2025 12:32 pm
I'm confused:
Why are you calling an (apparently) SBASIC job a "Mutibasic job"? It isn't.
Ah, that's the difference!
A NEW in Minerva's MB clears out the name table except for machine code procedures and functions already loaded (and inherited).
A NEW in SBASIC clears out the whole name table, and machine code procedures and functions get copied from the main SBASIC as you use them. But if you've loaded them locally, they will simply go away!
So ql_freak was in fact testing SBASIC...
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Mon Aug 18, 2025 5:01 pm
by RalfR
So an SBASIC daughter job is not the right way for testing. Never knew, that this happens. Any remarks for that in any documentation?
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Mon Aug 18, 2025 5:48 pm
by tofro
RalfR wrote: Mon Aug 18, 2025 5:01 pm
So an SBASIC daughter job is not the right way for testing. Never knew, that this happens. Any remarks for that in any documentation?
Early SMSQ/E manuals (the QXL manual, for example) were pretty clear about this
This was just some random manual I had lying around. I'm sure that later manuals also point this out clearly.
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Posted: Mon Aug 18, 2025 6:16 pm
by RalfR
Yes, but "NEW" removing all in a daughter job is not stated!