缓冲输入的工作原理

时间:2017-11-19 16:16:54

标签: assembly input dos x86-16

下一个程序的输入工作正常,但是当我要求显示输出时,DOS  根本不显示任何东西!这怎么可能?

        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 : ', '$'
; --------------------------------------

2 个答案:

答案 0 :(得分:3)

看看你如何定义输入缓冲区(buf: db 20 dup ('$')),我明白了  你想要偷工减料并且输入已经为$ -terminated准备好了  重新显示它。遗憾的是,这会扰乱DOS输入所需的设置  功能0Ah和您的程序遇到潜在缓冲区的严重问题  超限。
此外,使用$ -termination并不是您可以做出的最明智的选择  因为$字符可能已经出现在输入的字符中。  我在下面介绍的所有示例程序都将使用零终止  代替。

使用int 21h AH=0Ah

输入文字

Buffered STDIN Input函数从键盘获取字符  继续这样做,直到用户按下 Enter 键。所有  字符和最终回车符放在存储空间中  从调用程序提供的输入缓冲区的第3个字节开始  通过DS:DX中的指针 不包括最终回车的字符数存储在  输入缓冲区的第二个字节 调用程序的责任是告诉DOS有多大  存储空间是。因此,您必须将其长度放在第1个字节中  调用此函数前输入缓冲区。允许输入1  您将存储大小设置为2的字符。允许输入254  您将存储大小设置为255的字符 如果您不希望能够从模板中调用之前的任何输入,  那么最好也将第二个字节归零。基本上模板是  调用程序的输入缓冲区中预先存在的(和有效的)内容  提供。如果预先存在的内容无效,则模板不是  可用。

令人惊讶的是,此功能的编辑功能有限。

  • Escape 从当前输入中删除所有字符 当前输入被放弃但保留在屏幕上并且光标被放置 下一行,输入首先开始的位置。
  • Backspace 从当前输入中删除最后一个字符 如果输入保持在屏幕上的单行内,则按预期工作。 另一方面,如果输入跨越多行,那么这个退格将会 停在屏幕的左边缘。从那时起将会有一个严重的问题 逻辑输入和视觉输入之间的差异,因为逻辑 退刀将一直持续到达存储空间的第一个位置!
  • F6 在当前输入中插入文件结尾字符(1Ah)。
    屏幕将显示" ^ Z"。
  • F7 在当前输入中插入一个零字节 屏幕将显示" ^ @"。
  • ctrl 输入转换到下一行(执行 回车和换行),没有任何东西被添加到当前输入,你 无法回去。

可以使用更多编辑键。它们都让人想起 EDLIN.EXE ,  古老的DOS行编辑器,它是每个前一行的文本编辑器  成为构建下一行的模板。

  • F1 将模板中的一个字符复制到新行。
  • F2 + ... 将模板中的所有字符复制到新行,直到指定的字符。
  • F3 将模板中的所有剩余字符复制到新行。
  • F4 + ... 跳过模板中的字符,向上 到指定的角色。
  • F5 使新行成为新模板。
  • Escape 清除当前输入并保持模板不变。
  • 删除跳过模板中的一个字符。
  • 插入进入或退出插入模式。
  • Backspace 删除新行的最后一个字符,并将光标放回模板中的一个字符。
  • 与Backspace相同。
  • 与F1相同。

此功能扩展了标签。标签扩展是替换的过程 ASCII 9由一系列一个或多个空格(ASCII 32)直到光标到达  列位置是8的倍数 此选项卡扩展仅在屏幕上发生。存储空间将保留ASCII 9。

此函数执行 ctrl C / ctrl Break  检查。

当此功能完成时,光标将位于最左侧的列中  当前行。

示例1,缓冲STDIN输入。

        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
; --------------------------------------

使用int 21h AH=3Fh

输入文字

与预定义句柄0(BX)一起使用时Read From File Or Device  函数从键盘获取字符并继续这样做,直到  用户按 Enter 。所有字符(从不超过127)和  最后的回车加上额外的换行符放在私人中  DOS内核中的缓冲区。这现在成为新模板 此后,该函数将写入DS:DX提供的缓冲区中的金额  CX参数中请求的字节数。如果CX指定了一个数字  它小于此输入生成的一个或多个字节数  需要额外调用此函数才能检索完整的输入。  只要有剩余的字符被拿起,这个功能就会  不使用键盘启动另一个输入会话!这之间甚至是如此  不同的程序或同一程序的会话。

上一节中描述的所有编辑键都可用。

标签仅在屏幕上展开,而不是在模板中展开。

此函数执行 ctrl C / ctrl Break  检查。

当此功能完成时,光标将位于

的最左列
  • 当前行,如果终止换行符不在返回的字节中。
  • 如果终止换行符在返回的字节中,则
  • 下一行。

示例2a,从文件或设备读取,一次全部接收。

        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
; --------------------------------------

示例2b,从文件或设备读取,一次拾取一个字节。

        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
; --------------------------------------

