assembly - Como funciona a entrada em buffer




input dos (2)

A entrada no próximo programa funciona bem, mas quando peço para exibir a saída, o DOS não exibe nada! Como isso é possível?

        ORG     256
        mov     dx, msg1
        mov     ah, 09h                 ;DOS.WriteString
        int     21h
        mov     dx, buf
        mov     ah, 0Ah                 ;DOS.BufferedInput
        int     21h
        mov     dx, msg2
        mov     ah, 09h                 ;DOS.WriteString
        int     21h
        mov     dx, buf
        mov     ah, 09h                 ;DOS.WriteString
        int     21h
        mov     ax, 4C00h               ;DOS.TerminateWithExitcode
        int     21h
; --------------------------------------
msg1:   db      'Input : ', '$'
buf:    db      20 dup ('$')
msg2:   db      13, 10, 'Output : ', '$'
; --------------------------------------

Introdução de texto usando int 21h AH=08h

Todos os três métodos de entrada descritos até agora (na resposta acima!) Foram claramente feitos sob medida para atender às ferramentas da Microsoft, como EDLIN.EXE e COMMAND.COM.
Se você está escrevendo sua própria aplicação, melhores resultados podem ser alcançados através da produção de seu próprio procedimento de entrada. No coração de tal procedimento, estará uma das funções de entrada de caractere único do DOS. Eu escolhi a função de Entrada STDIN 08h porque eu quero permitir a checagem de ctrl C / ctrl Break e eu pretendo ecoar os caracteres eu mesmo via BIOS Int 10h AH=09h Escrever caractere e atributo na posição do cursor . Dessa forma, posso evitar interferir em qualquer saída redirecionada.

Programaticamente não há diferença em usar esse procedimento BufferedInput ou a chamada do sistema DOS.BufferedInput . No entanto, para o usuário na entrada do teclado será muito mais fácil, pois todas as teclas associadas à edição antiga e difícil do modelo foram descartadas e substituídas pelas teclas de edição usuais que permitem mover o cursor livremente.

  • Esquerda Move o cursor para a esquerda.
  • Direita Move o cursor para a direita.
  • Home Move o cursor para a esquerda.
  • End Move o cursor para a extrema direita.
  • Ctrl Home Remove todos os caracteres à esquerda.
  • Ctrl End Remove todos os caracteres à direita.
  • Excluir Remove o caractere atual.
  • Backspace Remove o caractere à esquerda do cursor.
  • Escape Remove todos os personagens.
  • Retorno termina a entrada.

Se o segundo byte do buffer de entrada contiver um valor diferente de zero, o espaço de armazenamento deverá conter uma string antiga (talvez de uma entrada anterior). O DOS teria chamado isso de modelo. Diferente do DOS é que:

  • a cadeia antiga não precisa ter o retorno de carro terminado.
  • a string antiga é mostrada imediatamente na tela.

Enquanto a entrada está em andamento, as guias não são expandidas e a entrada está limitada a permanecer dentro da linha atual. Textos mais longos rolam horizontalmente.
Quando a entrada é finalmente concluída, o texto completo é gravado uma vez com a expansão da guia (na tela, o espaço de armazenamento sempre mantém ASCII 9) e não mais restrito a uma única linha.

Esse procedimento faz a verificação de quebra de ctrl C / ctrl .

Quando este procedimento terminar, o cursor estará na coluna da esquerda na linha atual.

Este procedimento foi escrito com redirecionamento de entrada e redirecionamento de saída em mente e, portanto, adequado para aplicativos de console.
Um efeito do redirecionamento de entrada é que é inútil fazer eco de qualquer saída temporária na tela. Ou o usuário não está lá para olhar a tela ou a saída temporária desaparecerá em um piscar de olhos.

Exemplo 4, entrada STDIN Buffered aprimorada.

        ORG     256                     ;Create .COM program
        cld
        mov     si, msg1
        call    WriteStringDOS
        mov     dx, buf
        call    BufferedInput           ;Replaces 'mov ah, 0Ah : int 21h'
        mov     si, msg2
        call    WriteStringDOS
        mov     si, buf+2
        movzx   bx, [si-1]              ;Get character count
        mov     word [si+bx+1], 10      ;Keep CR, append LF and 0
        call    WriteStringDOS
        mov     ax, 4C00h               ;DOS.TerminateWithExitcode
        int     21h
