【问题标题】:Trying to implement strlen in x86 GAS尝试在 x86 GAS 中实现 strlen
【发布时间】:2018-10-07 19:40:39
【问题描述】:

所以我对汇编编程非常陌生(非常新),并且正在尝试编写一个可以计算字符串长度的函数。

我觉得我在清除寄存器中的值或指针的增量方面遇到了一些问题,因为返回的值对我来说始终是“4571 + 长度”。

基本上,如果字符串长度为 0,我会得到 4571 作为返回值。 如果我的字符串长度为 6,我会得到 4577 作为返回值,等等。

这是我的代码,任何帮助将不胜感激:

.globl my_strlen
    my_strlen:
        pushq %rbp
        movq %rsp, %rbp
        pushq %r12
        pushq %r13

        movq $0, %rax
        cmp $0, (%rdi)
        jne my_strlen_loop
        ret

    my_strlen_loop:
        inc %rax
        inc %rdi
        cmp $0, (%rdi)
        jne my_strlen_loop

        popq %r13
        popq %r12
        popq %rbp
        ret

【问题讨论】:

  • 在“ret”之前添加这个:“sub $4571, %rax”
  • 不过,这更像是一个临时修复。为什么 4571 首先要进入 rax?
  • 是的,这是个玩笑。 :-) 我正在写一个真实的答案。
  • 您不需要对 RAX 和 RDI 以外的寄存器做任何事情。只留下 R12 和 R13。还有 RBP,您不需要传统的堆栈框架。
  • 这只是作为骨架代码的一部分提供给我们的。我知道我不需要这三个寄存器,但我就这样离开了

标签: x86 x86-64 gnu-assembler


【解决方案1】:

这段代码有两个问题。

首先,cmp 指令没有指定大小,而且两个操作数都不是寄存器,所以它是模棱两可的。对于大多数指令(如mov $0, (%rdi)),GAS 会拒绝汇编它,但由于某种原因,cmp 会汇编为cmpl,比较一个双字。将助记词显式更改为cmpb

其次,在第一次 ret 之前,它不会弹出被压入的寄存器。最好跳到最后(并有一个 ret)。

【讨论】:

  • 它返回 4571 的原因仅仅是因为这是程序数据中第一个找到 4 个连续 0 字节的位置,因此 cmp 匹配。
  • 它没有拒绝组装它。将“cmp”更改为“cmpb”就可以了!非常感谢,我添加了一个标签来做弹出和返回。再次感谢您。
  • @Suhas 和 prl:我的错误,我以为我知道 GAS 会在那里做什么,但出于某种原因,cmpmov $0, (%rdi) 不同,并且确实组装到 dword cmp。我会认为这是一个错误,因此 not 错误,并在没有警告的情况下静默组装。
  • 我同意,这似乎是气体中的一个错误。
猜你喜欢
  • 2018-09-25
  • 2014-08-05
  • 1970-01-01
  • 2012-08-01
  • 2010-12-16
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多