汇编中的strlen函数

6

我自己用汇编语言实现了strlen函数,但是它返回的值不正确。它返回字符串长度+4。因此,我不知道为什么会这样,希望有人能够帮忙解决。

汇编源码:

section .text
    [GLOBAL stringlen:] ; C function

stringlen:  
    push ebp
    mov ebp, esp        ; setup the stack frame

    mov ecx, [ebp+8]

    xor eax, eax        ; loop counter


startLoop:
    xor edx, edx
    mov edx, [ecx+eax]
    inc eax

    cmp edx, 0x0 ; null byte    
    jne startLoop
end:    
    pop ebp

    ret

主程序如下:

#include <stdio.h>

extern int stringlen(char *);

int main(void)
{
  printf("%d", stringlen("h"));

  return 0;
}

Thanks

6个回答

6
你正在访问双字节而不是单个字符。因此,你的代码不是在寻找单个终止零,而是在寻找4个连续的零。请注意,这不总是会返回正确的值+4,它取决于字符串后面的内存内容。
要修复这个问题,你应该使用字节访问,例如将edx改为dl

我以为在每个循环中将edx设置为0也可以解决这个问题,但显然并不行。感谢您的回答。 - Michel
它不会,因为 mov edx, [ecx+eax] 会从内存中加载4个字节,覆盖掉 edx 中的任何内容(在这种情况下是零)。 - Jester

5
感谢您的回答。以下是适用于与我有相同问题的任何人的工作代码。
section .text
    [GLOBAL stringlen:]

stringlen:  
    push ebp
    mov ebp, esp

    mov edx, [ebp+8]    ; the string
    xor eax, eax        ; loop counter

    jmp if

then:
    inc eax

if:
    mov cl, [edx+eax]
    cmp cl, 0x0
    jne then

end:
    pop ebp
    ret

1

更改这行

mov edx, [ecx+eax]

mov dl, byte [ecx+eax]

  cmp edx, 0x0 ; null byte

  cmp dl, 0x0 ; null byte

因为你只能一次比较一个字节。以下是代码。你原来的代码有一个偏移错误。对于"h",它将返回两个h + null字符。

section .text
    [GLOBAL stringlen:] ; C function

stringlen:
    push ebp
    mov ebp, esp        ; setup the stack frame

    mov ecx, [ebp+8]

    xor eax, eax        ; loop counter


startLoop:
    xor dx, dx
    mov dl, byte [ecx+eax]
    inc eax

    cmp dl, 0x0 ; null byte
    jne startLoop
end:
    pop ebp

    ret

1

对于这四个不确定,但显然它总是返回正确的长度+1,因为eax总是增加的,即使从字符串中读取的第一个字节为零。


0

-2

我认为你的inc应该在jne之后。我对这个汇编不太熟悉,所以不是很确定。


我认为那不是一个好主意,因为如果你这样做,你永远无法移动到字符串的下一个字母,因为跳转会在增加之前执行。 - Tony The Lion
你是否在考虑某些具有分支延迟槽的RISC架构,其中跳转后紧随其后的第一条指令将被执行,无论跳转是否被执行? - Chris Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接