This gist is showing an example of C program calling routine written in assembly.
- C is case sensitive so it is necessary to use /ml switch in TASM
- C compiler uses leading underscore (_) character for function names
- parameters are passed to function in stack and integer return value is passed back in AX register
- stack cleaning is done by caller
Example:
extern int min(int p1, int p2)
SP + 4 p2
SP + 2 p1
SP: offset of return value
in case of FAR calling:
SP + 6 p2
SP + 4 p1
SP + 2 segment of return value
SP: offset of return value
We will implement two functions (max and swap) in assembler. Max function will accept two integers (a and b) and returns maximal value. Swap function accepts two pointers to two integers and swap their values.
;LIB.ASM
.MODEL SMALL
.CODE
_max PROC ;return value is in AX
PUBLIC _max
PUSH BP
MOV BP,SP
MOV AX,[BP+4] ;AX=a
CMP AX,[BP+6] ;a=b?
JGE end ;jump if a>=b
MOV AX,[BP+6] ;else AX=b
end:
POP BP
RET
_max ENDP
_swap PROC
PUBLIC _swap
PUSH BP
MOV BP,SP
MOV SI,[BP+4] ;SI=adresa a
MOV DI,[BP+6] ;DI=adresa b
MOV AX,[SI] ;AX=a
MOV BX,[DI] ;BX=b
MOV [SI],BX ;a=b
MOV [DI],AX ;b=a
POP BP
RET
_swap ENDP
ENDS
END
C program is showing how to use functions described above.
/*
* main.c
*/
#include <stdio.h>
extern int max(int a, int b);
extern void swap(int *a, int *b);
void main() {
int a, b;
printf("\nInsert two integers\n");
printf("A=");
scanf("%d", &a);
printf("B=");
scanf("%d", &b);
printf("maximum=%d\n", max(a,b));
swap(&a, &b);
printf("a=%d, b=%d\n", a, b);
}
Finally we will compile them and link all together.
tasm lib.asm /ml
tcc -c main.c
tlink c:\tc\lib\c0s main lib,app,,c:\tc\lib\cs