NASM (64-bit linux): my 'puts' procedure doesn't work with my 'strlen' procedure

1

As a preface, I'm running this on a 64-bit Linux OS and am thus using the 64-bit Linux syscalls.

My strlen procedure takes rdi as a parameter and returns the length of the string excluding \0 in rax. (You have to enter a string that ends with \0). I have tested this procedure and know it works correctly.

My puts procedure takes rdi as its parameter, uses strlen to get the length and then uses the write syscall.

Here is a (hopefully) minimal reproducible example:

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

I'm really confused as to why this isn't working. My puts procedure is just a simple syscall really, so I honestly don't know what is going wrong here.

assembly
linux-kernel
x86-64
nasm
asked on Stack Overflow Feb 6, 2021 by mediocrevegetable1 • edited Feb 6, 2021 by mediocrevegetable1

1 Answer

3

I have tested [my strlen] and know it works correctly.

I'm afraid not.

mov rcx, 0xffffffff

You seem to be thinking this loads rcx with -1, but it doesn't: 0xffffffff is -1 as a 32-bit signed integer, but rcx is a 64-bit register. (Maybe you copied from some 32-bit code?) In particular, mov rcx, 0xffffffff followed by not rcx does not result in rcx containing 0, but rather 0xffffffff00000000. As a result your strlen returns a seriously incorrect value.

Change this to mov rcx, -1 or mov rcx, 0xffffffffffffffff.

answered on Stack Overflow Feb 6, 2021 by Nate Eldredge

User contributions licensed under CC BY-SA 3.0