=====Printing strings===== //by Jon Ripley, August 2006//\\ \\ This article documents three routines to output strings and VDU command sequences from assembler:\\ \\ * Write0 - Output a NULL terminated string * WriteN - Output a known length string * WriteS - Output an in-line string \\ ===== Output a NULL terminated string ===== \\ The subroutine below outputs a NULL terminated string to the active output stream. The string must be terminated by ASCII character zero:\\ \\ ; ; Write0 - write NULL terminated string to active output stream ; eax - pointer to NULL terminated string ; On exit: ; eax = pointer to end of string + 1 ; Corrupts flags ; .Write0 push edx ; store edx mov edx,eax ; edx = pointer to string .Write0_lp mov al, [edx] ; read character from string inc edx ; move to next character cmp al,0 ; is it the terminating character? jz Write0_end ; yes, exit routine call "oswrch" ; output character jmp Write0_lp ; jump to start of loop .Write0_end mov eax,edx ; preserve current string pointer pop edx ; restore edx ret ; return \\ If the string address is constant use code similar to the following:\\ \\ mov eax, Str ; load pinter to string call Write0 ; output string ret ; return .Str db "Hello world!" ; the string db 0 ; terminating character \\ If the string is pointed to by a BASIC variable use code similar to the following. The BASIC variable should be an integer:\\ \\ mov eax, [^Str%] ; load pointer to string (current value of BASIC variable Str%) call Write0 ; output string ret ; return \\ ==== Output a known length string ==== \\ The previous routine suffers from the problem that it cannot output any strings containing ASCII character zero as this is the terminator. However when sending characters to the VDU driver for graphics operations it is sometimes required to include character zero in the command sequence. This alternative routine is used to print any string where the length is known:\\ \\ The subroutine below outputs a known length string to the active output stream:\\ \\ ; ; WriteN - write string to active output stream ; eax - Pointer to string ; ecx - Number of characters to write ; All registers preserved, corrupts flags ; .WriteN jecxz WriteN_end ; if (ecx=0) there are no characters to write push eax ; store eax push ecx ; store ecx push edx ; store edx mov edx, eax ; edx = pointer to string .WriteN_lp mov al, [edx] ; read character inc edx ; move to next character call "oswrch" ; output character loop WriteN_lp ; loop while there are characters to write pop edx ; restore edx pop ecx ; restore ecx pop eax ; restore eax .WriteN_end ret ; return \\ If the string address is constant use code similar to the following:\\ \\ mov eax, Str ; load pointer to string mov ecx, 12 ; load length of string call WriteN ; output string ret ; return .Str db "Hello world!" ; the string \\ If the string pointer is variable use code similar to the following. The BASIC variable should be an integer:\\ \\ mov eax, [^Str%] ; load pointer to string (current value of BASIC variable Str%) mov ecx, 12 ; load length of string call WriteN ; output string ret ; return \\ To print a BASIC string use the following code:\\ \\ mov eax, [^my$] ; read current string address mov ecx, 0 ; clear ecx register mov cx, [^my$+4] ; read length of string call WriteN ; output string \\ ===== Output an in-line string ===== \\ The subroutine below outputs an in-line NULL terminated string to the active output stream. The string must be terminated by ASCII character zero:\\ \\ ; ; WriteS - write in-line NULL terminated string to active output stream ; All registers preserved, corrupts flags ; .WriteS xchg eax,[esp] ; store eax, read pointer to in-line string call Write0 ; write string, set eax to new return address xchg eax,[esp] ; restore eax, store return address ret \\ This routine is useful for embedding fixed prompts and messages in programs, such as:\\ \\ call WriteS ; output in-line string db "Press any key to continue." ; the in-line string db 0 ; terminating character call "osrdch" ; wait for key press ret ; return \\ **Note:** The routines Write0 and WriteN may be called from BASIC for testing purposes, however WriteS is designed to be called only from assembler. Calling WriteS from BASIC will cause undefined behaviour to occur and may crash BASIC.\\ \\ ===== References ===== \\ RISC OS Programmer's Reference Manual volume 1.