; --------------------------------------
; IN (ds:si) OUT ()
WriteStringDOS:
        pusha
        jmps    .b
.a:     mov     dl, al
        mov     ah, 02h                 ;DOS.DisplayCharacter
        int     21h                     ; -> AL
.b:     lodsb
        test    al, al
        jnz     .a
        popa
        ret
; --------------------------------------
; IN (ds:dx) OUT ()
BufferedInput:

; Entry DS:DX   Buffer of max 1+1+255 bytes
;               1st byte is size of storage space starting at 3rd byte
;               2nd byte is size of old (CR-terminated) string, 0 if none
;               Storage space can contain old (CR-terminated) string
; Exit  DS:DX   Nothing changed if header bytes were invalid
;               1st byte unchanged
;               2nd byte is size of new CR-terminated string
;               Storage space contains new CR-terminated string
; Local [bp-1]  PAGE    Display page
;       [bp-2]  STORE   Size of storage space
;       [bp-3]  ROW     Row of input box
;       [bp-4]  COL     Column of input box
;       [bp-5]  SHIFT   Number of characters shifted out on the leftside
;       [bp-6]  INBOX   Size of input box
;       [bp-7]  LIX     Number of characters in current input string
;       [bp-8]  CIX     Position of cursor in current input string
;       [bp-10] FLAGS   Bit[0] is ON for normal keyboard input

        pusha
        mov     si, dx
        lodsw                           ; -> SI points at storage space
        test    al, al                  ;AL is size of storage space
        jz      .Quit                   ;No storage space!
        cmp     ah, al                  ;AH is size of old string
        jnb     .Quit                   ;Old string too long!
        mov     bl, al

        sub     sp, 256                 ;Local edit buffer (max size)
        mov     bp, sp
        mov     ah, 0Fh                 ;BIOS.GetVideoMode
        int     10h                     ; -> AL=Mode AH=Cols BH=Page
        push    bx                      ;STORE and PAGE
        mov     bl, ah
        mov     ah, 03h                 ;BIOS.GetCursor
        int     10h                     ; -> CX=Shape DL=Col DH=Row
        push    dx                      ;COL and ROW
        sub     bl, dl                  ;Size of the widest inbox
        xor     bh, bh
        push    bx                      ;INBOX and SHIFT
        push    bx                      ;CIX and LIX (replaces 'sub sp, 2')

        call    .ESC                    ;Clear edit buffer, reset some vars
        mov     cl, [si-1]              ;Size of old string (starts at SI)
        jmps    .b
.a:     lodsb                           ;Storage space gives old string
        push    cx si
        call    .Asc                    ;Input old string
        pop     si cx
.b:     sub     cl, 1
        jnb     .a

        xor     bx, bx                  ;STDIN
        mov     ax, 4400h               ;DOS.GetDeviceInformation
        int     21h                     ; -> AX DX CF
        jc      .c                      ;Go default to keyboard
        test    dl, dl
        jns     .d                      ;Block device, not keyboard
        shr     dl, 1
.c:     adc     bx, bx                  ; -> BX=1 if Keyboard
.d:     push    bx                      ;FLAGS

.Main:  call    .Show                   ;Refresh input box on screen
        call    .Key                    ;Get key from DOS -> AX
        mov     bx, .Scans
        test    ah, ah
        jz      .f                      ;Not an extended ASCII
        mov     [cs:.Fail], ah          ;Sentinel
.e:     lea     bx, [bx+3]
        cmp     ah, [cs:bx-1]
        jne     .e
.f:     call    [cs:bx]
        jmps    .Main

.Quit:  popa                            ;Silently quiting just like DOS
        ret
; - - - - - - - - - - - - - - - - - - -
.Scans: db           .Asc
        db      4Bh, .s4B               ;<LEFT>
        db      4Dh, .s4D               ;<RIGHT>
        db      47h, .s47               ;<HOME>
        db      4Fh, .s4F               ;<END>
        db      77h, .s77               ;<CTRL-HOME>
        db      75h, .s75               ;<CTRL-END>
        db      53h, .s53               ;<DELETE>
