I am trying to make a simple assembly program that prints "Hello!" once, waits one second, then prints it again. Since sleep functions are relatively complex in assembly, and I'm not that good at it, I decided using C++ would be the way to go to make the Sleep subroutine. Here's the C++ program:
// Sleep.cpp
#include <thread>
#include <chrono>
void Sleep(int TimeMs) {
std::this_thread::sleep_for(std::chrono::milliseconds(TimeMs));
}
I then compiled this sleep function into an assembly program using "gcc -S Sleep.cpp" then compiled it into an object file using "gcc -c Sleep.s"
I am trying to call this C++ subroutine from assembly. I heard that you provide parameters to C++ subroutines by pushing them onto the stack, here's my assembly code so far:
global _main
extern _puts
extern Sleep
section .text
_main:
push rbp
mov rbp, rsp
sub rsp, 32
;Prompt user:
lea rdi, [rel prompt] ; First argument is address of message
call _puts ; puts(message)
push 1000 ; Wait 1 second (Sleep time is in milliseconds)
call Sleep
lea rdi, [rel prompt] ; Print hello again
call _puts
xor rax, rax ; Return 0
leave
ret
section .data
prompt:
db "Hello!", 0
Both these files are saved to Desktop/Program. I'm trying to compile it using NASM and GCC, my compiler invocation is:
nasm -f macho64 Program.asm && gcc Program.o Sleep.s -o Program && ./Program
But I get the error:
"Sleep", referenced from:
_main in Program.o
(maybe you meant: __Z5Sleepi)
"std::__1::this_thread::sleep_for(std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > const&)", referenced from:
void std::__1::this_thread::sleep_for<long long, std::__1::ratio<1l, 1000l> >(std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l> > const&) in Sleep-7749e0.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Changing the code to "extern __Z5Sleepi" and calling "__Z5Sleepi" instead of Sleep doesn't seem to fix the problem. (I get the same error message just without the "Maybe you meant __Z5Sleepi" bit. I also tried using _Sleep instead of Sleep without success.) What am I doing wrong? How do I properly use and link this C++ subroutine with my assembly program? Is the method I am using so far to do this just wrong from the ground up?
Any help is much appreciated, browsing stack overflow, there seem to be a lot of questions regarding this but none of them actually go into the linking process. (And they seem to be asking about linking assembly with C++, not C++ with assembly.) I am using NASM and GCC to compile, and my platform is Mac OSX.