assembly 汇编16位真实的模式- CMPS始终返回0

h9a6wy2h  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(109)

我想做一个16位汇编的小操作系统。在这段代码中,我创建了一种“终端”,在这里我接受用户输入,如果输入是shutdown,则启动函数关闭所有内容,否则什么都不会发生,循环继续(现在,稍后我将创建其他函数,因此如果命令不是“shutdown”,则其他检查将开始查看它是否是另一个命令)
代码:

bits 16

section .kernel
global _start_kernel

_start_kernel:
    mov ax, 0x3
    int 10h

    commandLoop:
        mov si, user
        call print

        mov di, input_string
        call input

        mov si, input_string
        call print

        ifCommandShutdown:
            cld
            mov si, C_shutdown
            mov di, input_string
            mov cx, CL_shutdown
            cmpsb
            jz thenCommandShutdown

        elseCommandShutdown:
            call newLine
            jmp commandLoop

        thenCommandShutdown:
            call shutdown

    exit:
        cli
        hlt

%include "lib/console.asm"
%include "lib/system.asm"

user: db "user >> ", 0
input_string:

;- Commands Variables ------------------------------+
;                                                   |
C_shutdown:  db "shutdown", 0 ;                     |
C_reboot:    db "reboot"  , 0 ;                     |
;                                                   |
CL_shutdown: db $ - C_shutdown ;                    |
CL_reboot:   db $ - C_reboot   ;                    |
;                                                   |
;---------------------------------------------------+

times 512-($-$$) db 0

字符串
console.asm:

print:
    mov ah, 0x0e
    characterLoop:
        lodsb
        or al, al
        jz break
        int 10h

    jmp characterLoop

    break:
        ret

input:
    mov ah, 0x0
    int 16h

    ifKeyIsEnter:
        cmp al, 0x0D
        jz enterIsPressed
    elseEnterKey:
        stosb
        mov ah, 0x0e
        int 10h
    jmp input

    enterIsPressed:
        mov al, 0x0
        stosb
        call newLine
        ret

newLine:
    mov ah, 0x0e
    mov al, 13
    int 10h

    mov al, 10
    int 10h

    ret


system.asm:

shutdown:
    mov ax, 0x1000
    mov ax, ss
    mov sp, 0xf000
    mov ax, 0x5307
    mov bx, 0x0001
    mov cx, 0x0003
    int 0x15


编译时没有错误,但在qemu中它总是关闭

myss37ts

myss37ts1#

cmps始终返回0
看看你是如何布局内存的(忘记为输入分配空间):

input_string:
C_shutdown:  db "shutdown", 0

字符串
输入只是覆盖了你将要比较的文本。显然,一个字符比较cmpsb总是会找到匹配。
因为你要验证和查看的是完整的单词'shutdown':

cld
mov si, C_shutdown
mov di, input_string
mov cx, CL_shutdown
cmpsb


如果您 * 尝试在CX* 中设置计数,则应在cmpsb指令前添加repe(RepeatWhileEqual)前缀。
当前加载计数是错误的,因为您使用字节大小的变量 CL_shutdown地址加载它,而您需要该变量的实际内容。但最好将这些长度定义为相等:

user:         db    "user >> ", 0
input_string: times 20 db 0
C_shutdown:   db    "shutdown", 0
CL_shutdown:  equ   $ - C_shutdown
C_reboot:     db    "reboot"  , 0
CL_reboot:    equ   $ - C_reboot


然后,要比较的代码变为(假设DS和ES已正确设置并且彼此相等):

cld
mov  si, C_shutdown     ; DS:SI
mov  di, input_string   ; ES:DI
mov  cx, CL_shutdown
repe cmpsb
jz   thenCommandShutdown
shutdown:
  mov ax, 0x1000
  mov ax, ss
  mov sp, 0xf000

的字符串
另一个错误是 shutdownmov ax, 0x1000mov ax, ss指令没有意义(加载AX两次)。应改为:

mov  ax, 0x1000
mov  ss, ax
mov  sp, 0xF000

相关问题