.Fail:  db        ?, .Beep
; - - - - - - - - - - - - - - - - - - -
.Beep:  mov     ax, 0E07h               ;BIOS.TeletypeBell
        int     10h
        ret
; - - - - - - - - - - - - - - - - - - -
.Key:   call    :1
        test    ah, ah                  ;Extended ASCII requires 2 calls
        jnz     :2
:1:     mov     ah, 08h                 ;DOS.STDINInput
        int     21h                     ; -> AL
        mov     ah, 0
:2:     xchg    al, ah
        ret
; - - - - - - - - - - - - - - - - - - -
.Show:  test    word [bp-10], 1         ;FLAGS.Keyboard ?
        jz      :Ready                  ;No, input is redirected
        movzx   di, [bp-6]              ;INBOX
        movzx   si, [bp-5]              ;SHIFT
        mov     dx, [bp-4]              ;COL and ROW
        mov     cx, 1                   ;Replication count
        mov     bh, [bp-1]              ;PAGE
        mov     bl, 07h                 ;WhiteOnBlack
:Next:  mov     ah, 02h                 ;BIOS.SetCursor
        int     10h
        mov     al, [bp+si]
        mov     ah, 09h                 ;BIOS.WriteCharacterAndAttribute
        int     10h
        inc     dl                      ;Next column
        inc     si                      ;Next character
        dec     di
        jnz     :Next                   ;Process all of the input box

        mov     dx, [bp-4]              ;COL and ROW
        add     dl, [bp-8]              ;CIX
        sub     dl, [bp-5]              ;SHIFT
        mov     ah, 02h                 ;BIOS.SetCursor
        int     10h
:Ready: ret
; - - - - - - - - - - - - - - - - - - -
.BS:    cmp     byte [bp-8], 0          ;CIX
        jne     :1
        ret
:1:     call    .s4B                    ;<LEFT>
; ---   ---   ---   ---   ---   ---   --
; <DELETE>
.s53:   movzx   di, [bp-8]              ;CIX
        movzx   cx, [bp-7]              ;LIX
        sub     cx, di
        je      :2                      ;Cursor behind the current input
:1:     mov     dl, [bp+di+1]           ;Move down in edit buffer
        mov     [bp+di], dl
        inc     di
        dec     cx
        jnz     :1
        dec     byte [bp-7]             ;LIX
:2:     ret
; - - - - - - - - - - - - - - - - - - -
.RET:   xor     si, si
        mov     bx, [bp+256+10]         ;pusha.DX -> DS:BX
        mov     al, [bp-7]              ;LIX
        inc     bx
        mov     [bx], al                ;2nd byte is size of new string
        inc     bx
        jmps    :2
:1:     mov     dl, [bp+si]
        mov     [bx+si], dl             ;Storage space receives new string
        inc     si
:2:     sub     al, 1
        jnb     :1
        mov     byte [bx+si], 13        ;Terminating CR

        push    bx                      ;(1)
        call    .ESC                    ;Wipe clean the input box
        call    .Show                   ; and reset cursor
        pop     si                      ;(1) -> DS:SI
:3:     lodsb                           ;Final unrestricted display,
        mov     dl, al                  ; expanding tabs
        mov     ah, 02h                 ;DOS.DisplayCharacter
        int     21h                     ; -> AL
        cmp     dl, 13                  ;Cursor ends in far left column
        jne     :3

        lea     sp, [bp+256]            ;Free locals and edit buffer
        popa
        ret
; - - - - - - - - - - - - - - - - - - -
.ESC:   mov     di, 256                 ;Fill edit buffer with spaces
:1:     sub     di, 2
        mov     word [bp+di], "  "
        jnz     :1
        mov     [bp-8], di              ;DI=0 -> CIX=0 LIX=0
        mov     byte [bp-5], 0          ;SHIFT=0
        ret
; - - - - - - - - - - - - - - - - - - -
.Asc:   cmp     al, 8                   ;<BACKSPACE>
        je      .BS
        cmp     al, 13                  ;<RETURN>
        je      .RET
        cmp     al, 27                  ;<ESCAPE>
        je      .ESC
        cmp     al, 10                  ;Silently ignoring linefeed
        jne     :1                      ; in favor of input redirection
        ret
