【问题标题】:How to save keyboard input to a register in assembly?如何将键盘输入保存到程序集中的寄存器中?
【发布时间】:2021-09-13 11:43:54
【问题描述】:

所以我基本上是在制作一个基本的命令行操作系统,并且我已经制作了它,以便当我按下回车键时它可以按键盘和一个程序进入新行,但我希望它在移动之前将命令存储为字符串到一个新行,以便我可以将命令与用户输入进行比较,以便我可以让它打印一个字符串或做一些事情,那么我们如何加入所有的字符并制作一个字符串,这是我到目前为止的代码

;bg
MOV AH, 06h   
XOR AL, AL    
XOR CX, CX    
MOV DX, 184FH  
MOV BH, 1Eh  
INT 10H
;cursor
mov dh, 1
mov dl, 30
mov bh, 0
mov ah, 2
int 10h
;text
mov ah, 0x0E
mov al, 'W'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'E'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'L'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'C'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'O'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'M'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'E'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, ' '
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'T'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'O'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, ' '
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'D'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'A'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'R'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'S'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'H'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'O'
mov bh, 0x00
int 10h
mov ah, 0x0E
mov al, 'S'
mov bh, 0x00
int 10h
;cursor
mov dh, 3
mov dl, 2
mov bh, 0
mov ah, 2
int 10h
;commandline
Key:
    MOV AH,0 
    INT 16H
    cmp ah, 28
    je Newline
    mov ah, 0eh
    int 10h
    jmp Key

Newline:

    add dh, 1
    mov dl, 2
    mov bh, 0
    mov ah, 2
    int 10h
    jmp Key
times 510-($-$$) db 0
dw 0xaa55

截图: img of the program

【问题讨论】:

    标签: assembly x86 qemu 16-bit


    【解决方案1】:

    作为第一个观察,您将所有这些都写在一个引导扇区中。这对于学习目的可能很好,但至少要意识到引导扇区的 512 字节大小限制。我的意思是,你不应该单独输出所有这些字符,而是作为一个字符串输出,这当然是你的问题,不是吗。

    先解决输出,输入存储问题类似

    使用以下代码启动您的引导扇区程序:

    ORG  7C00h
    xor  ax, ax
    mov  ds, ax
    mov  es, ax
    cld
    

    在程序底部附近插入此文本:

    msg  db 'WELCOME TO DARSHOS', 0
    times 510-($-$$) db 0
    dw 0xAA55
    

    如果您有很长的单字符输出链,则将整个链替换为以下内容:

    ;text
      mov  si, msg     ; Load address of the message in SI 
      mov  bh, 0       ; DisplayPage
      lodsb
    More:
      mov  ah, 0Eh     ; BIOS.Teletype
      int  10h
      lodsb            ; Retrieve a character, auto-increments the address SI
      cmp  al, 0
      jnz  More
    

    如果你的汇编器遵循 NASM 风格,mov si, msg 会加载消息的地址。但是如果你的汇编器遵循 MASM 风格,你将不得不写 mov si, offset msg


    为了保存输入的字符,需要定义一个合适的缓冲区。
    下面的 buf 行将允许最多 7 个字符的文本命令,后跟分隔回车符。您需要分隔符以便稍后知道完整命令有多长。在程序底部附近插入以下行:

    buf  db '........'
    msg  db 'WELCOME TO DARSHOS', 0
    times 510-($-$$) db 0
    dw 0xAA55
    

    这就是你填写它的方式:

    ;commandline
    Key:
        mov  di, buf   ; Load address of the buffer in DI
    Next:
        mov  ah, 00h   ; BIOS.GetKeyboardKey
        int  16h       ; -> AX
        stosb          ; Store in buffer, auto-increments the address DI
        mov  bh, 0     ; DisplayPage
        mov  ah, 0Eh   ; BIOS.Teletype
        int  10h
        cmp  al, 13
        jne  Next      ; Not yet carriage return
        mov  al, 10    ; Let follow a linefeed to complete the 'newline' sequence
        int  10h
        ...
    

    ...,您可以开始处理构成命令的字符串,例如CLSTIME,或任何适合您的东西。

    【讨论】:

    • 谢谢您的回复,我照您说的做了,但是我是否将输入的文本与我想要的命令进行比较,例如我尝试使用 cmp 的“--help 或--cls”,但它给出了一个在线错误“不正确的 optcode 和 opreands”请帮助我,我对 asm 和 osdev 真的很陌生
    • 还有如何获得更多的数据空间,正如你所说的,引导扇区中只能有 512 字节的代码
    • @DarshCubing 引导扇区的大小是固定的,但诀窍是用引导加载程序填充引导扇区。该代码的唯一工作就是从磁盘加载操作系统的其余部分。您可以在此答案stackoverflow.com/questions/34216893/… 中找到一个示例。把它做好绝对不是一件容易的事!如果学习汇编语言是你真正想要的,那么也许可以考虑编写 .COM 程序而不是更难的操作系统开发......
    • @DarshCubing 关于将新输入的文本与可用命令列表进行比较的问题,我认为值得单独提出一个问题。非常欢迎您发布它。在进入一个新问题之前,正确的做法当然是接受当前问题的答案,这样人们就可以看到它已经被处理了。
    • 感谢回复我发布的问题请看一下:stackoverflow.com/questions/69202323/…
    猜你喜欢
    • 2021-08-13
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多