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);