我的读写字符串函数吐出 %%% 而不是我输入的 3 个字符

My read and write string function spits out %%% instead of the 3 characters I put in

所以我已经开始写一个“内核”,可以这么说,我正在尝试读取一个字符串并将其打印回给我。当我执行它时问题就来了,它只打印 3 个相同的字符,而不是我在行上写的内容。

read_string:
    call newline
    mov si, read_attempt
    call print
    call newline
    push bx
    mov ah, 0x03
    int 0x10
    mov dl, 0
    int 0x10
                    ;read 1st char
    mov ah, 0x08
    int 0x10
    mov bl, al
    pop bx
                    ;read 2nd char
    mov ah, 0x03
    int 0x10
    add dl, 1
    int 0x10
    mov ah, 0x08
    int 0x10
    mov bl, al
    pop bx
                    ;read 3rd char
    mov ah, 0x03
    int 0x10
    add dl, 1
    int 0x10
    mov ah, 0x08
    int 0x10
    mov bl, al
    pop bx
                    ;try to write all 3 chars
    call newline
    mov si, write_attempt
    call print
    call newline
    push bx
    mov al, bl
    call printchar
    push bx
    mov al, bl
    call printchar
    push bx
    mov al, bl
    call printchar
    call newline
    mov si, read_write_success
    call print
    call newline
    ret

请记住,“第二扇区”之前的所有内容都是 2 个月前写的,之后的所有内容都是过去 2 天写的。我也在使用 NASM 到 assemble 代码。

这是它正在做的事情的图片imgur

您在使用 push 时表示 pop,反之亦然。 Push 在堆栈上保存一个值,而 pop 从堆栈中检索一个值。所以代码的写法,打印了三次bl中的值。它还会弄乱堆栈上的 return 地址。确保你的推动和弹出是平衡的。

您正在屏幕上打印一些文本,然后试图从屏幕上读取该文本的前 3 个字符。对吧?

使用 BIOS 功能 08h 可以实现此效果,但您每次都忘记定位光标!

call newline
mov  si, read_attempt
call print
call newline    ;(*)

这刚刚输出了一些文本,光标位于第一个字符下方。
要找出行,您需要使用 BIOS 功能 03h,然后向上移动 1 行。
你只需要在BH中指定显示页面一次,前提是你不使用BH注册其他任何东西!
重要提示:不要忘记指定函数编号。

mov  bh, 0      ;Select display page 0
mov  ah, 03h    ;BIOS.GetCursor -> CL, CH, DL, DH
int  10h

dec  dh         ;Go 1 row up, Column is at 0 because of (*)
mov  ah, 02h    ;BIOS.SetCursor
int  10h

mov  ah, 08h    ;BIOS.ReadCharacterAndAttribute -> AL, AH
int  10h
push ax         ;Save 1st character on stack

无需重新读取光标位置,因为 DLDH 寄存器仍保留该位置。只需增加 DL 中的列并通过 BIOS 进行设置:

inc  dl         ;Go 1 column right
mov  ah, 02h    ;BIOS.SetCursor
int  10h

mov  ah, 08h    ;BIOS.ReadCharacterAndAttribute -> AL, AH
int  10h
push ax         ;Save 2nd character on stack

重复第三个字符:

inc  dl         ;Go 1 column right
mov  ah, 02h    ;BIOS.SetCursor
int  10h

mov  ah, 08h    ;BIOS.ReadCharacterAndAttribute -> AL, AH
int  10h
push ax         ;Save 3rd character on stack

打印使用:

pop  ax         ;Restore 3rd character
call printchar
pop  ax         ;Restore 2nd character
call printchar
pop  ax         ;Restore 1st character
call printchar

由于堆栈的工作原理,字符将以相反的顺序显示
如果顺序很重要,请从屏幕上的第 3 个字符开始阅读,然后从头开始阅读。

mov  bh, 0      ;Select display page 0
mov  ah, 03h    ;BIOS.GetCursor -> CL, CH, DL, DH
int  10h
 MOV  DL, 2      ;START AT 3RD CHARACTER
dec  dh         ;Go 1 row up
mov  ah, 02h    ;BIOS.SetCursor
int  10h
mov  ah, 08h    ;BIOS.ReadCharacterAndAttribute -> AL, AH
int  10h
push ax         ;Save 3rd character on stack
 DEC  DL         ;GO 1 COLUMN LEFT
mov  ah, 02h    ;BIOS.SetCursor
int  10h
mov  ah, 08h    ;BIOS.ReadCharacterAndAttribute -> AL, AH
int  10h
push ax         ;Save 2nd character on stack
 DEC  DL         ;GO 1 COLUMN LEFT
mov  ah, 02h    ;BIOS.SetCursor
int  10h
mov  ah, 08h    ;BIOS.ReadCharacterAndAttribute -> AL, AH
int  10h
push ax         ;Save 1st character on stack
...
pop  ax         ;Restore 1st character
call printchar
pop  ax         ;Restore 2nd character
call printchar
pop  ax         ;Restore 3rd character
call printchar