* * * * * The definitive guide to writing assembly language subroutines for Color BASIC There's nothing quite like documenting 40 year old technology, but hey, retro computing is now popular, so why not? Anyway, since I've modified my assembler to make it easier to write assembly subroutines for Color BASIC (Beginner's All-purpose Symbolic Instruction Code) [1], I've been doing a deep dive into the nuances of doing so. This post will cover the method for plain Color BASIC; Extended Color BASIC, which does things a bit differently, will be covered in another post [2]. The information in _Getting Started With Color BASIC_ [3] is a bit light. It covers how to use POKE to load the object code into memory, and how to define the address for use by the USR function by poking that address into memory, but that's it. It gives one sample program: -----[ Assembly ]----- LOOP1 JSR [POLCAT] ;POLL FOR A KEY BEQ LOOP1 ;IF NONE, RETRY CMPA #10 ;CTRL KEY (DN ARW)? BNE OUT ;NO, SO EXIT LOOP2 JSR [POLCAT] ;YES, SO GET NEXT KEY BEQ LOOP2 ;IF NONE, RETRY CMPA #65 ;IS IT A-Z? BLT OUT ;IF 'Z', no processing bhi .out adda #13 ; ROT-13 the character cmpa #'Z' bls .out suba #26 .out sta ,x+ ; save character in new string decb ; continue if more bne .loop jmp GIVBF ; return result to BASIC buffer rmb 255 ; maximum length of string end -----[ END OF LINE ]----- But that will fail if you attempt to ROT-13 multiple strings at the same time. A better way is to call RSVPSTR (again, found on the Unravelled series and given a name by me and located at address $B56D) which will reserve space from the dynamic string pool maintained by BASIC. It expects the amount of space in the B register, and if it returns (it can error out with an “OS” (out of string space) error), it returns the length in the B register, and the space in the X register. So now our function looks like: -----[ Assembly ]----- rot13 jsr CHKSTR ; ensure a string ldy FP0 + 2 ; get string descriptor ldb ,y ; get length jsr RSVPSTR ; reserve new string of said length ldu 2,y ; get original string stx 2,y ; save pointer to new string in descriptor .loop lda ,u+ ; get character cmpa #'A' ; if < 'A', no processing blo .out cmpa #'Z' ; if > 'Z', no processing bhi .out adda #13 ; ROT-13 the character cmpa #'Z' bls .out suba #26 .out sta ,x+ ; save character in new string decb ; continue if more bne .loop jmp GIVBF ; return result to BASIC buffer rmb 255 ; maximum length of string end -----[ END OF LINE ]----- The only downside is that you have to use a string variable when calling the routine. You could give it a string literal: -----[ ColorBASIC ]----- 100 X=USR("THIS IS A STRING") -----[ END OF LINE ]----- While that won't crash, you won't have access to the newly created string either. Just something to keep in mind. One other thing to keep in mind—don't change the actual string data itself, for doing so will cause undefined results. For instance, if you call USR() with a string literal: -----[ ColorBASIC ]----- 110 X=USR("HELLO, WORLD!") -----[ END OF LINE ]----- The pointer in the string descriptor points directly into the source code! So you can change the contents of the descriptor, but not the string itself. Also to keep in mind, when you call USR() with a number, you don't have to convert it to an integer. You could call into some Color BASIC floating point routines if you know where they are. So, for example: -----[ Assembly ]----- CHKNUM equ $B143 FMULx equ $BACA org $7F00 twopi jsr CHKNUM ; check for number input ldx #.pi jmp FMULx .pi .float 3.14159265358979323846 end -----[ END OF LINE ]----- To aid in writing such code, I have written definitions for interfacing with Color BASIC [9] and a file that points to floating point routines within BASIC [10]. Note that these files assume you are using my assembler [11] but it should be easy to adapt to other assemblers. And that's pretty much it for calling an assembly language subroutine in plain Color BASIC. You can pass in numbers or strings, but you can only return numbers. And if you want a new string, you have to pass in a string variable. You are also restricted to only one such function. A fair start, but things get eaiser with Extended Color BASIC. [1] gopher://gopher.conman.org/0Phlog:2024/11/26.1 [2] gopher://gopher.conman.org/0Phlog:2024/11/26.3 [3] https://archive.org/details/getting-started-with-color-basic-1984-edition/page/140/mode/2up [4] https://archive.org/details/Color_Computer_Assembly_Language_Programming_1983_William_Barden_Jr/page/n263/mode/2up [5] https://en.wikipedia.org/wiki/Microsoft_Binary_Format [6] https://archive.org/details/Getting_Started_with_Extended_Color_BASIC_1984_Tandy [7] https://colorcomputerarchive.com/repo/Documents/Books/Unravelled%20Series/ [8] https://en.wikipedia.org/wiki/ROT13 [9] gopher://gopher.conman.org/0Phlog:2024/11/26/basic.i [10] gopher://gopher.conman.org/0Phlog:2024/11/26/basic-fp.i [11] https://github.com/spc476/a09 --- Discussions about this page Two Stop Bits | The definitive guide to writing assembly language subroutines for Color BASIC https://twostopbits.com/item?id=4699 Email Sean Conner at sean@conman.org .