Cómo funciona la entrada almacenada en búfer
La entrada en el siguiente programa (usando la función DOS.BufferedInput 0Ah) funciona bien, pero cuando pido mostrar la salida, DOS no muestra nada en absoluto. ¿Cómo es esto posible?
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 : ', '$'
; --------------------------------------
Tenga en cuenta que estas preguntas y respuestas autocontestadas vienen con una respuesta de dos partes. Cualquier persona interesada debe comenzar su lectura con la respuesta aceptada .
Al observar cómo definió su búfer de entrada ( buf: db 20 dup ('$')
), entiendo que desea tomar atajos y tener la entrada terminada en $ lista para volver a mostrarla. Lamentablemente, esto arruina la configuración requerida para la función de entrada de DOS 0Ah y su programa tiene serios problemas con una posible saturación del búfer.
Además, usar la terminación $ no es la elección más inteligente que puede hacer, ya que el carácter $ ya podría aparecer entre los caracteres ingresados. Todos los programas de ejemplo que presento a continuación utilizarán terminación cero en su lugar.
Ingresando texto usandoint 21h AH=0Ah
Esta función de entrada STDIN almacenada en búfer obtiene caracteres del teclado y continúa haciéndolo hasta que el usuario presiona la Entertecla. Todos los caracteres y el retorno de carro final se colocan en el espacio de almacenamiento que comienza en el tercer byte del búfer de entrada proporcionado por el programa que llama mediante el puntero en DS:DX
.
El recuento de caracteres, sin incluir el retorno de carro final, se almacena en el segundo byte del búfer de entrada.
Es responsabilidad del programa que llama decirle a DOS qué tan grande es el espacio de almacenamiento. Por lo tanto, debes poner su longitud en el primer byte del búfer de entrada antes de llamar a esta función. Para permitir una entrada de 1 carácter, establezca el tamaño de almacenamiento en 2. Para permitir una entrada de 254 caracteres, establezca el tamaño de almacenamiento en 255.
Si no desea poder recuperar de la plantilla ninguna entrada anterior, entonces es mejor poner a cero también el segundo byte. Básicamente, la plantilla es el contenido preexistente (y válido) en el búfer de entrada que proporcionó el programa de llamada. Si el contenido preexistente no es válido, la plantilla no estará disponible.
Sorprendentemente, esta función tiene funciones de edición limitadas.
- EscapeElimina todos los caracteres de la entrada actual.
La entrada actual se abandona pero permanece en la pantalla y el cursor se coloca en la siguiente fila, debajo de donde comenzó la entrada. - BackspaceElimina el último carácter de la entrada actual.
Funciona como se esperaba si la entrada permanece dentro de una sola fila en la pantalla. Si, por otro lado, la entrada abarca varias filas, este retroceso se detendrá en el borde izquierdo de la pantalla. A partir de entonces habrá una grave discrepancia entre la entrada lógica y la entrada visual porque lógicamente el retroceso continuará hasta que se alcance la primera posición en el espacio de almacenamiento. - F6Inserta un carácter de fin de archivo (1Ah) en la entrada actual.
La pantalla mostrará "^Z". - F7Inserta un byte cero en la entrada actual.
La pantalla mostrará "^@". - ctrlEnterPasa a la siguiente fila (ejecuta un retorno de carro y un salto de línea), no se agrega nada a la entrada actual y no se puede retroceder.
Hay muchas más claves de edición disponibles. Todos recuerdan a EDLIN.EXE , el antiguo editor de líneas de DOS, que es un editor de texto donde cada línea anterior se convierte en la plantilla sobre la cual se construye la siguiente línea.
- F1Copia un carácter de la plantilla a la nueva línea.
- F2+ ... Copia todos los caracteres de la plantilla a la nueva línea, hasta el carácter especificado.
- F3Copia todos los caracteres restantes de la plantilla en la nueva línea.
- F4+ ...Salta los caracteres de la plantilla, hasta el carácter especificado.
- F5Convierte la nueva línea en la nueva plantilla.
- EscapeBorra la entrada actual y deja la plantilla sin cambios.
- DeleteSalta un carácter en la plantilla.
- InsertEntra o sale del modo de inserción.
- BackspaceElimina el último carácter de la nueva línea y coloca el cursor un carácter atrás en la plantilla.
- LeftLo mismo que Retroceso.
- RightLo mismo que la F1.
Esta función amplía las pestañas. La expansión de pestañas es el proceso de reemplazar ASCII 9 por una serie de uno o más espacios (ASCII 32) hasta que el cursor alcanza una posición de columna que es múltiplo de 8.
Esta expansión de pestañas solo ocurre en la pantalla. El espacio de almacenamiento contendrá ASCII 9.
Esta función hace ctrlC/ ctrlBreak verifica.
Cuando finalice esta función, el cursor estará en la columna del extremo izquierdo de la fila actual.
Ejemplo 1, entrada STDIN almacenada en búfer.
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, byte [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
; --------------------------------------
Ingresando texto usandoint 21h AH=3Fh
Cuando se usa con el identificador predefinido 0 (en BX
), esta función Leer desde archivo o dispositivo
obtiene caracteres del teclado y continúa haciéndolo hasta que el usuario presiona Enter. Todos los caracteres (nunca más de 127) y el retorno de carro final más un salto de línea adicional se colocan en un búfer privado dentro del kernel de DOS. Esta ahora se convierte en la nueva plantilla.
De ahora en adelante la función escribirá en el buffer provisto en DS:DX
, la cantidad de bytes que fueron solicitados en el CX
parámetro. Si CX
se especifica un número menor que el número de bytes generados por esta entrada, se requieren una o más llamadas adicionales a esta función para recuperar la entrada completa. Mientras queden caracteres por seleccionar, esta función no iniciará otra sesión de entrada usando el teclado. Esto es cierto incluso entre diferentes programas o sesiones del mismo programa.
Están disponibles todas las claves de edición descritas en el apartado anterior.
Las pestañas se expanden sólo en la pantalla, no en la plantilla.
Esta función hace ctrlC/ ctrlBreak verifica.
Cuando finalice esta función, el cursor estará en la columna del extremo izquierdo de la
- fila actual si el salto de línea final no estaba entre los bytes devueltos.
- siguiente fila si el salto de línea final estaba entre los bytes devueltos.
Ejemplo 2a, Leer desde archivo o dispositivo, seleccione todo a la 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
; --------------------------------------
Ejemplo 2b, Lectura desde archivo o dispositivo, seleccione un byte a la 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
; --------------------------------------
Ingresando texto usandoint 2Fh AX=4810h
Esta función de entrada STDIN almacenada en búfer de DOSKEY sólo se puede invocar si se instaló DOSKEY.COM TSR . Funciona de manera muy similar a la función de entrada STDIN almacenada en búfer 0Ah (ver arriba), pero tiene las mismas posibilidades de edición que la línea de comando de DOS, incluida la capacidad de usar todas las teclas especiales de DOSKEY.
- UpObtiene el elemento anterior del historial.
- DownObtiene el siguiente elemento del historial.
- F7Muestra una lista de todos los elementos del historial.
- AltF7Borra el historial.
- ...F8Encuentra elementos que comienzan con...
- F9Selecciona un elemento del historial por número.
- AltF10Elimina todas las macrodefiniciones.
En DOS 6.2, el espacio de almacenamiento siempre está limitado a 128 bytes, lo que permite una entrada de 127 caracteres y espacio para el retorno de carro obligatorio. No es posible precargar una plantilla, por lo tanto, establezca siempre el segundo byte del búfer de entrada en cero.
En DOS Win95, el espacio de almacenamiento puede ser tan grande como 255 bytes si instaló DOSKEY.COM TSR con un comando comodoskey /line:255
. Es posible precargar el espacio de almacenamiento con una plantilla. Esto acerca la versión Win95 a lo que es factible con la función de entrada 0Ah.
Esta función hace ctrlC/ ctrlBreak verifica.
Cuando finalice esta función, el cursor estará en la columna del extremo izquierdo de la fila actual. Si el recuento de caracteres es cero, significa que el usuario escribió el nombre de una macro DOSKEY que aún no estaba expandida. ¡No podrás ver la línea no expandida! Es necesaria una segunda invocación de la función y al regresar esta vez, el cursor estará detrás del último carácter del texto expandido.
Una peculiaridad es que cuando se expande una macro de múltiples comandos ( $T
), solo se obtiene el texto expandido del primer comando. Se necesitan invocaciones adicionales de la función para obtener los otros textos expandidos. Aunque todo esto es muy útil desde un shell de comandos como COMMAND.COM, desde una aplicación de usuario es realmente molesto que no puedas saber cuándo sucede esto.
Dado que el texto ingresado se agrega al historial de comandos, es inevitable que el historial se llene con elementos no relacionados. ¡Ciertamente no es lo que desea ver en el indicador de DOS!
Ejemplo 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, byte [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
; --------------------------------------
Ingresando texto usandoint 21h AH=08h
Debido al límite de 30000 bytes que impone Stack Overflow, el texto continúa en la siguiente respuesta...
¿Problemas para entender la fuente? El ensamblador que utilicé:
- considera etiquetas que comienzan con un punto ( . ) como etiquetas locales de 1er nivel
- considera las etiquetas que comienzan con dos puntos ( : ) como etiquetas locales de segundo nivel
- es Instrucción única de múltiples operandos (SIMO), por lo que
push cx si
se traduce comopush cx
push si
.
Ingresando texto usandoint 21h AH=08h
Los tres métodos de entrada descritos hasta ahora (¡en la respuesta anterior!) fueron claramente hechos a medida para adaptarse a herramientas de Microsoft como EDLIN.EXE y COMMAND.COM.
Si está escribiendo su propia aplicación, podrá lograr mejores resultados produciendo su propio procedimiento de entrada. En el centro de dicho procedimiento estará una de las funciones de entrada de un solo carácter de DOS. Elegí la función de entrada STDIN 08h porque quiero permitir
ctrlC/ ctrlBreakverificar y tengo la intención de hacer eco de los caracteres yo mismo a través del BIOS Int 10h AH=09h
Escribir caracteres y atributos en la posición del cursor . De esta manera puedo evitar estropear cualquier salida redirigida.
Programáticamente no hay diferencia en el uso de este procedimiento BufferedInput o la llamada al sistema DOS.BufferedInput . Sin embargo, para el usuario escribir en el teclado será mucho más fácil ya que todas las teclas asociadas con la antigua y difícil edición de plantillas han sido descartadas y reemplazadas por las teclas de edición habituales que le permiten mover libremente el cursor.
- LeftMueve el cursor hacia la izquierda.
- RightMueve el cursor hacia la derecha.
- HomeMueve el cursor hacia el extremo izquierdo.
- EndMueve el cursor hacia el extremo derecho.
- CtrlHomeElimina todos los caracteres a la izquierda.
- CtrlEndElimina todos los caracteres a la derecha.
- DeleteElimina el carácter actual.
- BackspaceElimina el carácter a la izquierda del cursor.
- EscapeElimina todos los personajes.
- ReturnFinaliza la entrada.
Si el segundo byte del búfer de entrada contiene un valor distinto de cero, entonces se supone que el espacio de almacenamiento contiene una cadena antigua (quizás de una entrada anterior). DOS habría llamado a esto la plantilla. A diferencia de DOS es que:
- No es necesario que la cadena antigua tenga terminación de retorno de carro.
- la cadena antigua se muestra inmediatamente en la pantalla.
Mientras la entrada está en curso, las pestañas no se expanden y la entrada se limita a permanecer dentro de la fila actual. Los textos más largos se desplazarán horizontalmente.
Cuando finalmente se realiza la entrada, el texto completo se escribe una vez con expansión de pestañas (en la pantalla, el espacio de almacenamiento siempre tendrá ASCII 9) y ya no estará restringido a una sola fila.
Este procedimiento hace ctrlC/ ctrlBreak verifica.
Cuando finalice este procedimiento, el cursor estará en la columna del extremo izquierdo de la fila actual.
Este procedimiento se escribió teniendo en cuenta la redirección de entrada y la redirección de salida
y, por lo tanto, es muy adecuado para aplicaciones de consola.
Un efecto de la redirección de entrada es que es inútil hacer eco de cualquier salida temporal en la pantalla. O el usuario no está allí para mirar la pantalla o la salida temporal desaparecerá en un abrir y cerrar de ojos.
Ejemplo 4, entrada STDIN almacenada en búfer mejorada.
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, byte [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, byte [bp-6] ;INBOX
movzx si, byte [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, byte [bp-8] ;CIX
movzx cx, byte [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, byte [bp-8] ;CIX
movzx si, byte [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
; --------------------------------------
¿Problemas para entender la fuente? El ensamblador que utilicé:
- considera etiquetas que comienzan con un punto ( . ) como etiquetas locales de 1er nivel
- considera las etiquetas que comienzan con dos puntos ( : ) como etiquetas locales de segundo nivel
- es Instrucción única de múltiples operandos (SIMO), por lo que
push cx si
se traduce comopush cx
push si
.
Para conocer un procedimiento de entrada de muy alto rendimiento, consulte Entrada de formulario de edición enriquecida , una contribución de revisión de código.