【问题标题】:NASM (64-bit linux): my 'puts' procedure doesn't work with my 'strlen' procedureNASM(64 位 linux):我的“puts”程序不适用于我的“strlen”程序
【发布时间】:2021-05-10 17:22:34
【问题描述】:

作为前言,我在 64 位 Linux 操作系统上运行它,因此我使用的是 64 位 Linux 系统调用。

我的strlen 过程以rdi 为参数,并返回rax 中字符串excluding \0 的长度。 (您必须输入一个以 \0 结尾的字符串)。我已经测试过这个程序并且知道它可以正常工作。

我的puts 过程将rdi 作为其参数,使用strlen 获取长度,然后使用write 系统调用。

这是一个(希望是)最小的可重现示例:

section .data
    msg db "HELLO", 10, 0

section .text
    global _start
_start:
    mov  rdi, msg
    call puts
    mov  rax, 0x3c
    xor  rdi, rdi
    syscall

strlen:
    push rdi
    push rcx
    push rsi

    xor rax, rax
    mov rcx, 0xffffffff
    repnz scasb
    jnz .error
    not rcx
    dec rcx
    mov rax, rcx
.return:
    pop rsi
    pop rcx
    pop rdi
    ret
.error:
    mov rax, -1
    jmp .return

puts:
    mov rsi, rdi
    call strlen
    mov rdx, rax
    mov rax, 1
    mov rdi, rax
    syscall
    ret

我真的很困惑为什么这不起作用。我的puts 过程实际上只是一个简单的系统调用,所以我真的不知道这里出了什么问题。

【问题讨论】:

  • 请提供一个minimal reproducible example,其中包含您的完整代码,而不仅仅是一些功能。
  • @fuz 我编辑了我的帖子以包含一个(希望)最小的可重现示例。
  • 你不要打电话给你的puts
  • 抱歉,小错字。但是当我调用它时仍然不起作用。
  • 另外,您的 puts 依赖于 strlen 保留 RSI 的值。 RSI 未在 System V AMD64 ABI 中保存被调用者,因此您可能应该对其进行保护,以便以后使其更加兼容。

标签: assembly linux-kernel x86-64 nasm


【解决方案1】:

我已经测试过 [my strlen] 并且知道它可以正常工作。

恐怕不行。

mov rcx, 0xffffffff

您似乎认为这会将 rcx-1 一起加载,但事实并非如此:0xffffffff-1 作为 32 位有符号整数,但 rcx 是 64 位寄存器。 (也许您是从某些 32 位代码中复制的?)特别是,mov rcx, 0xffffffff 后跟 not rcx 不会导致 rcx 包含 0,而是 0xffffffff00000000。因此,您的 strlen 返回一个严重错误的值。

将此更改为mov rcx, -1mov rcx, 0xffffffffffffffff

【讨论】:

  • 啊,是的,这行得通。我不敢相信我的整个事情都因为这样一个愚蠢的错误而不起作用。奇怪的是,当我自己打印strlen 的输出时,它显示了正确的数字。不管怎样,你的回答解决了我的问题。
  • 您是打印了结果的全部 64 位,还是只打印了低 32 位?低 32 位将包含正确的值(对于大小小于 4 GB 的字符串)。
  • 哦,是的,我将结果存储在一个字节大的变量中,因为我认为我不需要测试一个大字符串,所以你是对的。
  • @mediocrevegetable1:是的,你去。顺便说一句,这很容易通过单步执行gdb 找到,所以如果你还没有练习过,这对你来说是件好事。 strace 也有帮助,因为它显示了一个荒谬的长度被传递给 write 系统调用。
  • @mediocrevegetable1:我想说,现在是时候了。这是一项重要的投资,对于汇编编程几乎是强制性的。举个例子,你花了一个多小时等待这个问题的答案,更不用说你花在编写它上的时间了,而使用调试器,你会在三分钟内找到错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
  • 2014-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多