Lab 7
Subroutines and APCS
1. Implement the following C programs in Assembly
using APCS conventions
A. Subroution call
int tmp;
void swap(int a, int b);
int main()
{
int a,b;
a = 3;
b = 4;
swap(a,b);
} /* end main() */
void swap(int a,int b)
{
tmp = a;
a = b;
b = tmp;
} /* end swap() */
B. Pointer arguments
int tmp;
int *pa, *pb;
void swap(int a, int b);
int main()
{
int a,b;
pa = &a;
pb = &b;
*pa = 3;
*pb = 4;
swap(*pa, *pb);
} /* end main() */
void swap(int a,int b)
{
tmp = a;
a = b;
b = tmp;
} /* end swap() */
C. Lot of arguments
int tmp;
void test(int a, int b, int c, int d, int *e);
int main()
{ int a, b, c, d, e;
a = 3;
b = 4;
c = 5;
d = 6;
e = 7;
test(a, b, c, d, &e);
} /* end main() */
void test(int a,int b,
int c, int d, int *e)
{
tmp = a;
a = b;
b = tmp;
c = b;
b = d;
*e = d;
} /* end test() */
D. Nested calls
int tmp;
int swap(int a, int b);
void swap2(int a, int b);
int main(){
int a, b, c;
a = 3;
b = 4;
c = swap(a,b);
} /* end main() */
int swap(int a,int b){
tmp = a;
a = b;
b = tmp;
swap2(a,b);
return(10);
} /* end swap() */
void swap2(int a,int b){
tmp = a;
a = b;
b = tmp;
} /* end swap() */
E. Structures
typedef struct
testStruct {
unsigned int a;
unsigned int b;
char c;
} testStruct;
testStruct *ptest;
int main()
{
ptest>a = 4;
ptest>b = 10;
ptest>c = 'A';
} /* end main() */
2. Calling Assembly functions from C
Using APCS conventions write the divide function in Assembly and name it divasm .
Test by calling it from the following c program
extern int divasm(int
a, int b);
int divc(int a,int b)
{ int r;
int t=1;
while( (b&0x40000000) == 0 ) { /* fails if b=0 */
b=b<<1;
t=t<<1;
}
r=0;
do {
if((a-b)>=0) {
a=a-b;
r=r+t;
}
b=b>>1;
t=t>>1;
} while(t!=0);
return r;
}
int main( int argc,
char **argv )
{int i,j,k;
for(i=1; i<64; i+=3) {
j=divasm(1234,i);
k=divc(1234,i);
printf("1234/%2d = %4d
%s",i,j,(1234/i)==j ? "....correct" : "ERROR!!! ");
printf(" = %4d
%s\n",k,(1234/i)==k ? "....correct" : "ERROR!!! ");
}
return 0;
}
To make the assembly function available to our C program we need to export symbol from Assembly Language code. Since it is not stand alone we can eliminate the ENTRY statement and instead at beginning of code section we need to put
EXPORT label
where label is the name of the function we called from C.
We have told the C compiler that the code is defined elsewhere by including in the C code
extern type label (args);
in this case
extern int divasm(int a, int b);