X86-16 writing ASCIIZ strings directly to video

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
2
down vote

favorite
1












While developing my OS, I decided there was a need to be more verbose about what was happening in real-mode. The idea of embedding non-printable characters in an ASCII string was born from knowledge of VT100 control codes, but I wanted to make it a little simpler and more comprehensive in functionality at the same time.



On a Win7 machine, Notepad++ and NASM 2.11.08 are used to create binaries. Whenever possible, DOSBOX and DEBUG or DEBUGX are used for testing code, which is ultimately copied to image for BOCH's and finally to bootable media.



My code is completely independent and not intended to conform to any particular ABI or interface with established libraries. Any conformity to CDECL or FASTCALL is purely coincidental as I pick and choose what serves the purpose.




At either command prompt or in DEBUG, this allows testing of each string and waiting for user input after each display. I've selected 1000:0 because code can be modified, reloaded and jump back and forth from command prompt without affecting string to be displayed.



 BDA equ 40H

VIDEO equ 10H
SAP equ 05H ; BIOS function, change displayed page
KEYBOARD equ 16H

org 0x100 ; Origin for DOS .com files

; =============================================================================================
; This benchmark will display or at least process successive NULL terminated strings, wait
; for user response and then continue unless beginning of next string is NULL.
; ---------------------------------------------------------------------------------------------

enter 8, 0 ; So stack will be page aligned entering ShowS.

; As ShowS is an integral part of real mode startup code in my OS, DOSBOX is used as
; a convenient means of testing code, so this mimics required functionality.

push 0x1000 ; Segment where ASCIIZ string lives
push 0 ; Offset from segment

Read: call ShowS ; SP = FFE0
jz .done ; ZF = 1 if byte pointed to by SI is NULL.

push ax ; This is the pointer to next string.

xor ax, ax ; This allows me to single step through each string
int KEYBOARD
cmp al, ESC ; Did operator press escape?
jnz Read

.done: leave ; Kill procedure frame so RET will go to proper place
ret ; Essentially does an INT 20H @ CS:0000



Frame sizes and stack alignment are only used to facilitate visualization in DEBUG.





; ____________________________________________________________________________________________

Params: dw 0 ; Offset into page in bytes
db 0 ; Page to write too (0 - 7)
db 0 ; Characters attribute

%define TxtPntr BP + 4 ; ARG0 = Far pointer to ASCIIZ string.
%define SafeStk BP - (FrmSize + 7 * 2)

Cursors equ 50H ; Base of array of WORDS for cursor postion of each page.
DispPg equ 62H ; Page currently being displayed
EOS equ 0H ; End Of String
FrmSize equ 4H ; Bytes reserved for local data

ESC equ 0H
; =============================================================================================
; Display ASCIIZ text on an 80 x 25 x 16 color console. This can be a single or an array
; of strings, but must be terminated with DOUBLE NULL.

; ENTER: ARG1 = Segment portion of far pointer to string
; ARG0 = Offset and ultimately loaded into DS:SI

; LEAVE: AX = Offset to next string (Only if ZF = 0)
; CX = -1 if there was a buffer overrun (string larger than 128 bytes)
; DX = Size of memory leak on stack in bytes

; FLAGS: ZF = 1 if at end of array of strings, otherwise there is another string.
; ---------------------------------------------------------------------------------------------

ShowS: enter FrmSize, 0 ; ARGS begin @ SS:FFF0

; NOTE: Any changes in this prologue must be representative in SafeStk definition.

push es ; 1
push ds ; 2
push di ; 3
push si ; 4
push fs ; 5

push BDA
pop fs ; Establish segment into BDA

push cs ; As it is a far call into this procedure, DS might
pop ds ; not be pointing to CS
mov si, Params ; DS:SI points to the two DWORD parameters

push ds ; 6
push si ; 7 SafeStk points here

