Calling+internal+routines+from+assembler+code

//by Richard Russell, January 2016//

A small selection of subroutines, internal to the BB4W interpreter, is exposed to the assembly language programmer so that they may be called from his own assembler code. These are grouped into two sets; the most commonly needed subroutines are callable by **name** and the less commonly needed ones by a **jump table**. The first set is as follows (documented also in the main BB4W Help manual):

code format="asm" CALL "osbget" ; Read byte from file to AL, EBX contains channel number CALL "osbput" ; Write byte from AL to file, EBX contains channel number CALL "osrdch" ; Read keyboard character to AL CALL "osasci" ; Write AL to the VDU drivers (plus LF if CR) CALL "osnewl" ; Write LF,CR CALL "oswrch" ; Write AL to the VDU drivers CALL "osword" ; Read character dot pattern, EDX addresses buffer CALL "osbyte" ; Read character at cursor position to AL CALL "oscli" ; Various OS commands, EDX addresses string CALL "oskey" ; Equivalent to INKEY, EAX contains timeout value CALL "osline" ; Read a line from the console, EDX addresses buffer (DL=0) CALL "osshut" ; Close a file, EBX = channel number CALL "getptr" ; Read file pointer, EBX = channel number, result in EAX CALL "setptr" ; Set file pointer, EBX = channel number, EAX = value CALL "getext" ; Read file length, EBX = channel number, result in EAX CALL "setext" ; Set file length, EBX = channel number, EAX = value CALL "osopen" ; Open a file, EDX addresses filename, AL = 0 (read), ; 1 (create) or 2 (update), channel number returned in EAX CALL "csenter"; Enter critical section (@memhdc% settings may change) CALL "csleave"; Leave critical section (@memhdc% may not be changed) code

The second set is as follows (//BBC BASIC for Windows// v6.00a or later only):

code format="asm" CALL @fn%(0) ; Load numeric (al=type, ebp=varptr, returns ebx,ecx,edx) CALL @fn%(1) ; Load string (al=type, ebp=varptr, returns len=ecx, addr=edx) CALL @fn%(2) ; Store numeric (ah=type, ebp=varptr, value=bx,ecx,edx) CALL @fn%(3) ; Store string (bl=type, ebp=varptr, length=ecx, address=edx) CALL @fn%(4) ; Look up variable (esi points to name, returns type=al, varptr=ebp) CALL @fn%(5) ; Create variable (called immediately after @fn%(4) returns NC,NZ) CALL @fn%(6) ; Evaluate expression (esi points to expr, returns ebx,ecx,edx) CALL @fn%(7) ; Evaluate single item (esi points to item, returns ebx,ecx,edx) CALL @fn%(8) ; Tokenise string (esi points to srce, ebx points to dest, bl,cl = 0) CALL @fn%(9) ; Expand token to keyword on current output stream (al = token) CALL @fn%(10) ; Convert 64-bit integer (bx=0,ecx,edx) to 80-bit float (ebx,ecx,edx) CALL @fn%(11) ; Truncate 80-bit float (bx,ecx,edx) to 64-bit integer (bx=0,ecx,edx) CALL @fn%(12) ; Convert numeric (bx,ecx,edx) to string (at edi) using format [ebp] CALL @fn%(13) ; Convert decimal string (stored at esi) to numeric (ebx,ecx,edx) CALL @fn%(14) ; Raise numeric (bx,ecx,edx) to 64-bit integer power (eax,edi) CALL @fn%(15) ; Raise numeric (bx,ecx,edx) to float power (HIWORD(ebx),eax,edi) CALL @fn%(16) ; EXP function; calculate e raised to the power of (bx,ecx,edx) JMP @fn%(17) ; Return to BASIC (jmp rather than call), esi addresses statement CALL @fn%(18) ; Queue event (as in SYS @fn%(18), msg%, wparam%, lparam%) code