我在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次。当它打印时,它不会打印实际的字符串,而是一些随机字母。有谁知道为什么它不起作用?我正试图在引导扇区中运行它,所以我没有任何调试工具。
答案 0 :(得分: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在运行bootloader之前为堆栈“分配”小空间,因此它不会影响任何内容。
这一行
mov al, byte bl
会将AL
设置为等于BL
,这不是您想要的。您应该使用ebx
的间接字节寻址。
mov al, byte [ebx]
int 0x10
inc ebx
...