16位实模式汇编CMPS指令始终返回0致误触发关机问题求助
问题描述
我正在用16位汇编开发一个小型操作系统,目前实现了简易终端功能:获取用户输入,若输入为“shutdown”则执行关机函数,否则循环等待下一次输入(后续会扩展其他指令判断)。编译无错误,但在QEMU中运行时,无论输入什么内容都会触发关机,排查后发现CMPS指令始终返回0。
主程序代码
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
问题分析与修复
命令长度类型错误:
CL_shutdown用db定义为字节,但mov cx, CL_shutdown会将16位寄存器CX的高8位填充垃圾值,导致比较长度完全错误。需改为dw(字类型):CL_shutdown: dw $ - C_shutdown ; CL_reboot: dw $ - C_reboot ;单次比较逻辑错误:
cmpsb默认仅比较一个字节,需配合repe前缀实现全字符串匹配,只有当所有字节都相等时才触发跳转:ifCommandShutdown: cld mov si, C_shutdown mov di, input_string mov cx, CL_shutdown repe cmpsb ; 重复比较直到CX为0或字节不相等 jz thenCommandShutdown ; 全匹配时跳转执行关机输入缓冲区未分配:
input_string仅为标签,无预留空间,输入内容可能覆盖后续命令字符串。需分配足够缓冲区:input_string: times 64 db 0 ; 64字节输入缓冲区
内容的提问来源于stack exchange,提问作者Federico Occhiochiuso
相关产品推荐
相关产品推荐

