User Tools

Site Tools


printing_20strings

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

printing_20strings [2018/03/31 13:19] (current)
Line 1: Line 1:
 +=====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.
printing_20strings.txt ยท Last modified: 2018/03/31 13:19 (external edit)