:1:     movzx   di, [bp-8]              ;CIX
        movzx   si, [bp-7]              ;LIX
        lea     dx, [si+1]
        cmp     dl, [bp-2]              ;STORE
        jb      :3
        jmp     .Beep                   ;Storage capacity reached
:2:     mov     dl, [bp+si-1]           ;Move up in edit buffer
        mov     [bp+si], dl
        dec     si
:3:     cmp     si, di
        ja      :2
        mov     [bp+si], al             ;Add newest character
        inc     byte [bp-7]             ;LIX
; ---   ---   ---   ---   ---   ---   --
; <RIGHT>
.s4D:   inc     byte [bp-8]             ;CIX
        mov     al, [bp-7]              ;LIX
        cmp     [bp-8], al              ;CIX
        jbe     .Shift
        mov     [bp-8], al              ;CIX
        ret
; - - - - - - - - - - - - - - - - - - -
; <LEFT>
.s4B:   sub     byte [bp-8], 1           ;CIX
        jnb     .Shift
; ---   ---   ---   ---   ---   ---   --
; <HOME>
.s47:   mov     byte [bp-8], 0          ;CIX
        jmps    .Shift
; - - - - - - - - - - - - - - - - - - -
; <END>
.s4F:   mov     al, [bp-7]              ;LIX
        mov     [bp-8], al              ;CIX
; ---   ---   ---   ---   ---   ---   --
.Shift: mov     dl, [bp-5]              ;SHIFT
        mov     al, [bp-8]              ;CIX
        cmp     al, dl
        jb      :1
        add     dl, [bp-6]              ;INBOX
        sub     al, dl
        jb      :2
        inc     al
        add     al, [bp-5]              ;SHIFT
:1:     mov     [bp-5], al              ;SHIFT
:2:     ret
; - - - - - - - - - - - - - - - - - - -
; <CTRL-HOME>
.s77:   call    .BS
        cmp     byte [bp-8], 0          ;CIX
        ja      .s77
        ret
; - - - - - - - - - - - - - - - - - - -
; <CTRL-END>
.s75:   call    .s53                    ;<DELETE>
        mov     al, [bp-8]              ;CIX
        cmp     al, [bp-7]              ;LIX
        jb      .s75
        ret
; --------------------------------------
buf:    db      255, 16, "I'm an OldString", 13, 255-16-1+2 dup (0)
msg1:   db      'Choose color ? ', 0
msg2:   db      10, 'You chose ', 0
; --------------------------------------

Problema na compreensão da fonte? O assembler que usei:

  • considera rótulos que começam com um ponto ( . ) como rótulos locais de primeiro nível
  • considera rótulos que começam com dois pontos (:) como rótulos locais de segundo nível
  • é Single Instruction Multiple Operand (SIMO), então push cx si traduz para push cx push si .

Para um procedimento de entrada de alto desempenho, veja Rich Input Form Input , uma contribuição de revisão de código.


Olhando como você definiu o seu buffer de entrada ( buf: db 20 dup ('$') ), eu entendi que você quer cortar os cantos e ter a entrada já $ -terminada pronta para exibi-la novamente. Infelizmente isso estraga as configurações necessárias para a função de entrada do DOS 0Ah e seu programa está com sérios problemas com um potencial saturação de buffer.
Além disso, usar $ -terminação não é a escolha mais brilhante que você pode fazer, pois o caractere $ já pode aparecer entre os caracteres inseridos. Todos os programas de exemplo que apresento abaixo usarão a terminação zero.

Introdução de texto usando int 21h AH=0Ah

Esta função de Entrada STDIN em Buffer recebe caracteres do teclado e continua fazendo isso até que o usuário pressione a tecla Enter . Todos os caracteres e o retorno final de carro são colocados no espaço de armazenamento que começa no terceiro byte do buffer de entrada fornecido pelo programa de chamada através do ponteiro no DS:DX .
A contagem de caracteres, sem incluir o retorno final do carro, é armazenada no segundo byte do buffer de entrada.
É responsabilidade do programa de chamada dizer ao DOS qual é o tamanho do espaço de armazenamento. Portanto, você deve colocar seu comprimento no primeiro byte do buffer de entrada antes de chamar esta função. Para permitir uma entrada de 1 caractere, defina o tamanho do armazenamento como 2. Para permitir uma entrada de 254 caracteres, defina o tamanho do armazenamento como 255.
Se você não quiser recuperar do modelo nenhuma entrada anterior, é melhor também zerar o segundo byte. Basicamente, o modelo é o conteúdo pré-existente (e válido) no buffer de entrada fornecido pelo programa de chamada. Se o conteúdo pré-existente for inválido, o modelo não estará disponível.

