|
|||||
16
Interfacing with
High
Level
Languages
16.1.
CALLING CONVENTIONS
To
interface an assembly routine with a
high level language
program
means
to be able to call functions
back and forth. And to be
able to do so
requires
knowledge of certain behavior of
the HLL when calling
functions.
This
behavior of calling functions is
called the calling
conventions of the
language.
Two prevalent calling
conventions are the C
calling convention
and
the
Pascal calling
convention.
What is
the naming convention
C
prepends an underscore to every
function or variable name
while Pascal
translates
the name to all uppercase.
C++ has a weird name
mangling
scheme
that is compiler dependent. To
avoid it C++ can be forced
to use C
style
naming with extern "C"
directive.
How
are parameters passed to the
routine
In C
parameters are pushed in
reverse order with the
rightmost being
pushed
first. While in Pascal they
are pushed in proper order
with the
leftmost
being pushed first.
Which registers
must be preserved
Both
standards preserve EBX, ESI, EDI,
EBP, ESP, DS, ES,
and SS.
Which registers
are used as scratch
Both
standards do not preserve or
guarantee the value of EAX, ECX,
EDX,
FS,
GS, EFLAGS, and any
other registers.
Which
register holds the return
value
Both C
and Pascal return upto
32bit large values in EAX
and upto 64bit
large
values in EDX:EAX.
Who is responsible
for removing the parameters
In C
the caller removes the
parameter while in Pascal
the callee removes
them.
The C scheme has reasons
pertaining to its provision
for variable
number
of arguments.
16.2.
CALLING C FROM
ASSEMBLY
For
example we take a function
divide declared in C as
follows.
int divide( int dividend, int
divisor );
To call
this function from assembly
we have to write.
push
dword [mydivisor]
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
push
dword [mydividend]
call
_divide
add esp,
8
; EAX holds the
answer
Observe
the order of parameters
according to the C calling
conventions
and
observe that the caller
cleared the stack. Now take
another example of a
function
written in C as follows.
void swap( int*
p1, int* p2 )
{
int temp =
*p1;
*p1 = *p2;
*p2 = temp;
}
To call
it from assembly we have to
write this.
[section
.text]
extern
_swap
x:
dd 4
y:
dd 7
push
dword y
push
dword x
call
_swap
; will only retain the
specified registers
add esp,
8
Observe
how pointers were initialized
appropriately. The above
function
swap
was converted into assembly
by the gcc compiler as
follows.
; swap
generated by gcc with no optimizations (converted to
Intel
syntax)
; 15 instructions
AND 13 memory
accesses
_swap:
push
ebp
mov
ebp,
esp
sub
esp, 4
; space created
for temp
mov eax,
[ebp+8]
mov eax,
[eax]
mov
[ebp-4],
eax
; temp =
*p1
mov edx,
[ebp+8]
mov eax,
[ebp+12]
mov eax,
[eax]
mov
[edx],
eax
; *p1 = *p2
mov edx,
[ebp+12]
mov eax,
[ebp-4]
mov [edx],
eax
; *p2 =
temp
leave
;;;;; EQUIVALENT
TO mov esp, ebp AND pop
ebp ;;;;;
ret
If we turn on
optimizations the same
function is compiled into
the following
code.
180
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
; generated with
full optimization by gcc compiler
; 12 instructions
AND 11 memory
accesses
_swap:
push
ebp
mov
ebp,
esp
push
ebx
mov
edx,
[ebp+8]
mov
ecx,
[ebp+12]
mov
ebx, [edx]
mov
eax, [ecx]
mov
[edx],
eax
mov
[ecx],
ebx
pop
ebx
pop
ebp
ret
16.3.
CALLING ASSEMBLY FROM
C
We now
write a hand optimized
version in assembly. Our version is
only 6
instructions
and 6 memory
accesses.
Example
16.1
001
[section
.text]
002
global
_swap
003
_swap:
mov
ecx,[esp+4]
; copy
parameter p1 to ecx
004
mov
edx,[esp+8]
; copy
parameter p2 to edx
005
mov
eax,[ecx] ; copy *p1 into
eax
006
xchg eax,[edx]
; exchange eax with *p2
007
mov
[ecx],eax ; copy eax into
*p1
008
ret
; return from this
function
We
assemble the above program
with the following
command.
·nasm f win32
swap.asm
This
produces a swap.obj file.
The format directive told
the assembler that
it is to be
linked with a 32bit Windows
executable. The linking
process
involves
resolving imported symbols of
one object files with export
symbols of
another.
In NASM an imported symbol is declared
with the extern
directive
while
and exported symbol is
declared with the global
directive.
We
write the following program
in C to call this assembly
routine. We
should
have provided the swap.obj
file to the C linker
otherwise an
unresolved
external symbol error will
come.
Example
16.1
001
#include
<stdio.h>
002
003
void swap( int*
p1, int* p2 );
004
005
int main()
006
{
007
int a = 10, b =
20;
008
printf( "a=%d
b=%d\n", a, b );
009
swap(&a, &b
);
010
printf( "a=%d
b=%d\n", a, b );
011
system(
"PAUSE" );
012
return 0;
013
}
181
Computer
Architecture & Assembly Language
Programming
Course
Code: CS401
CS401@vu.edu.pk
EXERCISES
1.
Write a traverse function in
assembly, which takes an array,
the
number
of elements in the array and
the address of another
function
to be
called for each member of
the array. Call the
function from a C
program.
2. Make
the linked list functions
make in Exercise 5.XX available to
C
programs
using the following
declarations.
struct node
{
int data;
struct node*
next;
};
void init( void
);
struct node*
createlist( void );
void insertafter( struct node*,
int );
void deleteafter( struct
node* );
void deletelist( struct
node* );
3. Add
two functions to the above
program implemented in C.
The
function
"printnode" should print the
data in the passed node
using
printf,
while "countfree" should
count the number of free
nodes by
traversing
the free list starting
from the node address
stored in
firstfree.
void printnode( struct
node* );
void countfree( void
);
4. Add
the function "printlist" to
the above program and
implement
in
assembly.
This function should
traverse the list whose
head
is
passed
as parameter and for each
node containing data
(head
is
dummy
and doesn't contain data)
calls the C function
printnode
to
actually
print the contained
data.
void printlist( struct
node* );
5.
Modify the createlist and
deletelist functions in the
above program to
increment
and decrement an integer
variable "listcount" declared
in
C to
maintain a count of linked
lists present.
182
Table of Contents:
|
|||||