0

我在 Stack Overflow 上找到了代码来获取字符串的长度。这是代码:

HELLO_MSG: db 'Hello, world!', 0
mov ebx, HELLO_MSG
call print_string

print_string:
 call str_len
 mov ecx, eax ; puts the length of the called string into ecx register
 cdq          ; clear the direction flag; not sure if this is needed
 mov ah, 0x0e ; scrolling teleype BIOS routine

 printing:
    mov al, byte bl
    int 0x10
    inc ebx
    loop printing

 ret
str_len:
 mov eax,ebx

 l00p:
    cmp byte[eax], 0
    jz lpend
    inc eax
    jmp l00p
 lpend:
    sub eax, ebx ; puts the length of the string into eax register

    ret

问题是当函数调用时str_len,它只循环 3 次,有时它会循环 2 次。当它打印时,它不会打印实际的字符串,而是一些随机字母。有谁知道为什么它不起作用?我试图在引导扇区中运行它,所以我真的没有任何调试工具。

4

1 回答 1

2

您的代码中还有更多问题:

  1. 您应该在开头跳过字符串常量

    mov ebx, HELLO_MSG
    call print_string
    jmp $
    
    HELLO_MSG: db 'Hello, world!', 0
    
    print_string:
    ...
    
  2. cdq指令不用于清算DFcdq用于将双字转换eax为符号扩展edx:eax值。你应该cld改为。但是你是对的,当你不使用任何字符串指令(cmpsbmovsb...)时,DF通常并不重要。
  3. 我还没有设置基指针和堆栈指针,因为我并没有真正在这些打印字符串中使用它们。

    是的,但是您使用call指令,它将返回地址推入堆栈。通常,BIOS 在运行引导加载程序之前为堆栈“分配”小空间,因此它不应该影响任何东西。

  4. 这条线

     mov al, byte bl
    

    将设置ALBL,这不是您想要的。您应该使用间接字节寻址和ebx.

    mov al, byte [ebx]
    int 0x10
    inc ebx
    ...
    
于 2013-09-12T14:34:12.590 回答