hi all
char * msg = "Hello, World!\n";
char * wMsg = "Content of the window..";
char * wCaption = "Window title";
int main (){
std::cout << "before call" << "\n";
asm(
"movl _msg,%eax\n\t"
"pushl %eax\n\t"
"calll _printf\n\t"
"popl %eax\n\t"
"movl $0, %eax\n\t"
"movl _wCaption, %ebx\n\t"
"movl _wMsg, %ecx\n\t"
"movl $0, %edx\n\t"
"pushl %eax\n\t"
"pushl %ebx\n\t"
"pushl %ecx\n\t"
"pushl %edx\n\t"
"calll MessageBoxA\n\t"
"popl %edx\n\t"
"popl %ecx\n\t"
"popl %ebx\n\t"
"popl %eax\n\t"
);
std::cout << "after call" << "\n";
}
when i want to compile, i get:
undefined reference to `MessageBoxA'
can someone please tell me what's wrong?
This is the test code I use(I'm using 64bit GCC compiler)
#include <iostream>
using namespace std;
char * msg = "Hello, World!\n";
char * wMsg = "Content of the window..";
char * wCaption = "Window title";
int main (){
std::cout << "before call" << "\n";
int src = 1;
int dst;
asm ("mov %1, %0\n\t"
"add $1, %0"
: "=r" (dst)
: "r" (src));
printf("%d\n", dst);
asm(
"movq $0, %%rax\n\t"
"movq $0, %%rax\n\t"
"add $48, %%rax\n\t"
"movq $0, %%rbx\n\t"
"movq $0, %%rcx\n\t"
"movq $0, %%rdx\n\t"
"push %%rax\n\t"
"push %%rbx\n\t"
"push %%rcx\n\t"
"push %%rdx\n\t"
"call MessageBoxA\n\t"
:
: "r" (msg), "r" (wMsg) , "r" (wCaption)
: "cc");
std::cout << "after call" << "\n";
}
The MessageBoxA function can be called.
But I have no idea how to pass the string to this function.
See those links as reference:
http://asm.sourceforge.net/articles/rmiyagi-inline-asm.txt
https://stackoverflow.com/questions/66323292/messagebox-program-in-x86-assembly
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels
https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
BTW: you need an export on assembly language for help. Our forum is not the right forum to ask.
EDIT:
To reference the input variables, you need like string in the assembly code.
OK, I just notice that the call convension is different in 64bit and 32bit Windows.
So, here is the modified code for 64bit Windows
#include <iostream>
using namespace std;
char * msg = "Hello, World!\n";
char * wMsg = "Content of the window..";
char * wCaption = "Window title";
int main (){
std::cout << "before call" << "\n";
asm(
"movq $0, %%rcx\n\t"
"movq %2, %%rdx\n\t"
"movq %1, %%r8\n\t"
"movq $0, %%r9\n\t"
"callq MessageBoxA\n\t"
:
: "r" (msg), "r" (wMsg) , "r" (wCaption)
: "cc");
std::cout << "after call" << "\n";
}
The important change is: for 64bit function call, the first 4 arguments are not pushed in the stack, but put in the registers, see some references:
https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention
https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
https://stackoverflow.com/questions/42488273/call-a-function-with-inline-asm