Assembly 找不到字符串的长度

Assembly 找不到字符串的长度,assembly,x86,nasm,bios,Assembly,X86,Nasm,Bios,我在这里找到了在堆栈溢出上获取字符串长度的代码。代码如下: 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

我在这里找到了在堆栈溢出上获取字符串长度的代码。代码如下:

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次。当它打印时,它不会打印实际的字符串,而是一些随机字母。有人知道它为什么不起作用吗?我试图在引导扇区中运行它,因此我没有任何调试工具。

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

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

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

    是的,但您使用
    call
    指令,它将返回地址推送到堆栈上。通常,BIOS在运行引导加载程序之前为堆栈“分配”小空间,所以它不会影响任何事情

  • 这条线

     mov al, byte bl
    
    AL
    设置为
    BL
    ,这不是您想要的。您应该将间接字节寻址与ebx一起使用

    mov al, byte [ebx]
    int 0x10
    inc ebx
    ...
    

  • 您的程序偏移设置正确吗?我已声明代码从
    [org 0x7c00]
    开始,这是我设置的唯一其他内容。我还没有设置基指针和堆栈指针,因为我没有在这些打印字符串中真正使用它们。这会影响它吗?这是完整的源代码吗?怎么说执行将从第一条
    mov
    指令开始,而不是在
    HELLO\u MSG
    字符串中开始(即执行垃圾)?此外,用于清除方向标志的指令是
    cld
    ,而不是
    cdq
    cdq
    用于在除法之前将
    eax
    标志扩展到
    edx
    )。是的,我在实际代码中这样做,但这里只是打印的一个片段。2.我不知道我是怎么想到干熄焦的。。。很抱歉。3.我完全没有想到这一点。谢谢你让我知道。4.这个修好了!我感谢你的帮助!非常感谢。