Id like to explore differences between the various flavours of "QL" BASICs: SuperBASIC, MBASIC + MB and SBASIC and daughter BASICs. In this sense, QLib and Turbo could be considered dialects of QL BASIC.
The reasons are: To better understand how they work, and as an aid to improving the quality of programs and avoiding problems caused by compatibility issues.
Qdos beginners should be aware that these discussions (if any) are exploratory and therefore potentially misleading. The official documentation is 98% bug free, but much of it is extremely terse, and vast tracts of information, particularly on the inner workings, is lacking.
So, dyed-in-the-wool tinkerers and new explorers alike, I hope youll share your discoveries!
QL BASICs
QL BASICs
Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
Re: QL BASICs
So Ill kick off with with a continuation from a previous thread, "Command line parameters". I see a lot of programmers starting out with programming for Qdos/S*Basic, myself included, getting tangled in the RI stack, fetching and returning parameters, moving stuff around, padding strings, keeping it all nice and tidy. A lot of that is often error prone, inefficient, and unnecessary. (And a lot of that comes, I believe, from some of the early tutorial books, which the publishers wanted to get out in a rush, without their authors having had the time to familiarise themselves with their subject.)
What I want to say will be shorter, and hopefully more understandable if I just present it as code:
Obviously this code doesnt do anything sensible, but a keyword like DOUBLE% int% based on this method might be useful. The alternative is getting the string on the stack (involving copying the whole string), processing it and then returning it as a function or via the parameter (both involving copying again).
The purpose of this thread is to explore workings and differences between Basics, so in the following Im asking for a "peer-review" of the following assumptions (best described in code, again.):
Ive tested these in the systems mentioned, looking for corruption or memory leaks, but all seems fine. I may just have been lucky.
If theres an interest, Ill update this info if and when..
Per
What I want to say will be shorter, and hopefully more understandable if I just present it as code:
Code: Select all
* Sample code to demonstrate simplified parameter handling
* Ideal for simple integer maths or string handling where one or more
* strings dont change length (eg for reading only)
*
* Compatible with QDOS, Minerva and SMSQ/E
* Works with Qlib but not Turbo(?)
*
* a$ = 'abcXYZ': TOGGLE_CASE a$: PRINT a$
*
* a$ = 'abcXYZ': TOGGLE_CASE a$ & 'x': REMark ???
section code
filetype 0
include dev8_keys_qlv
include dev8_keys_sbasic
include dev8_keys_err
lea.l key,a1
move.w sb.inipr,a2
jmp (a2)
key
dc.w 2 one long proc name
dc.w ut_tc-*
dc.b 11,'TOGGLE_CASE'
dc.w 0,0,0 endprocs, no fns
ut_tc
lea.l 8(a3),a1 point past first par
cmp.l a1,a5 exactly one par?
bne.s err_bp no..
cmpi.w #nt.varst,nt_usetp(a6,a3.l) pure string?
bne.s err_bp nope
move.l nt_value(a6,a3.l),a1 value pointer
adda.l sb_datab(a6),a1 a1 -> string
move.w (a6,a1.l),d0 d0.w = len
addq.l #2,a1
bra.s tc_lend
tc_lp
eor.b #%100000,(a6,a1.l) A..z only
addq.l #1,a1
tc_lend
dbra d0,tc_lp
moveq #0,d0
rts back to basic
err_bp
moveq #err.ipar,d0
rts
*
end
The purpose of this thread is to explore workings and differences between Basics, so in the following Im asking for a "peer-review" of the following assumptions (best described in code, again.):
Code: Select all
* Sample code to demonstrate simplified parameter handling
* Ideal for simple integer maths or string handling where one or more
* strings dont change length (eg for reading only)
*
* Compatible with SMSQ/E and QLib only
*
* a$ = 'abcXYZ': TOGGLE_CASE a$: PRINT a$
*
* a$ = 'abcXYZ': TOGGLE_CASE a$ & 'x': REMark ???
section code
filetype 0
include dev8_keys_qlv
include dev8_keys_sbasic
include dev8_keys_err
lea.l key,a1
move.w sb.inipr,a2
jmp (a2)
key
dc.w 2 one long proc name
dc.w ut_tc-*
dc.b 11,'TOGGLE_CASE'
dc.w 0,0,0 endprocs, no fns
ut_tc
lea.l 8(a3),a1 point past first par
cmp.l a1,a5 exactly one par?
bne.s err_bp no..
cmpi.w #nt.varst,nt_usetp(a6,a3.l) pure string?
bne.s err_bp nope
move.l nt_value(a6,a3.l),a1 a1 -> string
move.w (a1)+,d0 d0.w = len
bra.s tc_lend
tc_lp
eor.b #%100000,(a1)+ A..z only
tc_lend
dbra d0,tc_lp
moveq #0,d0
rts back to basic
err_bp
moveq #err.ipar,d0
rts
*
end
If theres an interest, Ill update this info if and when..
Per
Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
Re: QL BASICs
I'm not sure I understand the conversation. You mention QL Basics, but the sample code that is listed is in Assembly. What does this assembly code have to do with QL Basics? Are you creating a new keyword for SuperBasic?
Re: QL BASICs
Per,
ah. Call by reference. Interesting.
My personal opinion would be your first method is the "valid" one for all QDOS derivates - It uses documented offsets only and makes sure all accesses are done relative to a6.
What you do in your second example is potentially dangerous - Although a change of a6 is not likely in your specific example that doesn't do much while handling nona6 relative pointers, in a bit more complicated one (like e.g. heavy fiddling with the maths stack on complicated calculations and allocating more space to it that doesn't fit into the pre-allocated area), your a1 that points to the string value might become invalid. You rarely see S*BASICs data space move in systems well equipped with memory like emulators or Qx0, but on the BB that happens quite often.
So, the second example would be potentially dangerous and prone to (infrequent) crashes.
Why is the first one "better"?
moves an a6-relative pointer to a1
adds an offset to it (so still relative to a6)
access to the string is relative to a6
Your second example is likely to break at
where you transform an a6-relative address into an absolute EA.
Tobias
ah. Call by reference. Interesting.
My personal opinion would be your first method is the "valid" one for all QDOS derivates - It uses documented offsets only and makes sure all accesses are done relative to a6.
What you do in your second example is potentially dangerous - Although a change of a6 is not likely in your specific example that doesn't do much while handling nona6 relative pointers, in a bit more complicated one (like e.g. heavy fiddling with the maths stack on complicated calculations and allocating more space to it that doesn't fit into the pre-allocated area), your a1 that points to the string value might become invalid. You rarely see S*BASICs data space move in systems well equipped with memory like emulators or Qx0, but on the BB that happens quite often.
So, the second example would be potentially dangerous and prone to (infrequent) crashes.
Why is the first one "better"?
Code: Select all
move.l nt_value(a6,a3.l),a1
Code: Select all
adda.l sb_datab(a6),a1
access to the string is relative to a6
Your second example is likely to break at
Code: Select all
move.l nt_value(a6,a3.l),a1 a1 -> string
Tobias
Last edited by tofro on Mon Apr 13, 2015 9:23 pm, edited 2 times in total.
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Re: QL BASICs
Tim,swensont wrote:I'm not sure I understand the conversation. You mention QL Basics, but the sample code that is listed is in Assembly. What does this assembly code have to do with QL Basics? Are you creating a new keyword for SuperBasic?
Per is referring to S*BASIC extensions written in assembler and the passing of parameters back and forth between the two languages. (And he's picked the most complicated example I can imagine

Tobias
ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Re: QL BASICs
Tim, Im trying to find out how the BASICs work. Differences between the various flavours sometimes cause compatibility problems. At the same time, Id like to explore and exploit the advances, not be held back by conventions when there is a better way of doing something. Extending S*Basic is a particular hobby of mine, hence my angle.
Tobias, thanks for your comprehensive input. To the specifics of my examples, some years ago I wrote some string processing functions. While tracing similar functions in SMSQ/E with a debugger,trying to understand why they were so much faster than mine, I discovered that Tony was cheating! His code acted like he was writing for QLib which, as you know, has a fixed a6. QPC was painfully slow in those days, so for my SMSQ/E-only project, using the same shortcuts made sense to me. Afterall, the Architect thought it was ok. However, my programming activities stopped abruptly at that time. I now have a bit more time, and, considering all the activity in other departments (retro, hardware, software, wiki, etc) I hope there might be a climate for exploring and documenting. The examples given were bizarre perhaps, but not complicated. On the contrary, I hope.
I agree this could be risky behaviour, but that is because I dont understand how SBasic allocates memory in its various stack and heaps. Does anyone here? I believe I had a reasonably good idea about SuperBASIC, but SBasic is different. It is possible to find out, but it will take time for the likes of me.
Tobias, thanks for your comprehensive input. To the specifics of my examples, some years ago I wrote some string processing functions. While tracing similar functions in SMSQ/E with a debugger,trying to understand why they were so much faster than mine, I discovered that Tony was cheating! His code acted like he was writing for QLib which, as you know, has a fixed a6. QPC was painfully slow in those days, so for my SMSQ/E-only project, using the same shortcuts made sense to me. Afterall, the Architect thought it was ok. However, my programming activities stopped abruptly at that time. I now have a bit more time, and, considering all the activity in other departments (retro, hardware, software, wiki, etc) I hope there might be a climate for exploring and documenting. The examples given were bizarre perhaps, but not complicated. On the contrary, I hope.
I agree this could be risky behaviour, but that is because I dont understand how SBasic allocates memory in its various stack and heaps. Does anyone here? I believe I had a reasonably good idea about SuperBASIC, but SBasic is different. It is possible to find out, but it will take time for the likes of me.
Per
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen
I love long walks, especially when they are taken by people who annoy me.
- Fred Allen