;this file -> test1.asm
includelib msvcrt.lib
includelib legacy_stdio_definitions.lib
extern _CRT_INIT: proc ;custom entrypoint needs c-runtime to be initialised by the programmer.
extern printf: proc
extern ExitProcess: proc
.data
msg db "hello world!", 13, 10, 0
.code
fun proc
sub rsp, 32 ;for shadow space
call _CRT_INIT ;called _CRT_INIT because I have my own entry point named "fun"
lea rcx,msg
call printf
add rsp, 32
call ExitProcess
fun endp
end
commandline for assembler: ml64 /nologo /c test1.asm
commandline for linker: link /entry:fun /subsystem:console test1.obj
This standalone assembly program seems to be working fine. But doing some changes(mentioned below) make the program crash.
1st change -> according to this link both libcmt.lib and msvcrt.lib statically links the native CRT startup (ie both can be used to call _CRT_INIT) into my code. The difference is msvcrt.lib is used with dll. As I don't have any dll I considered using libcmt.lib in place of msvcrt.lib but then the program crashes. Considering there is only printf function associated, that concludes printf function breaks the program. But why?
2nd change -> Now I tried calling this fun() function from a simple .C file. For that I made the necessary changes.
;this file -> test1.asm
;not including any libraries. linking the .c file make the libraries link too because that is in my libpath environment variable
;extern _CRT_INIT: proc ;no need of _CRT_INIT because now mainCRTStartup() will be the entrypoint and .c file will take care of initializing the c-runtime
extern printf: proc
;extern ExitProcess: proc ;no need of exitprocess. Instead i'm using ret instruction because I'm calling fun() from .c file.
.data
msg db "hello world!", 13, 10, 0
.code
fun proc c ;even if I replace 'c' with something like "abed" the program works. but if I dont give anything after proc then the program crashes.
sub rsp, 32 ;for shadow space
lea rcx,msg
call printf
add rsp, 32
ret
fun endp
end
//this file -> test2.c
#include <stdio.h>
#include <conio.h>
void fun(); //in C no need of extern keyword. extern is needed in c++
int main()
{
fun();
getch();
}
commandline for assembler: ml64 /nologo /c test1.asm
commandline for compiler: cl /nologo /c test2.c
commandline for linker: link test1.obj test2.obj
In the previous working example (ie. with msvcrt.lib) I don't have to give any suffixes after 'proc' directive. But in this case when I am calling 'fun' as a function from my C file I need to give anything like 'a'/'b'/combination('abcd') after 'proc' directive and only then the program works. If I don't give anything after 'proc' the program crashes. According to official MSDN documentation proc directive also accept language type. Even so wrong/random 'language type name' ie. any word seem to work. But how?
I tried many things like changing the libraries, using different version of printf (like vfprintf) and tried assigning more shadow space also googled much but unable to find any answer.
Related
I have C function and I want to use that in my MASM program.
C file:
#include <stdio.h>
int go() {
printf("Hello\n");
return 10;
}
I used this command in gcc: gcc -c go_func.c
After I've got go_func.obj
But, I can't compile/translate my MASM program, since I don't have the address of go function there. Maybe I need to create dll (static or dynamic)?
prog.asm:
.386p
.model flat, stdcall
; include c:\masm32\include\windows.inc
include c:\masm32\include\user32.inc
include c:\masm32\include\msvcrt.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\msvcrt.lib
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
extern go#0:NEAR
_data segment dword public use32 'data'
_data ends
_text segment dword public use32 'code'
START:
call go
_text ends
end START
I can't call that function, because I don't have a pointer to function?
You want a PROTO declaration for your function that tells MASM to use the C calling convention. In this case, that would be C, but not NEAR (which is an obsolete 16-bit calling convention from the ’80s).
I tried to write a char[] in stdout using inline NASM (note .intel_syntax and .att_syntax are added so it can be compiled with gcc)
but it doesn't write anything in stdout.
I am using Linux 16 (x86) on Virtual machine
Is it cause of char c[] ? ( I read by this way of compiling we cannot use memory variables but what to do instead?)
#include<stdio.h>
char c[] = "abcd";
int main(){
asm (".intel_syntax noprefix");
// write c into stdout
asm("mov EAX,4"); // 4: write
asm("mov EBX,1"); // 1: stdout
asm("mov ECX,c");
asm("mov EDX,5");
asm("int 0x80");
// exit program
asm("mov EAX,1")
asm("int 0x80")
asm (".att_syntax noprefix");
}
the output is nothing
The GNU assembler (which is what gcc uses) does not use NASM syntax. It rather uses a variant of Microsoft's MASM syntax where no brackets are needed to dereference a variable. Since you don't want to load the value of the c variable but rather its address, you need an offset keyword:
mov ecx, offset c
I strongly recommend you to avoid inline assembly as much as possible for learning assembly. Using inline assembly in gcc requires good knowledge of how exactly this whole thing works and writing random instructions usually leads to wrong code. Even your simple code is already fundamentally broken and would not work if it was any more complicated than that (so the compiler had a chance to try to use the registers you overwrote without telling).
Instead, put your assembly in a separate file and link it in. This sidesteps all issues you have with inline assembly and allows you to use NASM as you wanted. For example, try something like this:
main.c
char c[] = "abcd";
/* the function you define in print_c.asm */
extern void print_c();
int main() {
print_c(); /* call your assembly function */
}
print_c.asm
; pull in c defined in main.c
extern c
section .text
global print_c
print_c:
; write c to stdout
mov eax, 4
mov ebx, 1
mov ecx, c
mov edx, 5
int 0x80
; exit program
mov eax, 1
int 0x80
Then assemble, compile, and link with:
nasm -felf print_c.asm
cc -m32 -o print_c print_c.o main.c
Linking C with Assembly in Visual Studio
I've seen that already but that doesn't contain any helpful informations.
I have a C program, in which I'm using function written in assembly.
I include fun.h header in C file with declaration, and have fun.asm with implementation.
It was firstly written using NASM, and there is a global keyword. How can I achieve the same proper linking effect in MASM?
Minimal example:
main.c:
int main()
{
f();
return 0;
}
f.h:
void f();
f.asm:
.DATA
_05 DQ 0.5
_PI DQ 3.14159265358979323846264338327
.CODE
public _f
_f PROC
_f ENDP
END
According to what Michael Petch wrote in comment:
Searched keyword is PUBLIC, and in x86_64 there is NO need for underscore on PROC functions.
I'm trying to call C function in assembler. This is my code:
C:
int multiply(int what)
{
return what * 2;
}
ASM:
extern multiply
start:
mov eax, 10
push eax
call multiply
jmp $
;empty
times 510-($-$$) db 0
dw 0xAA55
I'm compiling C code to elf by gcc (MinGW) and ASM code by NASM. I'm compiling it without any problems, but when I'm trying to use this code(for creating .bin file):
gcc -o test.bin work.o test.o
I' getting this error:
Does anybody know how to call C function from ASM code, compile it and link it to working .bin file? Please help.
Try to add '_' to multiply:
extern _multiply
Works for me in this simple example:
global _main
extern _printf
section .data
text db "291 is the best!", 10, 0
strformat db "%s", 0
section .code
_main
push dword text
push dword strformat
call _printf
add esp, 8
ret
Try "global multiply" instead of "extern multiply" in your .asm file. You shouldn't need the underscore for ELF (I don't think), but you can get Nasm to automagically add an underscore to anything "extern" or "global" by adding "--prefix _" to Nasm's command line.
Edit: I take that back, "extern" is correct. You seem not to have a "main". Try adding "--nostartfiles"
(may be only one hyphen) to gcc's command line.
Best,
Frank
Each program has a main() and the program execution starts from there. Is it possible to write a program without main()and make another function as the entry point? If so, can any one please tell me how can that be done? I am using Linux?
If you're compiling with gcc, specifying -e <symbol> option will let you change the entry point to a function symbol().
You can do this in a portable way, simply by including this header file in your main program:
int nomDePlume(int argc, char *argv[]);
int main(int argc, char *argv[]) { return nomDePlume(argc, argv); }
Then provide your own variant of main:
int nomDePlume(int argc, char *argv[]) {
weaveYourMagic();
return 42;
}
That doesn't actually change the entry point of the executable (something that's very much implementation specific) but it does let you call your program entry point whatever you wish (within the bounds of legal identifiers, of course).
If you don't want a main at all (even in a header file), it becomes a little tricky.
That's because the entry pount for an executable generally isn't main - there's quite a bit of activity happening before main is called, to do with environment setup and other things (and some tear-down stuff after main exits, such as your atexit handlers).
In other words, while the main function may be where your C program starts, that's not the same thing as where your executable starts.
As one example, in Linux, the ELF executable format contains an entry point address in the e_entry field of a header block, and that's where the program loader jumps to when it's ready to run the executable.
What usually happens to set this up is that you link (implicitly) with some start-up code like crt0 and the linker populates the e_entry field with the address of a known symbol. An example of which is (from that link, with comments slightly modified):
.text
.globl _start
_start: # Entry point known to linker.
xor %ebp, %ebp # RBP <- 0, mark end of stack frames.
mov (%rsp), %edi # Get argc from stack (implicitly
# zero-extended to 64-bit).
lea 8(%rsp), %rsi # Take address of argv from stack.
lea 16(%rsp,%rdi,8), %rdx # Take address of envp from stack.
xor %eax, %eax # Per ABI and compatibility with icc.
call main # Three args %edi/%rsi/%rdx (first
# two are C standard).
mov %eax, %edi # Effectively set up _exit(main()).
xor %eax, %eax # Per ABI and compatibility with icc.
call _exit # Terminate the program.
You can see there the start-up and tear-down stuff happening on either side of the main call, and therein lies a possible solution for you.
By creating your own crt0, replacing the text main with whatever you want to call, and ensuring the linker uses your crt0 rather than the default one, you can have it call whatever function you want to provide as the main one.
However, it's not really clear what you gain from being able to use an arbitrarily-named main function, other than to obtain job security or annoy your colleague when they can't find where your code begins :-)
If it's an educational thing, that's fine - I just wouldn't do this in a real-world situation.
There is a solution for build executable shared library that you can build a program use another function as entry point.
The code looks like:
#include <stdio.h>
#include <stdlib.h>
const char __invoke_dynamic_linker[] __attribute__ ((section (".interp")))
= "/lib/ld-linux.so.2";
void fun()
{
printf("This is fun./n");
exit(0);
}
Then build your program as an shared library and specify func as entry point:
$ gcc -fpic -shared -o fun.so -Wl,-e,fun fun.c
$ ./fun.so
The problem of this way is that the func can't have the normal arguments as we have in main function, this is because we don't have the c library to initialize the main arguments stuff.