【问题标题】:strlen in assembly装配中的strlen
【发布时间】:2011-06-29 19:32:41
【问题描述】:

我在汇编中自己实现了 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;
}

谢谢

【问题讨论】:

    标签: linux assembly x86 nasm strlen


    【解决方案1】:

    您访问的不是字节(字符),而是双字。因此,您的代码不是在寻找单个终止零,而是在寻找 4 个连续的零。请注意,并不总是返回正确的值 +4,这取决于字符串之后的内存包含的内容。

    要解决此问题,您应该使用字节访问,例如将edx 更改为dl

    【讨论】:

    • 我认为在每个循环中将 edx 设置回 0 也可以解决这个问题.. 但显然它没有.. 感谢您的回答。
    • 这不是因为mov edx, [ecx+eax] 将从内存中加载 4 个字节,覆盖edx 中的任何内容(在这种情况下为零)。
    【解决方案2】:

    感谢您的回答。在此处为与我有相同问题的任何人提供工作代码。

    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
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        换行

        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
        

        【讨论】:

          【解决方案5】:

          这里有更简单的方法(仅限 ASCII 零终止字符串):

          REPE SCAS m8

          http://pdos.csail.mit.edu/6.828/2006/readings/i386/REP.htm

          【讨论】:

            【解决方案6】:

            我认为您的公司应该在 jne 之后。我对这个程序集不熟悉,所以我真的不知道。

            【讨论】:

            • 我怀疑这不是个好主意,因为如果你这样做,你将永远不会移动到字符串中的下一个字母,因为跳转将在增加之前执行。
            • 您是否在考虑某些具有分支延迟槽的 RISC 架构,在该架构中,无论是否执行跳转,都会立即执行跳转后的第一条指令?
            猜你喜欢
            • 2013-07-05
            • 2023-03-17
            • 1970-01-01
            • 1970-01-01
            • 2014-09-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-03-25
            相关资源
            最近更新 更多