Run a SuperBasic program from Assembler?

Anything QL Software or Programming Related.
User avatar
t0nyt
Gold Card
Posts: 390
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Run a SuperBasic program from Assembler?

Post by t0nyt »

Thanks everyone (I was doing so much wrong it was uncanny)

I seem to have a working program now that's resident and if I type Siri (just something unique for now) my test get's sent to the keyboard buffer to launch my menu

Many thanks again


User avatar
t0nyt
Gold Card
Posts: 390
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Run a SuperBasic program from Assembler?

Post by t0nyt »

t0nyt wrote: Fri Mar 29, 2024 4:12 pm Thanks everyone (I was doing so much wrong it was uncanny)

I seem to have a working program now that's resident and if I type Siri (just something unique for now) my test get's sent to the keyboard buffer to launch my menu

Many thanks again
This is the code I'm using, in case anyone wants to improve it (or use it)

It's based on a little routine in TK3 + extension wrapper code from Norman's assembly book.

But without all the advise I've received I couldn't of got it all working for a long time, so many thanks all

Code: Select all

         TITLE    Show Menu

         INCLUDE  'win2_dev_quanta_QDOS1_IN'
         INCLUDE  'win2_dev_quanta_MACRO_LIB'

BP.INIT  equ      $110
IO.QIN   equ      $E0

         SECTION CODE
start    lea      define,a1
         move.w   BP.INIT,a2
         jsr      (a2)
         rts

define   dc.w     1
         dc.w     MENU-*
         dc.b     4,'MENU'
         dc.w     0
         dc.w     0
         dc.w     0
         dc.b     0

MENU     lea      runcmd,a5         ; ptr to text

nextchar move.b   (a5)+,d1          ; get character
         cmp.b    #$FF,d1
         beq.s    sent              ; done
         move.l   a5,-(sp)
         bsr.s    doqin             ; send to buffer
         move.l   (sp)+,a5
         bra.s    nextchar

sent     rts

doqin    movem.l  a0/d1/d2,-(sp)
         QDOSMT$  MT.INF
         move.l   sv_keyq(a0),a2
         movem.l  (sp)+,a0/d1/d2
         VECTOR   IO.QIN,a4
         rts

runcmd   dc.b     'lrun win1_menu',$0A,$FF

         END
EDIT: VECTOR is a macro I added to MACRO_LIB

Code: Select all

VECTOR   MACRO A,B
         [.code]EXPAND
         MOVE.W [A],[B]
         JSR ([B])
         ENDM
Many thanks
Last edited by t0nyt on Sat Mar 30, 2024 10:19 am, edited 1 time in total.


User avatar
NormanDunbar
Forum Moderator
Posts: 2281
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: Run a SuperBasic program from Assembler?

Post by NormanDunbar »

Nice!

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
NormanDunbar
Forum Moderator
Posts: 2281
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: Run a SuperBasic program from Assembler?

Post by NormanDunbar »

If I may comment....

1. In QDOS/SMSQ, strings are defined this way, with a leading word determining the length, followed by the characters of the string.

Code: Select all

runcmd   dc.w    cmdEND-runcmd-2
              dc.b     'lrun win1_menu',$0A
cmdEND  equ *
Doing it this way means never having to count characters when you change the string contents. I think QMAC requires the "equ *" on the same line as the label.


2. In your loop, you then pick up the word before entering the loop, then send a single character, then decrement the counter and if not -1, yes that's minus one, not zero, skip back to the start. Something like the following untested code:

Code: Select all

MENU     lea runcmd,a5
         move.w (a5)+,D2            ; Counter of bytes in command.
         bra.s endLoop              ; Skip loop.


nextchar move.b   (a5)+,d1          ; get character
         move.l   a5,-(sp)
         bsr.s    doqin             ; send to buffer
         move.l   (sp)+,a5
         
endLoop  dbra     d2,nextchar       ; Loop until done.

sent     rts
So why skip the loop after getting the word count? Two reasons, the first is that we need to stop the loop at D2 = -1 and not at D2 = 0, so reducing the counter without copying a byte does this automagically. The second reason is, if the string just happened to be zero bytes long, improbably I know, but still possible, then the loop will end immediately without copying anything. I'm indebted to the late George Gwilt for this snippet, as I always did something like:

Code: Select all

pick up the word count.
Decrement it.
Enter the loop
   do stuff
dbra ...
Which meant that if the word I picked up was zero, my decrement made it -1,. then I would erroneously perform the task within the loop once, then decrement the counter to -2, which is not -1, so the loop would actually execute 65,536 times before reaching -1 again! Not good.

3. Instead of stacking A5 each time, if you have a spare unused address register, why not EXG A5,An before and after the call to doqin? It's quicker than using the stack. I'm indebted to Per Witte for that snippet. If you have spare registers, use them instead of the stack.


Anyway, I'm glad you kept at it and found a way to do it. Nicely done.


Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
t0nyt
Gold Card
Posts: 390
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Run a SuperBasic program from Assembler?

Post by t0nyt »

Thanks Norm, have taken that all on-board and the new tested code is below

I didn't do point 3 as I realised A0 was already being stacked so just used that (all the other Ax seem to get changed so didn't have anything to EXC to)

Many thanks

Code: Select all

         TITLE    Show Menu

         INCLUDE  'win2_dev_quanta_QDOS1_IN'
         INCLUDE  'win2_dev_quanta_MACRO_LIB'

BP.INIT  equ      $110
IO.QIN   equ      $E0

         SECTION CODE
start    lea      define,a1
         move.w   BP.INIT,a2
         jsr      (a2)
         rts

