How to link a program wrote in C language and a program in asm language?
## addfun.s
.section .data
str:
.ascii "hi/n/0"
.globl addfun
.type addfun, @function
.section .text
addfun:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movl 8(%ebp), %ebx
addl %ebx, %eax
movl %ebp, %esp
popl %ebp
ret
# subfun.s
.section .data
str:
.ascii "hi/n/0"
.globl subfun
.type subfun, @function
.section .text
subfun:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movl 8(%ebp), %ebx
subl %ebx, %eax
movl %ebp, %esp
popl %ebp
ret
First, the above two asm sources must be compiled to object files.
as addfun.s -o addfun.o
as subfun.c -o subfun.o
//callasm.c
#include <stdio.h>
// declare two extern functions.
extern int addfun(int, int);
extern int subfun(int, int);
int main(int argc, char *argv[]){
int r=0;
r = addfun(3, 5);
fprintf(stderr, "added result = %d/n", r);
r = subfun(3, 5);
fprintf(stderr, "subtracted result = %d/n", r);
return 0;
}
Secondly, let's compile and link them.
gcc -o callasm callasm.c addfun.o subfun.o -lc
OK, a binary file is producted. We can run it, now.
ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)
All of the fields are optional. To calculate the address, simply perform the following calculation:
FINALADDRESS=ADDRESS_OR_OFFSET+%BASE_OR_OFFSET+MULTIPLIER*%INDEX
Parameter#N<---N*4+4(%ebp)
...
Parameter2<---12(%ebp)
Parameter1<---8(%ebp)
ReturnAddress<---4(%ebp)
Old%ebp<---(%ebp)
LocalVariable1<----4(%ebp)
LocalVariable2<----8(%ebp)and(%esp)
as write-record.s -o write-record.o
as read-record.s -o read-record.o
ld -shared write-record.o read-record.o -o librecord.so
as write-records.s -o write-records
ld -L . -dynamic-linker /lib/ld-linux.so.2 -o write-records -lrecord write-records.o
Memory Layout of a Linux Program at Startup
Environment Variables
...
Arg #2
Arg #1
Program name
# of arguments %esp
Unmapped Memory
Break
Program Code and Data
How to make a .so lib for a linux program?
There is an example.
//datatime.h
#ifndef __DATETIME_H
#define __DATETIME_H
/* */
typedef strUCt
{
int year;
int mon;
int day;
}DATETYPE;
/* */
typedef struct
{
char hour;
char min;
char sec;
}TIMETYPE;
int getdate(DATETYPE *d); /* */
int gettime(TIMETYPE *t); /* */
#endif
#ifdef SHARED
int (*getdate)(DATETYPE *d);
#else
int getdate(DATETYPE *d);
#endif
#ifdef SHARED
int (*gettime)(TIMETYPE *t);
#else
int gettime(TIMETYPE *t);
#endif
#endif
//getdate.c
#include "time.h"
#include "datetime.h"
int getdate(DATETYPE *d)
{
long ti;
struct tm *tm;
time(&ti);
tm=localtime(&ti);
d->year=tm->tm_year+1900;
d->mon=tm->tm_mon+1;
d->day=tm->tm_mday;
}
//gettime.c
#include "time.h"
#include "datetime.h"
int gettime(TIMETYPE *t)
{
long ti;
struct tm *tm;
time(&ti);
tm=localtime(&ti);
t->hour=tm->tm_hour;
t->min=tm->tm_min;
t->sec=tm->tm_sec;
}
//make file.
all : libmy.so
SRC = getdate.c gettime.c
TGT = $(SRC:.c=.o)
$(SRC) : adatetime.h
@touch $@
%.o : %.c
cc -c $?
libmy.so : $(TGT)
gcc -s -shared -o $@ $(TGT)
After, get my.so, we can write a program use it.
//dy.c
#include "stdio.h" /* */
#include "dlfcn.h" /* */
#define SOFILE "./my.so" /* */
#define SHARED /* */
#include "datetime.h" /* */
int main()
{
DATETYPE d;
TIMETYPE t;
void *dp;
char *error;
dp=dlopen(SOFILE,RTLD_LAZY); /* */
if (dp==NULL) /* */
{
fputs(dlerror(),stderr);
exit(1);
}
getdate=dlsym(dp,"getdate"); /* */
error=dlerror(); /* */
if (error) /* */
{
fputs(error,stderr);
exit(1);
}
getdate(&d); /* */
printf(": %04d-%02d-%02d/n",d.year,d.mon,d.day);
gettime=dlsym(dp,"gettime"); /* */
error=dlerror(); /* */
if (error) /* */
{
fputs(error,stderr);
exit(1);
}
gettime(&t); /* */
printf(": %02d:%02d:%02d/n",t.hour,t.min,t.sec);
dlclose(dp); /* */
exit(0); /* */
}
// yet another make file.
all : dy
DYSRC = dy.c
DYTGT = $(DYSRC:.c=.o)
%.o : %.c
cc -c $?
dy : $(DYTGT)
cc -rdynamic -s -o $@ $(DYTGT) -ldl
Now, we can run it. Note: -rdynamic tell compiler to product a program with *.so; -s will remove symbol table
from object file; -ldl to load ld program in order to load those dl* functions.
How to import variables and functions using DLL?
//lib.h
#ifndef LIB_H
#define LIB_H
extern "C" int __declspec(dllexport) add(int x, int y);
extern int __declspec(dllexport) dllGlobalVar;
#endif
//lib.cpp
#include "lib.h"
#include <windows.h>
#include <stdio.h>
int dllGlobalVar;
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
printf("/nprocess attach of dll/n");
dllGlobalVar = 100;
break;
case DLL_THREAD_ATTACH:
printf("/nthread attach of dll/n");
break;
case DLL_THREAD_DETACH:
printf("/nthread detach of dll/n");
break;
case DLL_PROCESS_DETACH:
printf("/nprocess detach of dll/n");
break;
}
return TRUE;
}
int add(int x, int y){
return x + y;
}
Make it a DLL. If you need static load a DLL, you had better add a .def file and make a .lib file.
LIBRARY lib
EXPORTS
add @ 1
dllGlobalVar DATA
Static load
//stCall.cpp
#include <stdio.h>
#pragma comment(lib, "lib.lib")
//extern int dllGlobalVar;
extern int _declspec(dllimport) dllGlobalVar;
extern "C" __declspec(dllimport) add(int x, int y);
int main(){
printf("%d ", dllGlobalVar);
dllGlobalVar = 1;
printf("dll variable: %d/n", dllGlobalVar);
printf("dll function: %d/n", add(2,3));
return 0;
}
Dynamic load
//dtDll.cpp
#include <stdio.h>
#include <windows.h>
typedef int(*lpAddFun)(int, int);
int main(int argc, char *argv[])
{
HINSTANCE hDll;
lpAddFun addFun;
hDll = LoadLibrary(".//lib.dll");
if (hDll != NULL) {
addFun = (lpAddFun)GetProcAddress(hDll, "add");
if (addFun != NULL) {
int result = addFun(2, 3);
printf("%d", result);
}
}
FreeLibrary(hDll);
}
How to use classes in DLL?
//point.h
#ifndef POINT_H
#define POINT_H
#ifdef DLL_FILE
class _declspec(dllexport) point
#else
class _declspec(dllimport) point
#endif
{
public:
float y;
float x;
point();
point(float x_coordinate, float y_coordinate);
};
#endif
//circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include "point.h"
#ifdef DLL_FILE
class _declspec(dllexport)circle
#else
class _declspec(dllimport)circle //?$BF~(B?circle
#endif
{
public:
void SetCentre(const point centrePointt);
void SetRadius(float r);
float GetGirth();
float GetArea();
circle();
private:
float radius;
point centre;
};
#endif
//clsDll
#include "circle.h"
#include <stdio.h>
#pragma comment(lib, "clsDll.lib")
int main(int argc, char *argv[])
{
circle c;
point p(2.0, 2.0);
c.SetCentre(p);
c.SetRadius(1.0);
printf("area:%f girth:%f", c.GetArea(), c.GetGirth());
return 0;
}
Make it a DLL, too.
//clsCall.cpp
#include "circle.h"
#include <stdio.h>
#pragma comment(lib, "clsDll.lib")
int main(int argc, char *argv[])
{
circle c;
point p(2.0, 2.0);
c.SetCentre(p);
c.SetRadius(1.0);
printf("area:%f girth:%f", c.GetArea(), c.GetGirth());
return 0;
}
Yes, it is to static load a DLL.
## addfun.s
.section .data
str:
.ascii "hi/n/0"
.globl addfun
.type addfun, @function
.section .text
addfun:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movl 8(%ebp), %ebx
addl %ebx, %eax
movl %ebp, %esp
popl %ebp
ret
# subfun.s
.section .data
str:
.ascii "hi/n/0"
.globl subfun
.type subfun, @function
.section .text
subfun:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
movl 8(%ebp), %ebx
subl %ebx, %eax
movl %ebp, %esp
popl %ebp
ret
First, the above two asm sources must be compiled to object files.
as addfun.s -o addfun.o
as subfun.c -o subfun.o
//callasm.c
#include <stdio.h>
// declare two extern functions.
extern int addfun(int, int);
extern int subfun(int, int);
int main(int argc, char *argv[]){
int r=0;
r = addfun(3, 5);
fprintf(stderr, "added result = %d/n", r);
r = subfun(3, 5);
fprintf(stderr, "subtracted result = %d/n", r);
return 0;
}
Secondly, let's compile and link them.
gcc -o callasm callasm.c addfun.o subfun.o -lc
OK, a binary file is producted. We can run it, now.
ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)
All of the fields are optional. To calculate the address, simply perform the following calculation:
FINALADDRESS=ADDRESS_OR_OFFSET+%BASE_OR_OFFSET+MULTIPLIER*%INDEX
Parameter#N<---N*4+4(%ebp)
...
Parameter2<---12(%ebp)
Parameter1<---8(%ebp)
ReturnAddress<---4(%ebp)
Old%ebp<---(%ebp)
LocalVariable1<----4(%ebp)
LocalVariable2<----8(%ebp)and(%esp)
as write-record.s -o write-record.o
as read-record.s -o read-record.o
ld -shared write-record.o read-record.o -o librecord.so
as write-records.s -o write-records
ld -L . -dynamic-linker /lib/ld-linux.so.2 -o write-records -lrecord write-records.o
Memory Layout of a Linux Program at Startup
Environment Variables
...
Arg #2
Arg #1
Program name
# of arguments %esp
Unmapped Memory
Break
Program Code and Data
How to make a .so lib for a linux program?
There is an example.
//datatime.h
#ifndef __DATETIME_H
#define __DATETIME_H
/* */
typedef strUCt
{
int year;
int mon;
int day;
}DATETYPE;
/* */
typedef struct
{
char hour;
char min;
char sec;
}TIMETYPE;
int getdate(DATETYPE *d); /* */
int gettime(TIMETYPE *t); /* */
#endif
#ifdef SHARED
int (*getdate)(DATETYPE *d);
#else
int getdate(DATETYPE *d);
#endif
#ifdef SHARED
int (*gettime)(TIMETYPE *t);
#else
int gettime(TIMETYPE *t);
#endif
#endif
//getdate.c
#include "time.h"
#include "datetime.h"
int getdate(DATETYPE *d)
{
long ti;
struct tm *tm;
time(&ti);
tm=localtime(&ti);
d->year=tm->tm_year+1900;
d->mon=tm->tm_mon+1;
d->day=tm->tm_mday;
}
//gettime.c
#include "time.h"
#include "datetime.h"
int gettime(TIMETYPE *t)
{
long ti;
struct tm *tm;
time(&ti);
tm=localtime(&ti);
t->hour=tm->tm_hour;
t->min=tm->tm_min;
t->sec=tm->tm_sec;
}
//make file.
all : libmy.so
SRC = getdate.c gettime.c
TGT = $(SRC:.c=.o)
$(SRC) : adatetime.h
@touch $@
%.o : %.c
cc -c $?
libmy.so : $(TGT)
gcc -s -shared -o $@ $(TGT)
After, get my.so, we can write a program use it.
//dy.c
#include "stdio.h" /* */
#include "dlfcn.h" /* */
#define SOFILE "./my.so" /* */
#define SHARED /* */
#include "datetime.h" /* */
int main()
{
DATETYPE d;
TIMETYPE t;
void *dp;
char *error;
dp=dlopen(SOFILE,RTLD_LAZY); /* */
if (dp==NULL) /* */
{
fputs(dlerror(),stderr);
exit(1);
}
getdate=dlsym(dp,"getdate"); /* */
error=dlerror(); /* */
if (error) /* */
{
fputs(error,stderr);
exit(1);
}
getdate(&d); /* */
printf(": %04d-%02d-%02d/n",d.year,d.mon,d.day);
gettime=dlsym(dp,"gettime"); /* */
error=dlerror(); /* */
if (error) /* */
{
fputs(error,stderr);
exit(1);
}
gettime(&t); /* */
printf(": %02d:%02d:%02d/n",t.hour,t.min,t.sec);
dlclose(dp); /* */
exit(0); /* */
}
// yet another make file.
all : dy
DYSRC = dy.c
DYTGT = $(DYSRC:.c=.o)
%.o : %.c
cc -c $?
dy : $(DYTGT)
cc -rdynamic -s -o $@ $(DYTGT) -ldl
Now, we can run it. Note: -rdynamic tell compiler to product a program with *.so; -s will remove symbol table
from object file; -ldl to load ld program in order to load those dl* functions.
How to import variables and functions using DLL?
//lib.h
#ifndef LIB_H
#define LIB_H
extern "C" int __declspec(dllexport) add(int x, int y);
extern int __declspec(dllexport) dllGlobalVar;
#endif
//lib.cpp
#include "lib.h"
#include <windows.h>
#include <stdio.h>
int dllGlobalVar;
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
printf("/nprocess attach of dll/n");
dllGlobalVar = 100;
break;
case DLL_THREAD_ATTACH:
printf("/nthread attach of dll/n");
break;
case DLL_THREAD_DETACH:
printf("/nthread detach of dll/n");
break;
case DLL_PROCESS_DETACH:
printf("/nprocess detach of dll/n");
break;
}
return TRUE;
}
int add(int x, int y){
return x + y;
}
Make it a DLL. If you need static load a DLL, you had better add a .def file and make a .lib file.
LIBRARY lib
EXPORTS
add @ 1
dllGlobalVar DATA
Static load
//stCall.cpp
#include <stdio.h>
#pragma comment(lib, "lib.lib")
//extern int dllGlobalVar;
extern int _declspec(dllimport) dllGlobalVar;
extern "C" __declspec(dllimport) add(int x, int y);
int main(){
printf("%d ", dllGlobalVar);
dllGlobalVar = 1;
printf("dll variable: %d/n", dllGlobalVar);
printf("dll function: %d/n", add(2,3));
return 0;
}
Dynamic load
//dtDll.cpp
#include <stdio.h>
#include <windows.h>
typedef int(*lpAddFun)(int, int);
int main(int argc, char *argv[])
{
HINSTANCE hDll;
lpAddFun addFun;
hDll = LoadLibrary(".//lib.dll");
if (hDll != NULL) {
addFun = (lpAddFun)GetProcAddress(hDll, "add");
if (addFun != NULL) {
int result = addFun(2, 3);
printf("%d", result);
}
}
FreeLibrary(hDll);
}
How to use classes in DLL?
//point.h
#ifndef POINT_H
#define POINT_H
#ifdef DLL_FILE
class _declspec(dllexport) point
#else
class _declspec(dllimport) point
#endif
{
public:
float y;
float x;
point();
point(float x_coordinate, float y_coordinate);
};
#endif
//circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include "point.h"
#ifdef DLL_FILE
class _declspec(dllexport)circle
#else
class _declspec(dllimport)circle //?$BF~(B?circle
#endif
{
public:
void SetCentre(const point centrePointt);
void SetRadius(float r);
float GetGirth();
float GetArea();
circle();
private:
float radius;
point centre;
};
#endif
//clsDll
#include "circle.h"
#include <stdio.h>
#pragma comment(lib, "clsDll.lib")
int main(int argc, char *argv[])
{
circle c;
point p(2.0, 2.0);
c.SetCentre(p);
c.SetRadius(1.0);
printf("area:%f girth:%f", c.GetArea(), c.GetGirth());
return 0;
}
Make it a DLL, too.
//clsCall.cpp
#include "circle.h"
#include <stdio.h>
#pragma comment(lib, "clsDll.lib")
int main(int argc, char *argv[])
{
circle c;
point p(2.0, 2.0);
c.SetCentre(p);
c.SetRadius(1.0);
printf("area:%f girth:%f", c.GetArea(), c.GetGirth());
return 0;
}
Yes, it is to static load a DLL.