Search code examples
linuxassemblynasmx86-64ld

NASM call label doesn't get called


I'm doing some assembly coding using NASM on Linux but I've run into a problem.

global _start

section .text

testFunctionName:
    mov rdi, 12
    ret

_start:

    call testFunctionName

    mov rax, 1
    mov rbx, 0
    int 0x80

then assembled and linked:

nasm -felf64 -F dwarf -g program.asm -o program.o
ld program.o -o program

testFunctionName is never jumped to. I verified this using GDB. I haven't found relatable explanations elsewhere. If somebody could explain what's happening and how to fix this, I would appreciate it.


Solution

  • You're probably using nexti or next which steps over calls, not into them.

    Set a breakpoint on the mov rdi, 12 inside your function, or single-step into calls using stepi (or si for short).

    Or if you don't trust GDB, write a program whose exit status depends on whether the function runs or not.

    testFunctionName:
        mov  ebx, 12
        ret
    
    _start:
        xor   ebx, ebx   ; ebx=0
    
        call testFunctionName
    
        mov   eax, 1
        int   0x80       ; sys_exit(ebx), 32-bit ABI
    

    Run this and echo $? to see that the exit status is 12, not 0, because the function does run unless your CPU is broken, or NASM or your linker are broken.


    You could also put an illegal instruction inside your test function, like ud2. Or a software breakpoint: int3. Or a divide by zero. Something that will raise an exception instead of letting your process make its exit system call. Then you'll definitely notice whether it's called or not.


    See also What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code? To make a native 64-bit exit(0) system call the same way glibc's _exit() function does, do

        xor   edi, edi     ; rdi=0
        mov   eax, 231     ; __NR_exit_group   from <asm/unistd_64.h>
        syscall            ; sys_exit_group(edi)