操作系统停止比较字符串

时间:2019-07-11 10:56:47

标签: assembly x86 operating-system virtualbox osdev

我正在尝试创建一个操作系统,我不了解所有的汇编语言,我主要是在学习中。这是问题所在,我构建了一个简单的函数来比较两个字符串(eaxebx),问题是当我运行代码来执行此操作时,系统在调用后不执行任何操作。 ..我做错了什么?

compare:
    xor ecx, ecx
    .by_char:
        mov dh, [eax+ecx]
        mov dl, [ebx+ecx]
        cmp dh, dl
        inc ecx
        je .zero_test
        stc
        jmp .done
    .zero_test:
        cmp dh, 0
        je .done
        jmp .by_char
    .done:
        ret

作为参考,这里是我从以下位置调用此函数的代码:

start:
    mov esp, stack
    mov si, msg_welcome
    call print

    mov eax, msg_welcome
    mov ebx, msg_diskerr
    call compare

    jc j_aa
    jmp j_bb 

    j_aa:
        mov si, msg_strnequ
        jmp part_b

    j_bb:
        mov si, msg_strrequ

    part_b:
        call print

        mov eax, msg_booting
        mov ebx, msg_booting
        call compare

        jc j_cc
        jmp j_dd

        j_cc:
            mov si, msg_strnequ
            jmp part_c

        j_dd:
            mov si, msg_strrequ

    part_c:
        call print
        jmp halt

halt:
    hlt
    jmp halt

在这里定义变量:

bss:
    msg_welcome: db "Welcome To Hypr Byte!", 10, 13, 10, 13, 0
    msg_nokernl: db "FATAL: Missing or Corrupted Kernel. System Halted...", 10, 13, 10, 13, 0
    msg_diskerr db "FATAL: An error occured while attempting to read the disk. Please go to https://www.instinct-loop.xyz/hypr/help to recieve support...", 0
    msg_bterror db "Uh oh! An error occured while attempting to boot. Please go to https://www.instinct-loop.xyz/hypr/help to recieve support...", 0
    msg_booting db "Attempting to load the kernel...", 10, 13, 10, 13, 0
    msg_kreturn db "Oops! The kernel ran into a fatal error... System Halted!", 0

    msg_strnequ db "Strings are Not Equal!", 10, 13, 0
    msg_strrequ db "Strings are Equal!", 10, 13, 0

1 个答案:

答案 0 :(得分:2)

  

我的操作系统是16位的,但是当我尝试在我的比较函数中使用16位的寄存器时,它告诉我给了它一个无效的有效地址。

16位寻址模式只能使用[bx|bp + si|di + constant]或其子集。如果您不能像普通人一样,仅在sidi这样的addr模式下在[si][di]中传递指针,则使用32位寻址模式是一种有效的解决方法。

但仅当您将16位地址零扩展到完整的32位寄存器中时,否则高垃圾会导致违反段限制。在实模式下,段隐式具有64k的限制;偏移> 65535将会出错。

您可能实际上并没有使VirtualBox本身崩溃,但是您可能由于三重故障或某些原因而使虚拟客户机崩溃了。

mov eax, msg_welcome确实使用零扩展地址写入完整寄存器,与mov si, msg_welcome

不同

您的循环将始终在第一次迭代后退出,因为inc ecx / je .zero_test会失败。 INC清除ZF,因为将ECX从0递增到1会使ECX!= 0。

如果您想让inc读取cmp设置的标志,大概应该在je / je之前cmp

我不确定您的代码实际在哪里出错。使用调试器进行查找,例如通过在BOCHS而不是VirtualBox中运行它。 BOCHS具有内置的调试器,该调试器可以理解分段,这不同于将GDB作为GDB远程程序附加到qemu或virtualbox。


您的循环效率很低,顺便说一句。您可以使用cmp dl, [di]之类的东西,然后在底部放置一个jne。如果您使用cmp / jcc退出循环,则可以在底部将test dl,dl / jnz作为循环分支。

永远不要在jcc上写jmp,而要写一个遇到相反情况的JCC。在这里,您可以使用RET而不是jmp .done。 (一个例外是,如果您必须跳得比-128 .. + 127字节还要远,并且您要针对的是不支持JCC rel16,而仅支持短JCC rel8的古老CPU。)

在AMD CPU(无部分寄存器重命名)上,mov dh, [mem]mov dl, [mem]的依赖是错误的,因此在cmp运行之前,合并负载值会有额外的延迟。这是使用cmp-with-mem而不是2个负载的另一个原因。