strchr()函数实现问题

时间:2018-03-18 10:39:19

标签: unix assembly x86-64

我最近开始研究汇编代码,我正在尝试重新编码一些基本的系统函数来控制它,我目前在我strchr上的0x0处遇到了分段错误。< / p>

section .text
global strchr

strchr:
    xor rax, rax

loop:
    cmp BYTE [rdi + rax], 0
    jz end

    cmp sil, 0
    jz end

    cmp BYTE [rdi + rax], sil
    jz good

    inc rax
    jmp loop

good:
    mov rax, [rdi + rcx]
    ret

end:
    mov rax, 0
    ret

我无法弄清楚如何使用GDB调试它,我遇到的文档非常有限或难以理解。

我在C中使用以下主要测试

extern char *strchr(const char *s, int c);

int main () {
   const char str[] = "random.string";
   const char ch = '.';
   char *ret;

   ret = strchr(str, ch);
   printf("%s\n", ret);
   printf("String after |%c| is - |%s|\n", ch, ret);

   return(0);
}

1 个答案:

答案 0 :(得分:5)

问题

紧跟good标签后的说明:

mov rax, [rdi + rcx]

实际应该是:

lea rax, [rdi + rax]

您根本没有使用rcx,但是rax,您需要的是该位置的地址,而不是该位置的值(即lea而不是mov)。

一些建议

  1. 请注意,典型的idiom for comparing sil against zero实际上是test sil, sil而不是cmp sil, 0。那就是:

    test sil, sil
    jz end
    

    但是,如果我们查看strchr(3) man page,我们可以找到以下内容:

      

    char *strchr(const char *s, int c);

         

    终止      null字节被认为是字符串的一部分,因此如果将c指定为&#39; \0',这些函数将返回指向终结符的指针。

    因此,如果我们希望此strchr()实现的行为与手册页中所述相同,则必须删除以下代码:

    cmp sil, 0
    jz end 
    
  2. rax注册表的典型zeroing idiom既不是mov rax, 0也不是xor rax, rax,而是xor eax, eax,因为它不是section .text global strchr strchr: xor eax, eax loop: ; Is end of string? cmp BYTE [rdi + rax], 0 jz end ; Is matched? cmp BYTE [rdi + rax], sil jz good inc rax jmp loop good: lea rax, [rdi + rax] ret end: xor eax, eax ret 编码为立即零,并为后者保存一个字节。

  3. 通过上述更正和建议,代码如下所示:

    select json_query ('{"name":"' + lookupvalue + '"}') as 'disk'
    from tblDataInfo 
    where lookupkey = 'diskname'
    for json path;