define   dc.w     1
         dc.w     MENU-*
         dc.b     4,'MENU'
         dc.w     0

         dc.w     0
         dc.w     0

MENU     lea      runcmd,a0         ; ptr to text
         move.w   (a0)+,d2          ; byte count
         bra.s    endLoop           ; skip loop

nextchar move.b   (a0)+,d1          ; get character
         bsr.s    doqin             ; send to buffer

endLoop  dbra     d2,nextchar       ; loop if not done
         rts                        ; done

doqin    movem.l  a0/d1/d2,-(sp)
         QDOSMT$  MT.INF
         move.l   sv_keyq(a0),a2
         movem.l  (sp)+,a0/d1/d2
         VECTOR   IO.QIN,a4
         rts

runcmd   dc.w     cmdEND-runcmd-2
         dc.b     'lrun win1_menu',$0A
cmdEND   equ      *

         END


User avatar
NormanDunbar
Forum Moderator
Posts: 2281
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: Run a SuperBasic program from Assembler?

Post by NormanDunbar »

And, for your next iteration, add a config block so that the command to be typed in is configurable without having to edit and reassemble the code! :D :D :D :D


By the way, there was nothing wrong with your code, it worked. My comments were there to point you at "better" QDOS specific stuff.

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
t0nyt
Gold Card
Posts: 390
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Run a SuperBasic program from Assembler?

Post by t0nyt »

NormanDunbar wrote: Sat Mar 30, 2024 4:10 pm And, for your next iteration, add a config block so that the command to be typed in is configurable without having to edit and reassemble the code! :D :D :D :D
Maybe a future bit of coding as it does what I need for now (though I do have ideas floating around my head for expanding what it does)

But out of interest how would you perceive the config working from a "good ql practice" point of view please?

Many thanks


User avatar
pjw
QL Wafer Drive
Posts: 1316
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: Run a SuperBasic program from Assembler?

Post by pjw »

Just a heads up: A bad typo at

Code: Select all

define   dc.w     1
         dc.w     MENU-*
         dc.b     4,'MENU'
..
It should be something like

Code: Select all

define   dc.w     1
         dc.w     MENU-*
         dc.b     4,'MENU',0
..
to make the line even.
I was altogether intrigued by the exercise so here's my take:

Code: Select all

;         TITLE    Show Menu

        section code

         INCLUDE  'win6_a_qmac_qdos1_in'
         INCLUDE  'win6_a_qmac_MACRO_LIB'

BP.INIT  equ      $110
IO.QIN   equ      $E0

         SECTION CODE
start    lea      define,a1
         move.w   BP.INIT,a2
         jmp      (a2)

define   dc.w     1
         dc.w     MENU-*
         dc.b     4,'MENU '
         dc.w     0,0,0

MENU
         QDOSMT$  MT.INF
         move.l   sv_keyq(a0),a2

         move.w   IO.QIN,a4	    ;couldnt find the VECTOR macro, but never mind..

         lea.l    runcmd,a5         ; ptr to text
         move.w  (a5)+,d4
         bra.s   lend

nextchar move.b   (a5)+,d1          ; get character
         jsr      (a4)              ; send to buffer
lend
         dbra     d4,nextchar

sent     moveq #0,d0
         rts

runcmd   dc.w    rcend-runcmd
         dc.b   'print "Hello world!"',$0A
rcend
         dc.w    0

         END
The code is re-styled for the Qmac assembler.

Happy coding!


Per
dont be happy. worry
- ?
User avatar
t0nyt
Gold Card
Posts: 390
Joined: Wed Nov 22, 2023 6:46 pm
Location: UK

Re: Run a SuperBasic program from Assembler?

Post by t0nyt »

pjw wrote: Sat Mar 30, 2024 5:37 pm Just a heads up: A bad typo at

Code: Select all

define   dc.w     1
         dc.w     MENU-*
         dc.b     4,'MENU'
..
It should be something like

Code: Select all

define   dc.w     1
         dc.w     MENU-*
         dc.b     4,'MENU',0
..
to make the line even.
Hi Per,

I can see what you mean about the missing byte to force the next line onto a word boundary, so have done that to be safe

But the GST QMAC manual I have seems to say it automatically adjusts and puts DC.W/DC.L onto word boundaries, which is why I assume my code worked as is? (or it was pure luck)

Many thanks


User avatar
pjw
QL Wafer Drive
Posts: 1316
Joined: Fri Jul 11, 2014 8:44 am
Location: Norway
Contact:

Re: Run a SuperBasic program from Assembler?

Post by pjw »

t0nyt wrote: Sat Mar 30, 2024 5:56 pm <>I can see what you mean about the missing byte to force the next line onto a word boundary, so have done that to be safe

But the GST QMAC manual I have seems to say it automatically adjusts and puts DC.W/DC.L onto word boundaries, which is why I assume my code worked as is? (or it was pure luck)
In your original code you had:

Code: Select all

define   dc.w     1
         dc.w     MENU-*
         dc.b     4,'MENU'
         dc.w     0
         dc.w     0
         dc.w     0
         dc.b     0   <-------- !
You may be right. Or it was that last byte that saved you! Best stick to best practices. Not all assemblers work the same so it could lead to tears..

Nowadays I mainly use the proc macro for this, as found with the SMSQ/E sources. Saves a lot of faffing around.

In fact, if youre starting out with QL assembler now, it may altogether be better to use the SMSQ/E nomenclature and macros. Throw out your Adrian Dickens and Pennel books; theyre mainly a re-hash of The Qdos/SMSQ Reference Guide - the only reference you need.

(Im on a mission here, so please excuse ;) )


Per
dont be happy. worry
- ?
Post Reply