; At each iteration it is assumed to continue from last position in same page. To
; override this, use whatever control characters at beginning of string to achieve desired
; results.

; In all probability, writes will be to the same page as previous, but for the sake
; of 12 bytes of code, this is as practical as conditionals to check BDA (active page)

lodsw ; Get 16 bit offset into desired page.
mov di, ax
lodsw ; AH = Attribute, AL = Page #
push ax
add al, 0B8H ; Segments being @ 80x25 16 color
shl ax, 8
mov es, ax ; ES:DI setup for STOSB or STOSW
pop ax ; Retrieve AH = characters attribute

lds si, [TxtPntr] ; Grab far pointer to ASCIIZ string
mov cx, 128 ; Overflow count

.next: lodsb ; Read next or first char
cmp al, EOS
jz .done
cmp al, ' '
jb DoCtl ; Execute handler for control character

; Write character to next location pointed to by ES:DI

.post: or ah, ah ; Has an attribute been defined
jnz .attr
stosb
inc di
jmp .attr + 1 ; Do overrun check

.attr: stosw
dec cx ; Decrement displayable character count.
jnc .next ; Return CX = -1 for overflow

; Until algorithm has been proven, this will give an indication of stack corruption.

.done: mov dx, sp
lea sp, [SafeStk] ; Changes in prologue affects this
sub dx, sp
neg dx ; CX = Difference in pointers

shr ax, 8 ; Move characters attribute into low nibble
push ax
push es
mov ax, di ; Save copy of offset
les di, [SafeStk]
stosw ; Save location of next write

; Skewing SP by one, forces attribute back into AH & MSB of video segment into AL

inc sp
pop ax
inc sp
and al, 7 ; Converts MSB of segment into page # (0-7)
stosw
add sp, 4 ; Waste far pointer to procedures parameters

; Test character after this strings terminator to set ZF appropriately.

test byte [si], 0FFH ; Test if there is another string.
mov ax, si ; Return offset to next string in AX

pop fs
pop si
pop di
pop ds
pop es

leave ; Kill procedure frame
ret 2 ; Only waste far pointers offset

; To avoid conditional jump of more than 128 bytes, this allows ret to branch back
; to DoCtl from a place than will definitely be more than 128 bytes away. It also serves
; as a convenient entry point for things that apply to each handler such as preserving AX

DoCtl: push ax ; Need to preserve attribute
push .done ; Set to return address
jmp .exe ; First function in list
.done: pop ax
jmp ShowS.next ; Continue reading string

; Handlers should start here, but if not, suitable code should be implemented

.exe:






