如何在NASM x86_64 Linux汇编中比较字符串中的一个字符与另一个字符

3

我正在尝试理解Intel x64语法下NASM汇编的基本概念,但在尝试创建strchr等效函数时遇到了问题...

我已经在网上搜索了尽可能多的信息,但我不知道如何将字符串的当前字符(例如str[i])与一个简单的字符进行比较。

这是测试主函数:

#include <stdio.h>

extern char* my_strchr(char*, char);

int     main(void)
{
  char* str;

  str = my_strchr("foobar", 'b');
  printf("%s\n", str);
  return 0;
}

以下是我的汇编代码:

我假设 rdi 是我的字符串,rsi 是一个字节的数据。

my_strchr:
    push    rcx                  ;Save our counter
    xor     rcx, rcx             ;Set it to 0
loop:
    cmp     rdi, byte 0          ;Check the end of string
    jz      end
    cmp     rsi, [byte rdi+rcx]  ;Here is the point ...
    jz      end
    inc     rcx                  ;increment our counter
    jmp     loop
end:
    mov     rax, [rdi+rcx]       ;Are the brackets needed ? Is it equivalent to '&' in C ? 
    pop     rcx
    ret

以下是针对用 C 语言编写的 strchr 函数的 Gdb 输出和反汇编结果:

....
cmp    al,BYTE PTR [rbp-0x1c]
....

但是我的实际情况是这样的:
0x400550 <my_strchr>            push   rcx
0x400551 <my_strchr+1>          xor    rcx,rcx
0x400554 <loop>                 cmp    rdi,0x0
0x400558 <loop+4>               je     0x400566 <end>
0x40055a <loop+6>               cmp    rsi,QWORD PTR [rdi+rcx*1+0x0]

提前感谢您,希望有人能知道。

1个回答

3

rdi是一个指针,因此cmp rdi, 0检查空指针。你想要的是cmp byte [rdi + rcx], 0来检查字符串的结尾。注意你需要检查当前字符,所以必须添加索引。

至于cmp rsi, [byte rdi+rcx]中的byte没有意义,因为你正在比较整个rsi,它有8个字节。应该是cmp sil, [rdi + rcx]

最后,strchr应该返回一个指针,所以你应该把mov rax, [rdi+rcx]改为lea rax, [rdi + rcx]


谢谢!在您的解释之后,一切都变得清晰明了了。我刚刚发现了"lea"指令和sil(运算符?),以后应该如何正确使用它们? - Cegree
你可以寻找手册了解名称,以便访问寄存器的较小部分。每当需要更小的单位时,您都可以使用它们。lea 对于寻址或一些简单的算术运算非常有用。您也可以使用 mov rax, rdi; add rax, rcx 来实现相同的效果。 - Jester

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