QPC2 MultiBASIC: Load SBASIC machine code function resident
QPC2 MultiBASIC: Load SBASIC machine code function resident
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)?
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)?
http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX

- janbredenbeek
- Super Gold Card
- Posts: 711
- Joined: Wed Jan 21, 2015 4:54 pm
- Location: Hilversum, The Netherlands
- Contact:
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
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.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)?
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
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:
Ciao Peter
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
http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX

- janbredenbeek
- Super Gold Card
- Posts: 711
- Joined: Wed Jan 21, 2015 4:54 pm
- Location: Hilversum, The Netherlands
- Contact:
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
I see some issues in your code:
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?
- 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.
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
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
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).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
Oops, thank you.
- 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.
Thank you, I wasn't sure. In this case I will correct the code and run the benchmark (see here) again.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
Yes, this will most probably be the problem as I think I have already loaded SB extensions in QPC2s MultiBASICs which survived NEW.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?
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
http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX

Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
I'm confused:
Why are you calling an (apparently) SBASIC job a "Mutibasic job"? It isn't.
Why are you calling an (apparently) SBASIC job a "Mutibasic job"? It isn't.
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
- janbredenbeek
- Super Gold Card
- Posts: 711
- Joined: Wed Jan 21, 2015 4:54 pm
- Location: Hilversum, The Netherlands
- Contact:
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Ah, that's the difference!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.
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
So an SBASIC daughter job is not the right way for testing. Never knew, that this happens. Any remarks for that in any documentation?
7000 4E75
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Early SMSQ/E manuals (the QXL manual, for example) were pretty clear about thisRalfR 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?
This was just some random manual I had lying around. I'm sure that later manuals also point this out clearly.
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Re: QPC2 MultiBASIC: Load SBASIC machine code function resident
Yes, but "NEW" removing all in a daughter job is not stated!
7000 4E75