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.
Related
;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.
I have declared a function tolower in assembly language and I am calling it from my C code which includes standard library. I wonder why this works properly without giving any error as now two functions with same name are present.
My C code:
#include <stdio.h>
#include <string.h>
int main() {
char in0[] = "something";
char in1[] = "SomethinG";
char in2[] = "S0mething";
int i = 0;
while (in0[i]) {
in0[i] = tolower(in0[i]);
in1[i] = tolower(in1[i]);
in2[i] = tolower(in2[i]);
i++;
}
return 0;
}
I can't put my assembly code as it comes under an assignment. I have globally declared tolower function.
.section .data
.section .text
.globl _start
.globl tolower
.type tolower, #function
tolower:
I have compiled using gcc cfile.c assfile.s
Are you sure you are calling the assembler version from the C code, and not the standard library version? How is the assembler code defined? Is it a module (.asm) in your C project, in-lined, a static .DLL library, or .DEF/OBJ import? What compiler, assembler, (and IDE, OS?) are you using? There is not enough information currently to yield a concrete answer, however if there is nothing "defining" the assembler function to C, in a way that C can understand, then it will be oblivious to any naming conflicts. This isn't technically an error either; identical function names are like having two identical house addresses (123_Anystreet) in Canada and Europe. Entirely possible and allowable, but C typically doesn't allow it (and assembler does.)
I wonder if the number that follows a local static variable name in assembler is random or if there is a meaning.
I compiled a sample C source with gcc v. 4.7.2 in Debian wheezy; the assembler listing shows a row containing:
.comm i.1705,4,4
Where does 1705 come from?
Thank you in advance.
Here is the source:
int main() { static int i=0; return i; }
It is probably some counter of all identifiers encountered during the compilation. If I put another declaration just behind, it gives me the next number. If I put another, non-static, object in between the difference is 2.
Is there a C library for assembling a x86/x64 assembly string to opcodes?
Example code:
/* size_t assemble(char *string, int asm_flavor, char *out, size_t max_size); */
unsigned char bytes[32];
size_t size = assemble("xor eax, eax\n"
"inc eax\n"
"ret",
asm_x64, &bytes, 32);
for(int i = 0; i < size; i++) {
printf("%02x ", bytes[i]);
}
/* Output: 31 C0 40 C3 */
I have looked at asmpure, however it needs modifications to run on non-windows machines.
I actually both need an assembler and a disassembler, is there a library which provides both?
There is a library that is seemingly a ghost; its existance is widely unknown:
XED (X86 Encoder Decoder)
Intel wrote it: https://software.intel.com/sites/landingpage/pintool/docs/71313/Xed/html/
It can be downloaded with Pin: https://software.intel.com/en-us/articles/pintool-downloads
Sure - you can use llvm. Strictly speaking, it's C++, but there are C interfaces. It will handle both the assembling and disassembling you're trying to do, too.
Here you go:
http://www.gnu.org/software/lightning/manual/lightning.html
Gnu Lightning is a C library which is designed to do exactly what you want. It uses a portable assembly language though, rather than x86 specific one. The portable assembly is compiled in run time to a machine specific one in a very straightforward manner.
As an added bonus, it is much smaller and simpler to start using than LLVM (which is rather big and cumbersome).
You might want libyasm (the backend YASM uses). You can use the frontends as examples (most particularly, YASM's driver).
I'm using fasm.dll: http://board.flatassembler.net/topic.php?t=6239
Don't forget to write "use32" at the beginning of code if it's not in PE format.
Keystone seems like a great choice now, however it didn't exist when I asked this question.
Write the assembly into its own file, and then call it from your C program using extern. You have to do a little bit of makefile trickery, but otherwise it's not so bad.
Your assembly code has to follow C conventions, so it should look like
global _myfunc
_myfunc: push ebp ; create new stack frame for procedure
mov ebp,esp ;
sub esp,0x40 ; 64 bytes of local stack space
mov ebx,[ebp+8] ; first parameter to function
; some more code
leave ; return to C program's frame
ret ; exit
To get at the contents of C variables, or to declare variables which C can access, you need only declare the names as GLOBAL or EXTERN. (Again, the names require leading underscores.) Thus, a C variable declared as int i can be accessed from assembler as
extern _i
mov eax,[_i]
And to declare your own integer variable which C programs can access as extern int j, you do this (making sure you are assembling in the _DATA segment, if necessary):
global _j
_j dd 0
Your C code should look like
extern void myasmfunc(variable a);
int main(void)
{
myasmfunc(a);
}
Compile the files, then link them using
gcc mycfile.o myasmfile.o
I just cannot find the solution to this issue..
What I'm trying to do is calling an assembly function using gcc. Just take a look:
// Somewhere in start.s
global _start_thread
_start_thread:
; ...
// Somewhere in UserThread.cpp
extern void _start_thread( pointer );
static void UserMainHack()
{
_start_thread(((UserThread*)currentThread)->getUserMain());
}
Thanks for any help..
Did you know that many C linkers automatically adds the leading underscore when looking for identifiers? So in the C source (not the assembler source), just remove the leading underscore:
extern void start_thread( pointer );
static void UserMainHack()
{
start_thread(((UserThread*)currentThread)->getUserMain());
}
Give your function [declaration] assembly linkage by using an "Asm Label":
extern void start_thread(pointer) __asm__("start_thread");
(and have the .global on the asm side match it.)
It works much like extern "C" in that it can be used for both functions and variables, and that it's one-sided (but on the C side this time).