Surpreendentemente, esta função tem recursos de edição limitados.

  • Escape Remove todos os caracteres da entrada atual.
    A entrada atual é abandonada, mas permanece na tela e o cursor é colocado na próxima linha, abaixo de onde a entrada foi iniciada.
  • Backspace Remove o último caractere da entrada atual.
    Funciona como esperado se a entrada permanecer em uma única linha na tela. Se, por outro lado, a entrada ocupar várias linhas, esse retrocesso será interrompido na borda esquerda da tela. A partir daí, haverá uma séria discrepância entre a entrada lógica e a entrada visual, porque o backspacing logicamente continuará até a primeira posição no espaço de armazenamento ser alcançada!
  • F6 Insere um caractere de final de arquivo (1Ah) na entrada atual.
    A tela mostrará "^ Z".
  • F7 Insere um byte zero na entrada atual.
    A tela mostrará "^ @".
  • ctrl Digite Transitions para a próxima linha (executando um retorno de carro e avanço de linha), nada é adicionado à entrada atual e você não pode voltar atrás.

Muitas outras chaves de edição estão disponíveis. Eles são todos reminiscentes de EDLIN.EXE , o antigo editor de linhas do DOS, que é um editor de texto no qual cada linha anterior se torna o modelo no qual você constrói a próxima linha.

  • F1 Copia um caractere do modelo para a nova linha.
  • F2 + ... Copia todos os caracteres do modelo para a nova linha, até o caractere especificado.
  • F3 Copia todos os caracteres restantes no modelo para a nova linha.
  • F4 + ... Pula os caracteres no modelo, até o caractere especificado.
  • F5 Torna a nova linha o novo modelo.
  • Escape Limpa a entrada atual e deixa o modelo inalterado.
  • Excluir Salta um caractere no modelo.
  • Inserir Entra ou sai do modo de inserção.
  • Backspace Exclui o último caractere da nova linha e coloca o cursor de volta em um caractere no modelo.
  • Esquerda mesmo que o Backspace.
  • Direita O mesmo que F1.

Guias são expandidas por esta função. A expansão de tabulação é o processo de substituir o ASCII 9 por uma série de um ou mais espaços (ASCII 32) até que o cursor atinja uma posição de coluna que seja um múltiplo de 8.
Essa expansão da guia só acontece na tela. O espaço de armazenamento conterá o ASCII 9.

Esta função faz ctrl C / ctrl Break checking.

Quando esta função terminar, o cursor estará na coluna da esquerda na linha atual.

Exemplo 1, Entrada STDIN armazenada em buffer.

        ORG     256                     ;Create .COM program
        cld
        mov     si, msg1
        call    WriteStringDOS
        mov     dx, buf
        mov     ah, 0Ah                 ;DOS.BufferedInput
        int     21h
        mov     si, msg2
        call    WriteStringDOS
        mov     si, buf+2
        movzx   bx, [si-1]              ;Get character count
        mov     word [si+bx+1], 10      ;Keep CR, append LF and 0
        call    WriteStringDOS
        mov     ax, 4C00h               ;DOS.TerminateWithExitcode
        int     21h
; --------------------------------------
; IN (ds:si) OUT ()
WriteStringDOS:
        pusha
        jmps    .b
.a:     mov     dl, al
        mov     ah, 02h                 ;DOS.DisplayCharacter
        int     21h                     ; -> AL
.b:     lodsb
        test    al, al
        jnz     .a
        popa
        ret
; --------------------------------------
buf:    db      255, 16, "I'm the template", 13, 255-16-1+2 dup (0)
msg1:   db      'Choose color ? ', 0
msg2:   db      10, 'You chose ', 0
; --------------------------------------

Introdução de texto usando int 21h AH=3Fh

