What is the proper NASM equivalent of the following two functions?
get_user_input:  ; (char*, unsigned long)
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     qword [rbp-8], rdi
        mov     qword [rbp-16], rsi
        mov     rdx, qword stdin[rip]  ; previously: mov   rdx, QWORD PTR stdin[rip]
        mov     rax, qword [rbp-16]
        mov     ecx, eax
        mov     rax, qword [rbp-8]
        mov     esi, ecx
        mov     rdi, rax
        call    fgets
        nop
        leave
        ret
print_string:  ; (char const*)
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     qword [rbp-8], rdi
        mov     rdx, qword stdout[rip]  ; previously: mov   rdx, QWORD PTR stdout[rip]
        mov     rax, qword [rbp-8]
        mov     rsi, rdx
        mov     rdi, rax
        call    fputs
        nop
        leave
        ret
The above snippet was originally in GAS syntax and I manually converted it to NASM. It was generated using GCC (-O0) from the following C++ code:
void
get_user_input( char* const buffer, const std::size_t buffer_size ) noexcept
{
    std::fgets( buffer, static_cast<int>( buffer_size ), stdin );
}
void
print_string( const char* const str ) noexcept
{
    std::fputs( str, stdout );
}
But my conversion was not without errors. Apparently, the external symbols must be declared at the top of the file:
extern fgets
extern fputs
extern stdin
extern stdout
This solves some issues. But NASM says there are still issues in these two lines:
        mov     rdx, qword stdin[rip]
and
        mov     rdx, qword stdout[rip]
The error message:
nasm -g -F dwarf -f elf64 Main.asm -l Main.lst -o Main.o
Main.asm:96: error: symbol `rip' not defined
Main.asm:111: error: symbol `rip' not defined
How do we tell NASM to move the address of stdout or stdin to the rdx register similar to the above GAS assembly code?
