Search code examples
assemblyx86nasmcalling-conventionfputs

Why do we have to dereference stdout here?


I am trying to call fputs(str, stdout); from assembly.

Why should I push dword [stdout] instead of just push stdout?

Since in C we don't do fputs(str, *stdout), why do we need to dereference stdout in assembly?

Full code:

extern fputs
extern stdout

section .data
    hw: db "Hello World!", 10, 0

section .text
    global main

main:
    enter 0,0

    push dword [stdout]
    ;push stdout
    push hw
    call fputs

    leave
    mov eax, 0
    ret

Solution

  • You're dereferencing the asm label stdout, which is equivalent to &stdout in C. It's the static location in memory where the FILE* value is stored.

    Only C array types behave like asm labels, where the name in C is the address, not the contents.

    See also Why in NASM do we have to use square brackets ([ ]) to MOV to memory location?


    In NASM, a bare symbol name is the static address. In C, a bare name is the value.

    (Except for true C arrays, where the bare name is the address of the first element.)


    In C, variables with automatic storage class (i.e. local vars) can also have names, not just static. In asm, symbols can only go on static addresses. (Automatic storage in C is normally a register in x86 asm, or stack space like [ebp - 8] if you need to spill/reload. Stack addresses aren't link-time constants, so can't have labels. You address the stack relative to ESP or EBP.)

    Objects with dynamic storage can't have names in C, only be pointed to by named pointers.