Quando usada com o identificador predefinido 0 (em BX ), essa função Ler de arquivo ou dispositivo obtém caracteres do teclado e continua fazendo isso até que o usuário pressione Enter . Todos os caracteres (nunca mais de 127) e o retorno final de carro mais um avanço de linha adicional são colocados em um buffer privado dentro do kernel do DOS. Isso agora se torna o novo modelo.
A seguir, a função gravará no buffer fornecido no DS:DX , a quantidade de bytes solicitados no parâmetro CX . Se o CX tiver especificado um número menor que o número de bytes gerados por essa entrada, uma ou mais chamadas adicionais para essa função serão necessárias para recuperar a entrada completa. Enquanto houver caracteres restantes, esta função não iniciará outra sessão de entrada usando o teclado! Isso é verdade mesmo entre diferentes programas ou sessões do mesmo programa.

Todas as teclas de edição descritas na seção anterior estão disponíveis.

Guias são expandidas apenas na tela, não no modelo.

Esta função faz ctrl C / ctrl Break checking.

Quando esta função terminar, o cursor estará na coluna da esquerda

  • linha atual se o avanço de linha de terminação não estava entre os bytes retornados.
  • próxima linha se o avanço de linha de terminação estiver entre os bytes retornados.

Exemplo 2a, Leia do arquivo ou dispositivo, pegue tudo de uma vez.

        ORG     256                     ;Create .COM program
        cld
        mov     si, msg1
        call    WriteStringDOS
        mov     dx, buf
        mov     cx, 127+2               ;Max input is 127 chars + CR + LF
        xor     bx, bx                  ;STDIN=0
        mov     ah, 3Fh                 ;DOS.ReadFileOrDevice
        int     21h                     ; -> AX CF
        jc      Exit
        mov     bx, ax                  ;Bytes count is less than CX
        mov     si, msg2
        call    WriteStringDOS
        mov     si, buf
        mov     [si+bx], bh             ;Keep CR and LF, append 0 (BH=0)
        call    WriteStringDOS
Exit:   mov     ax, 4C00h               ;DOS.TerminateWithExitcode
        int     21h
; --------------------------------------
; IN (ds:si) OUT ()
WriteStringDOS:
        pusha
        jmps    .b
.a:     mov     dl, al
        mov     ah, 02h                 ;DOS.DisplayCharacter
        int     21h                     ; -> AL
.b:     lodsb
        test    al, al
        jnz     .a
        popa
        ret
; --------------------------------------
buf:    db      127+2+1 dup (0)
msg1:   db      'Choose color ? ', 0
msg2:   db      'You chose ', 0
; --------------------------------------

Exemplo 2b, Leia do arquivo ou dispositivo, escolha um byte de cada vez.

        ORG     256                     ;Create .COM program
        cld
        mov     si, msg1
        call    WriteStringDOS
        mov     dx, buf
        mov     cx, 1
        xor     bx, bx                  ;STDIN=0
        mov     ah, 3Fh                 ;DOS.ReadFileOrDevice
        int     21h                     ; -> AX CF
        jc      Exit
        mov     si, msg2
        call    WriteStringDOS
        mov     si, dx                  ;DX=buf, CX=1, BX=0
Next:   mov     ah, 3Fh                 ;DOS.ReadFileOrDevice
        int     21h                     ; -> AX CF
        jc      Exit
        call    WriteStringDOS          ;Display a single byte
        cmp     byte [si], 10
        jne     Next
Exit:   mov     ax, 4C00h               ;DOS.TerminateWithExitcode
        int     21h
; --------------------------------------
; IN (ds:si) OUT ()
WriteStringDOS:
        pusha
        jmps    .b
.a:     mov     dl, al
        mov     ah, 02h                 ;DOS.DisplayCharacter
        int     21h                     ; -> AL
.b:     lodsb
        test    al, al
        jnz     .a
        popa
        ret
; --------------------------------------
msg1:   db      'Choose color ? ', 0
msg2:   db      10, 'You chose '
buf:    db      0, 0
; --------------------------------------

Introdução de texto usando int 2Fh AX=4810h

