QL BASICs

Anything QL Software or Programming Related.
Post Reply
User avatar
pjw
QL Wafer Drive
Posts: 1299
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

QL BASICs

Post by pjw »

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!


Per
dont be happy. worry
- ?
User avatar
pjw
QL Wafer Drive
Posts: 1299
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: QL BASICs

Post by pjw »

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:

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
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.):

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
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


Per
dont be happy. worry
- ?
swensont
Forum Moderator
Posts: 252
Joined: Tue Dec 06, 2011 3:30 am
Location: SF Bay Area
Contact:

Re: QL BASICs

Post by swensont »

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?


User avatar
tofro
Font of All Knowledge
Posts: 2700
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: QL BASICs

Post by tofro »

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"?

Code: Select all

move.l nt_value(a6,a3.l),a1 
moves an a6-relative pointer to a1

Code: Select all

adda.l sb_datab(a6),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

Code: Select all

move.l nt_value(a6,a3.l),a1     a1  -> string
where you transform an a6-relative address into an absolute EA.

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
User avatar
tofro
Font of All Knowledge
Posts: 2700
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: QL BASICs

Post by tofro »

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?
Tim,

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 :D )

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
pjw
QL Wafer Drive
Posts: 1299
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: QL BASICs

Post by pjw »

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.


Per
dont be happy. worry
- ?
Post Reply