首页 > 解决方案 > NASM(64 位 linux):我的“puts”程序不适用于我的“strlen”程序

问题描述

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

我的strlen过程将rdi作为参数并返回字符串的excluding \0长度rax。(您必须输入一个以 \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程序实际上只是一个简单的系统调用,所以老实说,我不知道这里出了什么问题。

标签: assemblylinux-kernelx86-64nasm

解决方案


我已经测试了 [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


推荐阅读