Use assembly to call C-library functions

Source: Internet
Author: User

1. Implementation goals
Use assembler to call the C-database function, that is, the function can be called when the function name and parameter are given.
II. Problem description
when implementing the C interpreter, parse the function call statement, for example, strlen ("linxr"); then, how do I call the strlen function?
first, obtain the parameter list arg_listk, and then call the stlen function using the Code in the following format:
If (strcmp (token, "strlen") = 0) {
strlen (arg_list [0]);
}< br> else if (...) {
}< br>...
[problem] in this way, there are hundreds of library functions in C, so this code will become endless.


3. Solve the problem
based on the above problem. I came up with a way to call the C-library function with a unified entry. The function prototype is tentatively set to
int cCall (void * Fapp, var_t * arg_list);
Fapp: function address
arg_list: parameter list, var_t is the variable type I have defined, which is not described here.
to call the cCall function, you must first do two things:
1. You must obtain the corresponding function pointer Based on the function name.
now I am using a list to maintain the pointer of all c-database functions, which can be defined as follows:
struct cpp_t {
char * fname;
char * Fapp;
} cpp_table [100] ={< br> "strlen", (char *) strlen,
"strcpy ", (char *) strcpy,
....
}< br> the function pointer can be searched by function name to traverse the table, but the efficiency is relatively low. I have implemented all hash tables, which are not detailed here.
2. You must obtain a list of parameters based on the function call statement. How to implement it is about Syntax Parsing. :)

 
IV. Implementation of the cCall Function
If you understand the function calling rules of C, this problem will be quite simple. Here is a brief description:
For example, call printf ("% d", 1, 2 );
The C language calling rules (I .e. _ cdecl) are as follows:
Push 2
Push 1
Push 0x123456; Set 0x123456 to the address of the string "% d"
Call 0xa0b1c2; Set 0xa0b1c2 to the address of printf
Add ESP, 12; balance the stack here

So it's easy. We only need to let C call Assembly to implement this cCall function.
 

The following assembly is compiled using MASM. Compile command:ML/C/COFF/Zi/FL cCall. ASM
[CCall. ASM Code]

 Title cCall

. 386
. Model flat, c

. Data?
Arg_num DWORD 0
Arg_tab DWORD 100 DUP ( 0 )
Arg_tye DWORD 100 DUP ( 0 )
Fun_ptr DWORD 0


. Code

Push_arg_ini proc
MoV Arg_num, 0
RET
Push_arg_ini endp


Push_arg proc, Arg: sdword, Tye: sdword
MoV Eax, arg_num
MoV EBX, offset arg_tab
MoV ECX, ARG
MoV [EBX + eax * 4 ], ECx

MoV EBX, offset arg_tye
MoV ECX, Tye
MoV [EBX + eax * 4 ], ECx

Add Eax, 1
MoV Arg_num, eax
RET
Push_arg endp


Push_fun proc, fun: sdword
MoV Eax, fun
MoV Fun_ptr, eax
RET
Push_fun endp


I _fun_call proc
Local count: DWORD
XOR Eax, eax
MoV EBX, offset arg_tab
MoV ECX, offset arg_tye
MoV Count, 0

. While eax <arg_num
MoV EdX, [ECx + eax * 4 ]
; Floating point type inbound stack ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;
. If edX
Bytes Dword ptr [EBX + eax * 4 ]
Sub ESP, 8
Fstp Qword PTR [esp]
. Elseif
Push [EBX + eax * 4 ]
. Endif
Add Eax, 1
Add Count, 4
. Endw

MoV Eax, fun_ptr
Call Eax
Add ESP, count
RET
I _fun_call endp

F_fun_call proc
Local count: DWORD
XOR Eax, eax
MoV EBX, offset arg_tab
MoV ECX, offset arg_tye
MoV Count, 0

. While eax <arg_num
MoV EdX, [ECx + eax * 4 ]
; Floating point type inbound stack ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;
. If edX
Bytes Dword ptr [EBX + eax * 4 ]
Sub ESP, 8
Fstp Qword PTR [esp]
. Elseif
Push [EBX + eax * 4 ]
. Endif
Add Eax, 1
Add Count, 4
. Endw

MoV Eax, fun_ptr
Call Eax
Add ESP, count
RET
f_fun_call endp
end


declare these functions in C:
int _ cdecl push_arg_ini ();
int _ cdecl push_arg (INT Arg, int Tye );
int _ cdecl push_fun (INT fun);
int _ cdecl I _fun_call ();
double _ cdecl f_fun_call ();
in this way, if you want to call the strlen function in C, you can call the function as follows:
push_arg_ini ();
push_arg (INT) "linxr", 0); // The second parameter here is the parameter type, because the floating point type's inbound stack mode is different from the integer type
push_fun (INT) strlen );
I _fun_call (); // f_fun_call is used to return the double type.
In fact, calling any c-database function can be implemented in this way, so we can easily define and implement the above cCall function.
int cCall (void * Fapp, var_t * arg_list)
{< br> int I;
push_arg_ini ();
for (I = 0; I push_arg (arg_list [I]. value, arg_list [I]. type);
}< br> push_fun (INT) Fapp);
return I _fun_call ();
}< br> return the double type cCall...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.