Esta função de Entrada STDIN Buffered DOSKEY só pode ser chamada se o TSR DOSKEY.COM estiver instalado . Ele opera de maneira muito parecida com a função de Entrada STDIN Buffered regular 0Ah (veja acima), mas tem todas as mesmas possibilidades de edição que a linha de comando do DOS, incluindo a habilidade de usar todas as teclas especiais do DOSKEY.

  • Up Obtém o item anterior do histórico.
  • Down Obtém o próximo item do histórico.
  • F7 Mostra uma lista de todos os itens no histórico.
  • Alt F7 Limpa a história.
  • ... F8 Encontra o (s) item (s) que começam com ...
  • F9 Seleciona um item do histórico por número.
  • Alt F10 Remove todas as macrodefinições.

No DOS 6.2, o espaço de armazenamento é sempre limitado a 128 bytes, permitindo uma entrada de 127 caracteres e espaço para o retorno de carro obrigatório. Não é possível pré-carregar um modelo, portanto, sempre defina o segundo byte do buffer de entrada para zero.
No DOS Win95, o espaço de armazenamento pode ser tão grande quanto 255 bytes se você instalou o DOSKEY.COM TSR com um comando como doskey /line:255 . É possível pré-carregar o espaço de armazenamento com um modelo. Isso traz a versão do Win95 muito próxima do que é viável com a função de entrada 0Ah.

Esta função faz ctrl C / ctrl Break checking.

Quando esta função terminar, o cursor estará na coluna da esquerda na linha atual. Se a contagem de caracteres for zero, significa que o usuário digitou o nome de uma macro DOSKEY que ainda não estava expandida. Você não consegue ver a linha não expandida! Uma segunda invocação da função é necessária e, ao retornar desta vez, o cursor ficará atrás do último caractere do texto expandido.
Uma peculiaridade é que quando uma macro multi-comando ( $T ) é expandida, você só obtém o texto expandido do primeiro comando. Invocações adicionais da função são necessárias para obter os outros textos expandidos. Embora tudo isso seja muito útil em um shell de comando como o COMMAND.COM, de dentro de um aplicativo de usuário é realmente irritante não ser possível saber quando isso acontece.

Como o texto inserido é adicionado ao histórico de comandos, é inevitável que o histórico seja preenchido com itens não relacionados. Certamente não o que você quer ver no prompt do DOS!

Exemplo 3, Invocando DOSKEY.COM.

        ORG     256                     ;Create .COM program
        cld
        mov     ax, 4800h               ;DOSKEY.CheckInstalled
        int     2Fh                     ; -> AL
        test    al, al
        mov     si, err1
        jz      Exit_
Again:  mov     si, msg1
        call    WriteStringDOS
        mov     dx, buf
        mov     ax, 4810h               ;DOSKEY.BufferedInput
        int     2Fh                     ; -> AX
        test    ax, ax
        mov     si, err2
        jnz     Exit_
        cmp     [buf+1], al             ;AL=0
        je      Again                   ;Macro expansion needed
        mov     si, msg2
        call    WriteStringDOS
        mov     si, buf+2
        movzx   bx, [si-1]              ;Get character count (is GT 0)
        mov     word [si+bx+1], 10      ;Keep CR, append LF and 0
Exit_:  call    WriteStringDOS
Exit:   mov     ax, 4C00h               ;DOS.TerminateWithExitcode
        int     21h
; --------------------------------------
; IN (ds:si) OUT ()
WriteStringDOS:
        pusha
        jmps    .b
.a:     mov     dl, al
        mov     ah, 02h                 ;DOS.DisplayCharacter
        int     21h                     ; -> AL
.b:     lodsb
        test    al, al
        jnz     .a
        popa
        ret
; --------------------------------------
buf:    db      128, 0, 128+2 dup (0)
msg1:   db      'Choose color ? ', 0
msg2:   db      13, 10, 'You chose ', 0
err1:   db      'N/A', 13, 10, 0
err2:   db      'Failed', 13, 10, 0
; --------------------------------------

Introdução de texto usando int 21h AH=08h

Devido ao limite de 30000 bytes que o impõe, o texto continua na resposta abaixo ...

Problema na compreensão da fonte? O assembler que usei:

  • considera rótulos que começam com um ponto ( . ) como rótulos locais de primeiro nível
  • considera rótulos que começam com dois pontos (:) como rótulos locais de segundo nível
  • é Single Instruction Multiple Operand (SIMO), então push cx si traduz para push cx push si .




x86-16