_MOVING FROM ASSEMBLY TO C_ by Beth Mazur [LISTING ONE} ; 1 /* Here is a method of determining how the compiler expects parameters ; 2 to be passed between C and assembly routines. For example, suppose ; 3 you need to pass 3 integers to an assembly routine, where they will ; 4 be manipulated, and an integer value returned. The trick is to write ; 5 a C routine that simulates this. Then compile to assembly and see how ; 6 the compiler treats the parameters (you can use the generated ; 7 assembly code as a template and add your code to it). */ ; 8 int h,i,j,k; ; 9 main() ; 10 { _main: ; 11 h = subroutine(i,j,k); ldd _k ; push k on stack first pshd ldd _j ; push j on stack next pshd ldd _i ; leave i in register jbsr _subroutine ins ; clear parameters off stack ins ins ins std _h ; result in register ; 12 } rts ; 13 int subroutine(int a, int b, int c) ; 14 { _subroutine: pshx ; save X pshd ; save i on stack tsx ; transfer SP to X .set OFST=0 ; 15 return(a+b+c); ldd OFST+0,x ; code to copy i back to D addd OFST+6,x ; add j addd OFST+8,x ; add k, result left in D pulx ; restore D into X from stack pulx ; restore X rts ; 16 } [LISTING TWO] extern void reset(); /* symbol defined in startup routine */ extern void default(); /* generic routine generates a return from interrupt */ void (* const vec_tab[])() = { default, /* SCI */ default, /* SPI */ default, /* Pulse accumulator input edge */ default, /* Pulse accumulator overflow */ default, /* Timer overflow */ default, /* Timer output compare 5 */ default, /* Timer output compare 4 */ default, /* Timer output compare 3 */ default, /* Timer output compare 2 */ default, /* Timer output compare 1 */ default, /* Timer input capture 3 */ default, /* Timer input capture 2 */ default, /* Timer input capture 1 */ default, /* Real time interrupt */ default, /* IRQ */ default, /* XIRQ */ default, /* SWI */ default, /* illegal op-code */ default, /* COP watchdog timer fail */ default, /* COP monitor clock fail */ reset, /* RESET */ }; [LISTING THREE] ; 1 /* Here is a method of accessing the M68HC11 I/O ports that is portable ; 2 and can be compiled by most C compilers. c is declared as an int ; 3 because that's how putchar is defined by ANSI. The (char) cast is done ; 4 to avoid "illegal assignment" warnings from strict compilers. */ ; 5 #define SCSR *(char *) 0x102e /* SCI Status Register */ ; 6 #define SCDR *(char *) 0x102f /* SCI Data Register */ ; 7 #define TDRE 0x80 /* Transmit Data Register Empty bit */ ; 8 int putchar(int c) ; 9 { _putchar: pshx pshd tsx .set OFST=0 L1: ; line 14, offset 3 ; 10 while (!(SCSR & TDRE)) ldab 102eH bitb #128 beq L1 ; 11 /* loop until ready to transmit */ ; 12 SCDR = (char) c; ldab OFST+1,x stab 102fH ; 13 return(c); ldd OFST+0,x pulx pulx rts ; 14 } .public _putchar .end Example 1: int factorial(int fact) { int temp; temp=fact; if (!fact) temp=1; /* fact = 0? */ else temp*=factorial(temp-1); /* fact > 0 */ return (temp); } Example 2: (a) const double pi = 3.14159; main() { pi = 1.234; /* will generate error at compile-time */ } (b) extern const double pi; double circum(double radius) { double circ; circ = 2.0 * pi * radius; } Example 3: ; 1 volatile char porta; ; 2 char portb; ; 3 test() ; 4 { _test: ; 5 porta=1; ldab #1 stab _porta LL4: ; 6 porta=2; ldab #2 stab _porta LL6: ; 7 portb=1; /* optimized out as redundant */ ; 8 portb=2; ldab #2 stab _portb ; 9 } rts ; 10 Example 4: /* Initialized variables are declared with a value. The variable will have this value when the program begins executing. Uninitialized variables are not declared with a value. */ int days_of_year = 365; /* this is an intialized variable */ int number_of_days; /* this is uninitialized */ Example 5: long a,b; int i,j,k; int subroutine(int first, long second); main() { i=subroutine(j,a); /* no action will be taken */ i=subroutine(j,k); /* compiler will promote k to long */ i=subroutine(a,b); /* will generate error, since long cannot be passed for first param */ } Example 6: #define RDRF 0x20 /* Receive Data Register Full */ #define TRDE 0x80 /* Transmit Data Ready Empty */ #define SCSR *(char *) 0x102e /* SCI Status Register */ #define SCDR *(char *) 0x102f /* SCI Data Register */ int putchar(int c) { if (c == '\n') putchar('\r'); /* put newline and carriage return */ while (!(SCSR & TRDE)) /* wait until ready to receive */ ; SCDR = c; /* output character */ return (c); } int getchar() { int c; while (!(SCSR & RDRF)) /* wait for character */ ; c = SCDR; /* receive character */ if (c == '\r') c = '\n'; /* translate to newline */ return (c); } Example 7: (a) i = 1; /* i is declared as an int */ (b) ldab #1 stab _i (c) jsr _func Example 8: main() { ... _asm("sei\n"); /* disable interrupts */ func(); /* call function */ _asm("cli\n"); /* enable interrupts */ ... }