Last but not least we're gonna give our app some functionality. Without modifying the layout etc... we just going to make some adjustments in native-lib.cpp and test-nasm.asm.
A major caveat is that the we are programming a shared library to use with C++. This means that strings defined in assembly language must be treated a bit more special than we should do in a (simple) assembly language program. All addresses are position independent because a shared library can be loaded anywhere (not just anywhere there are rules for it) and that we don't know where in memory it will reside. Knowing this we must inform the linker that almost everything is relocatable, thus strings too. Many words for a complex matter, an example will tell us more.
modify native-lib.cpp like the example below:
#include <jni.h> #include <string> extern "C" char* GetGreeting(void); extern "C" JNIEXPORT jstring JNICALL Java_org_agguro_testnasm_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = GetGreeting(); return env->NewStringUTF(hello.c_str()); }
It's a plain C++ program right from the Android Studio wizard. The only modification is the extern declaration of GetGreeting which takes no arguments and gets a pointer to a string from our assembly routine (linked with the native-lib.so file, and the calling of our function and pass the pointer to the string in the hello string.
we already created the file test-nasm.asm, so open it and put following code in it, don't be too scared (especially beginners can be) of the complexity, it's not just a "get the address of the string and return it in rax program, it's somewhat more complex).
; name: test-nasm.asm ; ; description: pass a pointer to "Hello from NASM" to the calling C++ program ; ; use: extern "C" char* GetMessage(void); bits 64 extern _GLOBAL_OFFSET_TABLE_ global GetGreeting global greeting:data ; define global to make relocatable section .data ; define our string here greeting: db "Hello from NASM", 0 ; for c++ strings end with zero so our length isn't necessary, you can however define ; the length as global data so we can ask the length instead of calculating it section .text GetGreeting: push rbp mov rbp,rsp push rbx call .get_GOT .get_GOT: pop rbx add rbx,_GLOBAL_OFFSET_TABLE_+$$-.get_GOT wrt ..gotpc mov rax, qword [rbx + greeting wrt ..got] mov rbx,[rbp-8] mov rsp,rbp pop rbp ret
Save it all and build your project. Once build with no errors (if not, check all again) you will have this output in your emulator.