share|improve this question

























    up vote
    2
    down vote

    favorite
    1












    While developing my OS, I decided there was a need to be more verbose about what was happening in real-mode. The idea of embedding non-printable characters in an ASCII string was born from knowledge of VT100 control codes, but I wanted to make it a little simpler and more comprehensive in functionality at the same time.



    On a Win7 machine, Notepad++ and NASM 2.11.08 are used to create binaries. Whenever possible, DOSBOX and DEBUG or DEBUGX are used for testing code, which is ultimately copied to image for BOCH's and finally to bootable media.



    My code is completely independent and not intended to conform to any particular ABI or interface with established libraries. Any conformity to CDECL or FASTCALL is purely coincidental as I pick and choose what serves the purpose.




    At either command prompt or in DEBUG, this allows testing of each string and waiting for user input after each display. I've selected 1000:0 because code can be modified, reloaded and jump back and forth from command prompt without affecting string to be displayed.



     BDA equ 40H

    VIDEO equ 10H
    SAP equ 05H ; BIOS function, change displayed page
    KEYBOARD equ 16H

    org 0x100 ; Origin for DOS .com files

    ; =============================================================================================
    ; This benchmark will display or at least process successive NULL terminated strings, wait
    ; for user response and then continue unless beginning of next string is NULL.
    ; ---------------------------------------------------------------------------------------------

    enter 8, 0 ; So stack will be page aligned entering ShowS.

    ; As ShowS is an integral part of real mode startup code in my OS, DOSBOX is used as
    ; a convenient means of testing code, so this mimics required functionality.

    push 0x1000 ; Segment where ASCIIZ string lives
    push 0 ; Offset from segment

    Read: call ShowS ; SP = FFE0
    jz .done ; ZF = 1 if byte pointed to by SI is NULL.

    push ax ; This is the pointer to next string.

    xor ax, ax ; This allows me to single step through each string
    int KEYBOARD
    cmp al, ESC ; Did operator press escape?
    jnz Read

    .done: leave ; Kill procedure frame so RET will go to proper place
    ret ; Essentially does an INT 20H @ CS:0000



    Frame sizes and stack alignment are only used to facilitate visualization in DEBUG.





    ; ____________________________________________________________________________________________

    Params: dw 0 ; Offset into page in bytes
    db 0 ; Page to write too (0 - 7)
    db 0 ; Characters attribute

    %define TxtPntr BP + 4 ; ARG0 = Far pointer to ASCIIZ string.
    %define SafeStk BP - (FrmSize + 7 * 2)

    Cursors equ 50H ; Base of array of WORDS for cursor postion of each page.
    DispPg equ 62H ; Page currently being displayed
    EOS equ 0H ; End Of String
    FrmSize equ 4H ; Bytes reserved for local data

    ESC equ 0H
    ; =============================================================================================
    ; Display ASCIIZ text on an 80 x 25 x 16 color console. This can be a single or an array
    ; of strings, but must be terminated with DOUBLE NULL.

    ; ENTER: ARG1 = Segment portion of far pointer to string
    ; ARG0 = Offset and ultimately loaded into DS:SI

    ; LEAVE: AX = Offset to next string (Only if ZF = 0)
    ; CX = -1 if there was a buffer overrun (string larger than 128 bytes)
    ; DX = Size of memory leak on stack in bytes

    ; FLAGS: ZF = 1 if at end of array of strings, otherwise there is another string.
    ; ---------------------------------------------------------------------------------------------

    ShowS: enter FrmSize, 0 ; ARGS begin @ SS:FFF0

    ; NOTE: Any changes in this prologue must be representative in SafeStk definition.

    push es ; 1
    push ds ; 2
    push di ; 3
    push si ; 4
    push fs ; 5

    push BDA
    pop fs ; Establish segment into BDA

    push cs ; As it is a far call into this procedure, DS might
    pop ds ; not be pointing to CS
    mov si, Params ; DS:SI points to the two DWORD parameters

    push ds ; 6
    push si ; 7 SafeStk points here

    ; At each iteration it is assumed to continue from last position in same page. To
    ; override this, use whatever control characters at beginning of string to achieve desired
    ; results.

    ; In all probability, writes will be to the same page as previous, but for the sake
    ; of 12 bytes of code, this is as practical as conditionals to check BDA (active page)

    lodsw ; Get 16 bit offset into desired page.
    mov di, ax
    lodsw ; AH = Attribute, AL = Page #
    push ax
    add al, 0B8H ; Segments being @ 80x25 16 color
    shl ax, 8
    mov es, ax ; ES:DI setup for STOSB or STOSW
    pop ax ; Retrieve AH = characters attribute

    lds si, [TxtPntr] ; Grab far pointer to ASCIIZ string
    mov cx, 128 ; Overflow count

    .next: lodsb ; Read next or first char
    cmp al, EOS
    jz .done
    cmp al, ' '
    jb DoCtl ; Execute handler for control character

    ; Write character to next location pointed to by ES:DI

    .post: or ah, ah ; Has an attribute been defined
    jnz .attr
    stosb
    inc di
    jmp .attr + 1 ; Do overrun check

    .attr: stosw
    dec cx ; Decrement displayable character count.
    jnc .next ; Return CX = -1 for overflow

    ; Until algorithm has been proven, this will give an indication of stack corruption.

    .done: mov dx, sp
    lea sp, [SafeStk] ; Changes in prologue affects this
    sub dx, sp
    neg dx ; CX = Difference in pointers

    shr ax, 8 ; Move characters attribute into low nibble
    push ax
    push es
    mov ax, di ; Save copy of offset
    les di, [SafeStk]
    stosw ; Save location of next write

    ; Skewing SP by one, forces attribute back into AH & MSB of video segment into AL

    inc sp
    pop ax
    inc sp
    and al, 7 ; Converts MSB of segment into page # (0-7)
    stosw
    add sp, 4 ; Waste far pointer to procedures parameters

    ; Test character after this strings terminator to set ZF appropriately.

    test byte [si], 0FFH ; Test if there is another string.
    mov ax, si ; Return offset to next string in AX

    pop fs
    pop si
    pop di
    pop ds
    pop es

    leave ; Kill procedure frame
    ret 2 ; Only waste far pointers offset

    ; To avoid conditional jump of more than 128 bytes, this allows ret to branch back
    ; to DoCtl from a place than will definitely be more than 128 bytes away. It also serves
    ; as a convenient entry point for things that apply to each handler such as preserving AX

    DoCtl: push ax ; Need to preserve attribute
    push .done ; Set to return address
    jmp .exe ; First function in list
    .done: pop ax
    jmp ShowS.next ; Continue reading string

    ; Handlers should start here, but if not, suitable code should be implemented

    .exe:






    share|improve this question





















      up vote
      2
      down vote

      favorite
      1









      up vote
      2
      down vote

      favorite
      1






      1





      While developing my OS, I decided there was a need to be more verbose about what was happening in real-mode. The idea of embedding non-printable characters in an ASCII string was born from knowledge of VT100 control codes, but I wanted to make it a little simpler and more comprehensive in functionality at the same time.



      On a Win7 machine, Notepad++ and NASM 2.11.08 are used to create binaries. Whenever possible, DOSBOX and DEBUG or DEBUGX are used for testing code, which is ultimately copied to image for BOCH's and finally to bootable media.



      My code is completely independent and not intended to conform to any particular ABI or interface with established libraries. Any conformity to CDECL or FASTCALL is purely coincidental as I pick and choose what serves the purpose.




      At either command prompt or in DEBUG, this allows testing of each string and waiting for user input after each display. I've selected 1000:0 because code can be modified, reloaded and jump back and forth from command prompt without affecting string to be displayed.



       BDA equ 40H

      VIDEO equ 10H
      SAP equ 05H ; BIOS function, change displayed page
      KEYBOARD equ 16H

      org 0x100 ; Origin for DOS .com files

      ; =============================================================================================
      ; This benchmark will display or at least process successive NULL terminated strings, wait
      ; for user response and then continue unless beginning of next string is NULL.
      ; ---------------------------------------------------------------------------------------------

      enter 8, 0 ; So stack will be page aligned entering ShowS.

      ; As ShowS is an integral part of real mode startup code in my OS, DOSBOX is used as
      ; a convenient means of testing code, so this mimics required functionality.

      push 0x1000 ; Segment where ASCIIZ string lives
      push 0 ; Offset from segment

      Read: call ShowS ; SP = FFE0
      jz .done ; ZF = 1 if byte pointed to by SI is NULL.

      push ax ; This is the pointer to next string.

      xor ax, ax ; This allows me to single step through each string
      int KEYBOARD
      cmp al, ESC ; Did operator press escape?
      jnz Read

      .done: leave ; Kill procedure frame so RET will go to proper place
      ret ; Essentially does an INT 20H @ CS:0000



      Frame sizes and stack alignment are only used to facilitate visualization in DEBUG.





      ; ____________________________________________________________________________________________

      Params: dw 0 ; Offset into page in bytes
      db 0 ; Page to write too (0 - 7)
      db 0 ; Characters attribute

      %define TxtPntr BP + 4 ; ARG0 = Far pointer to ASCIIZ string.
      %define SafeStk BP - (FrmSize + 7 * 2)

      Cursors equ 50H ; Base of array of WORDS for cursor postion of each page.
      DispPg equ 62H ; Page currently being displayed
      EOS equ 0H ; End Of String
      FrmSize equ 4H ; Bytes reserved for local data

      ESC equ 0H
      ; =============================================================================================
      ; Display ASCIIZ text on an 80 x 25 x 16 color console. This can be a single or an array
      ; of strings, but must be terminated with DOUBLE NULL.

      ; ENTER: ARG1 = Segment portion of far pointer to string
      ; ARG0 = Offset and ultimately loaded into DS:SI

      ; LEAVE: AX = Offset to next string (Only if ZF = 0)
      ; CX = -1 if there was a buffer overrun (string larger than 128 bytes)
      ; DX = Size of memory leak on stack in bytes

      ; FLAGS: ZF = 1 if at end of array of strings, otherwise there is another string.
      ; ---------------------------------------------------------------------------------------------

      ShowS: enter FrmSize, 0 ; ARGS begin @ SS:FFF0

      ; NOTE: Any changes in this prologue must be representative in SafeStk definition.

      push es ; 1
      push ds ; 2
      push di ; 3
      push si ; 4
      push fs ; 5

      push BDA
      pop fs ; Establish segment into BDA

      push cs ; As it is a far call into this procedure, DS might
      pop ds ; not be pointing to CS
      mov si, Params ; DS:SI points to the two DWORD parameters

      push ds ; 6
      push si ; 7 SafeStk points here

      ; At each iteration it is assumed to continue from last position in same page. To
      ; override this, use whatever control characters at beginning of string to achieve desired
      ; results.

      ; In all probability, writes will be to the same page as previous, but for the sake
      ; of 12 bytes of code, this is as practical as conditionals to check BDA (active page)

      lodsw ; Get 16 bit offset into desired page.
      mov di, ax
      lodsw ; AH = Attribute, AL = Page #
      push ax
      add al, 0B8H ; Segments being @ 80x25 16 color
      shl ax, 8
      mov es, ax ; ES:DI setup for STOSB or STOSW
      pop ax ; Retrieve AH = characters attribute

      lds si, [TxtPntr] ; Grab far pointer to ASCIIZ string
      mov cx, 128 ; Overflow count

      .next: lodsb ; Read next or first char
      cmp al, EOS
      jz .done
      cmp al, ' '
      jb DoCtl ; Execute handler for control character

      ; Write character to next location pointed to by ES:DI

      .post: or ah, ah ; Has an attribute been defined
      jnz .attr
      stosb
      inc di
      jmp .attr + 1 ; Do overrun check

      .attr: stosw
      dec cx ; Decrement displayable character count.
      jnc .next ; Return CX = -1 for overflow

      ; Until algorithm has been proven, this will give an indication of stack corruption.

      .done: mov dx, sp
      lea sp, [SafeStk] ; Changes in prologue affects this
      sub dx, sp
      neg dx ; CX = Difference in pointers

      shr ax, 8 ; Move characters attribute into low nibble
      push ax
      push es
      mov ax, di ; Save copy of offset
      les di, [SafeStk]
      stosw ; Save location of next write

      ; Skewing SP by one, forces attribute back into AH & MSB of video segment into AL

      inc sp
      pop ax
      inc sp
      and al, 7 ; Converts MSB of segment into page # (0-7)
      stosw
      add sp, 4 ; Waste far pointer to procedures parameters

      ; Test character after this strings terminator to set ZF appropriately.

      test byte [si], 0FFH ; Test if there is another string.
      mov ax, si ; Return offset to next string in AX

      pop fs
      pop si
      pop di
      pop ds
      pop es

      leave ; Kill procedure frame
      ret 2 ; Only waste far pointers offset

      ; To avoid conditional jump of more than 128 bytes, this allows ret to branch back
      ; to DoCtl from a place than will definitely be more than 128 bytes away. It also serves
      ; as a convenient entry point for things that apply to each handler such as preserving AX

      DoCtl: push ax ; Need to preserve attribute
      push .done ; Set to return address
      jmp .exe ; First function in list
      .done: pop ax
      jmp ShowS.next ; Continue reading string

      ; Handlers should start here, but if not, suitable code should be implemented

      .exe:






      share|improve this question











      While developing my OS, I decided there was a need to be more verbose about what was happening in real-mode. The idea of embedding non-printable characters in an ASCII string was born from knowledge of VT100 control codes, but I wanted to make it a little simpler and more comprehensive in functionality at the same time.



      On a Win7 machine, Notepad++ and NASM 2.11.08 are used to create binaries. Whenever possible, DOSBOX and DEBUG or DEBUGX are used for testing code, which is ultimately copied to image for BOCH's and finally to bootable media.



      My code is completely independent and not intended to conform to any particular ABI or interface with established libraries. Any conformity to CDECL or FASTCALL is purely coincidental as I pick and choose what serves the purpose.




      At either command prompt or in DEBUG, this allows testing of each string and waiting for user input after each display. I've selected 1000:0 because code can be modified, reloaded and jump back and forth from command prompt without affecting string to be displayed.



       BDA equ 40H

      VIDEO equ 10H
      SAP equ 05H ; BIOS function, change displayed page
      KEYBOARD equ 16H

      org 0x100 ; Origin for DOS .com files

      ; =============================================================================================
      ; This benchmark will display or at least process successive NULL terminated strings, wait
      ; for user response and then continue unless beginning of next string is NULL.
      ; ---------------------------------------------------------------------------------------------

      enter 8, 0 ; So stack will be page aligned entering ShowS.

      ; As ShowS is an integral part of real mode startup code in my OS, DOSBOX is used as
      ; a convenient means of testing code, so this mimics required functionality.

      push 0x1000 ; Segment where ASCIIZ string lives
      push 0 ; Offset from segment

      Read: call ShowS ; SP = FFE0
      jz .done ; ZF = 1 if byte pointed to by SI is NULL.

      push ax ; This is the pointer to next string.

      xor ax, ax ; This allows me to single step through each string
      int KEYBOARD
      cmp al, ESC ; Did operator press escape?
      jnz Read

      .done: leave ; Kill procedure frame so RET will go to proper place
      ret ; Essentially does an INT 20H @ CS:0000



      Frame sizes and stack alignment are only used to facilitate visualization in DEBUG.





      ; ____________________________________________________________________________________________

      Params: dw 0 ; Offset into page in bytes
      db 0 ; Page to write too (0 - 7)
      db 0 ; Characters attribute

      %define TxtPntr BP + 4 ; ARG0 = Far pointer to ASCIIZ string.
      %define SafeStk BP - (FrmSize + 7 * 2)

      Cursors equ 50H ; Base of array of WORDS for cursor postion of each page.
      DispPg equ 62H ; Page currently being displayed
      EOS equ 0H ; End Of String
      FrmSize equ 4H ; Bytes reserved for local data

      ESC equ 0H
      ; =============================================================================================
      ; Display ASCIIZ text on an 80 x 25 x 16 color console. This can be a single or an array
      ; of strings, but must be terminated with DOUBLE NULL.

      ; ENTER: ARG1 = Segment portion of far pointer to string
      ; ARG0 = Offset and ultimately loaded into DS:SI

      ; LEAVE: AX = Offset to next string (Only if ZF = 0)
      ; CX = -1 if there was a buffer overrun (string larger than 128 bytes)
      ; DX = Size of memory leak on stack in bytes

      ; FLAGS: ZF = 1 if at end of array of strings, otherwise there is another string.
      ; ---------------------------------------------------------------------------------------------

      ShowS: enter FrmSize, 0 ; ARGS begin @ SS:FFF0

      ; NOTE: Any changes in this prologue must be representative in SafeStk definition.

      push es ; 1
      push ds ; 2
      push di ; 3
      push si ; 4
      push fs ; 5

      push BDA
      pop fs ; Establish segment into BDA

      push cs ; As it is a far call into this procedure, DS might
      pop ds ; not be pointing to CS
      mov si, Params ; DS:SI points to the two DWORD parameters

      push ds ; 6
      push si ; 7 SafeStk points here

      ; At each iteration it is assumed to continue from last position in same page. To
      ; override this, use whatever control characters at beginning of string to achieve desired
      ; results.

      ; In all probability, writes will be to the same page as previous, but for the sake
      ; of 12 bytes of code, this is as practical as conditionals to check BDA (active page)

      lodsw ; Get 16 bit offset into desired page.
      mov di, ax
      lodsw ; AH = Attribute, AL = Page #
      push ax
      add al, 0B8H ; Segments being @ 80x25 16 color
      shl ax, 8
      mov es, ax ; ES:DI setup for STOSB or STOSW
      pop ax ; Retrieve AH = characters attribute

      lds si, [TxtPntr] ; Grab far pointer to ASCIIZ string
      mov cx, 128 ; Overflow count

      .next: lodsb ; Read next or first char
      cmp al, EOS
      jz .done
      cmp al, ' '
      jb DoCtl ; Execute handler for control character

      ; Write character to next location pointed to by ES:DI

      .post: or ah, ah ; Has an attribute been defined
      jnz .attr
      stosb
      inc di
      jmp .attr + 1 ; Do overrun check

      .attr: stosw
      dec cx ; Decrement displayable character count.
      jnc .next ; Return CX = -1 for overflow

      ; Until algorithm has been proven, this will give an indication of stack corruption.

      .done: mov dx, sp
      lea sp, [SafeStk] ; Changes in prologue affects this
      sub dx, sp
      neg dx ; CX = Difference in pointers

      shr ax, 8 ; Move characters attribute into low nibble
      push ax
      push es
      mov ax, di ; Save copy of offset
      les di, [SafeStk]
      stosw ; Save location of next write

      ; Skewing SP by one, forces attribute back into AH & MSB of video segment into AL

      inc sp
      pop ax
      inc sp
      and al, 7 ; Converts MSB of segment into page # (0-7)
      stosw
      add sp, 4 ; Waste far pointer to procedures parameters

      ; Test character after this strings terminator to set ZF appropriately.

      test byte [si], 0FFH ; Test if there is another string.
      mov ax, si ; Return offset to next string in AX

      pop fs
      pop si
      pop di
      pop ds
      pop es

      leave ; Kill procedure frame
      ret 2 ; Only waste far pointers offset

      ; To avoid conditional jump of more than 128 bytes, this allows ret to branch back
      ; to DoCtl from a place than will definitely be more than 128 bytes away. It also serves
      ; as a convenient entry point for things that apply to each handler such as preserving AX

      DoCtl: push ax ; Need to preserve attribute
      push .done ; Set to return address
      jmp .exe ; First function in list
      .done: pop ax
      jmp ShowS.next ; Continue reading string

      ; Handlers should start here, but if not, suitable code should be implemented

      .exe:








      share|improve this question










      share|improve this question




      share|improve this question









      asked Feb 6 at 6:45









      Shift_Left

      46929




      46929

























          active

          oldest

          votes











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186887%2fx86-16-writing-asciiz-strings-directly-to-video%23new-answer', 'question_page');

          );

          Post as a guest



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes










           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186887%2fx86-16-writing-asciiz-strings-directly-to-video%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Greedy Best First Search implementation in Rust

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          C++11 CLH Lock Implementation