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?