使用int 2Fh AX=4810h

输入文字

DOSKEY Buffered STDIN Input函数只能调用if the DOSKEY.COM TSR was installed。它的运行方式与常规的Buffered非常相似  STDIN输入功能0Ah(见上文),但具有相同的编辑功能  作为DOS命令行的可能性,包括使用所有的能力  DOSKEY特殊键。

  • Up 从历史记录中获取上一个项目。
  • Down 从历史记录中获取下一个项目。
  • F7 显示历史记录中所有项目的列表。
  • Alt F7 清除历史记录。
  • ... F8 查找以...开头的项目
  • F9 按编号从历史记录中选择一个项目。
  • Alt F10 删除所有宏定义。

在DOS 6.2上,存储空间始终限制为128个字节,允许输入  127个字符和强制回车的空间。不是  可以预先加载模板,因此始终设置输入的第二个字节  缓冲到零。
在DOS Win95上,如果安装了,则存储空间可以大到255个字节  DOSKEY.COM TSR使用doskey /line:255之类的命令。它有可能  使用模板预加载存储空间。这带来了Win95版本  非常接近输入函数0Ah可行的。

此函数执行 ctrl C / ctrl Break  检查。

当此功能完成时,光标将位于最左侧的列中  当前行。如果字符数为零,则表示用户输入了  尚未展开的DOSKEY宏的名称。你没有  去看看未展开的线!需要第二次调用该函数  并且在这次返回时,光标将位于最后一个字符的后面  扩展文本。
一个特点是,当多命令宏($T)扩展时,您只能  获取第一个命令的扩展文本。额外的调用  获取其他扩展文本需要函数。虽然这一切都是  在COMMAND.COM等命令shell中,从用户内部非常有用  应用它真的很烦人,你不知道什么时候发生这种情况。

由于输入的文本被添加到命令历史中,因此不可避免  历史填补了无关的项目。当然不是你想看到的  在DOS提示符下!

示例3,调用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
; --------------------------------------

使用int 21h AH=08h

输入文字
  

由于Stack Overflow强加的30000字节限制,文本在下面的答案中继续...

了解来源的问题?我使用的汇编程序:

  • 将以点()开头的标签视为第一级本地标签
  • 将以冒号()开头的标签视为第二级本地标签
  • 是单指令多操作数(SIMO),因此push cx si 转换为push cx push si

答案 1 :(得分:2)

使用int 21h AH=08h

输入文字

到目前为止所描述的所有三种输入方法(在上面的答案!中)都是明确量身定制的,以适应像EDLIN.EXE和COMMAND.COM这样的Microsoft工具。
如果您正在编写自己的应用程序,那么可以获得更好的结果  通过制作自己的输入程序。这种程序的核心  将是DOS单字符输入函数之一。我选择了STDIN Input函数08h,因为我想允许   ctrl C / ctrl 打破检查和我  打算通过BIOS Int 10h AH=09h自己回应这些角色  Write Character And Attribute At Cursor Position。这样我就可以  避免弄乱任何重定向输出。

以编程方式使用此 BufferedInput 过程没有区别  或 DOS.BufferedInput 系统调用。但是对于键盘上的用户  输入将更容易,因为所有键与旧和  困难的模板编辑已被解雇并被通常的替换  编辑键,使您可以自由移动光标。

  • 向左移动光标。
  • 向右移动光标。
  • Home 将光标移动到最左侧。
  • 结束将光标移动到最右侧。
  • Ctrl Home 删除左侧的所有字符。
  • Ctrl 结束删除右侧的所有字符。
  • 删除删除当前字符。
  • Backspace 删除光标左侧的字符。
  • Escape 删除所有字符。
  • 返回结束输入。

如果输入缓冲区的第二个字节保持非零值,则存储空间  应该包含一个旧字符串(可能来自以前的输入)。 DOS会  把这称为模板。与DOS不同的是:

  • 旧字符串不需要回车。
  • 旧字符串会立即显示在屏幕上。

当输入正在进行时,标签展开且输入为  仅限于留在当前行内。较长的文本将水平滚动。
最后完成输入后,已完成的文本将选项卡一次写入  扩展(在屏幕上,存储空间将始终保持ASCII 9)并且不再局限于单行。

此程序执行 ctrl C / ctrl Break  检查。

当此过程完成时,光标将位于最左侧的列中  当前行。

此程序是用input redirection and output redirection编写的  记住,因此非常适合控制台应用。
输入重定向的一个影响是将任何临时输出回显到屏幕是没用的。用户不在那里凝视屏幕,或者临时输出将在眨眼之间消失。

示例4,改进的缓冲STDIN输入。

        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
; --------------------------------------

了解来源的问题?我使用的汇编程序:

  • 将以点()开头的标签视为第一级本地标签
  • 将以冒号()开头的标签视为第二级本地标签
  • 是单指令多操作数(SIMO),因此push cx si 转换为push cx push si
  

要获得真正高效的输入程序,请查看Rich Edit Form Input,即代码审核贡献。