; ; Procedures written in assembly but called by C ; ; C uses the stack to pass parameters, pushing them in reverse order ; ; We use a STANDARD STACK FRAME to access the stack, by PUSHing BP,and ; setting it to SP: ; ; STACK ;-------- ; arg3 (SP+10) ; arg2 (SP+8) ; arg1 (SP+6) ; CS (SP+4) ; IP (BP+2) ; BP (BP=SP) ; ... ; ; The return value is put in ; ; AL - if it's a "char" (byte) ; AX - if it's an "int" (word) ; DX:AX - if it's a "long" (dword) ; Any procedure called by C: ; ; 1) cannot modify ES,DS,SI,DI,BP ; 2) must balance the stack ; 3) must begin with an underscore "_" (name mangling) ; 4) must initialize DS to use its own ASM variables ; ; More examples: ; proc _MYSUB far push bp mov bp,sp push ds ; Save registers mov ax,cs ; Load DS mov dx,ax mov ax,[bp+6] ; Access function parameters sub ax,[bp+8] ; return value in AX pop ds ; Restore registers pop bp ret _MYSUB endp ; ; int printchar(int num,char c); ; proc _printchar far push bp mov bp,sp .. mov cx,word ptr [bp+6] mov dl,byte ptr [bp+8] ; character occupies lower address top: call dspout loop top .. pop bp ret _printchar endp ; ; int mydiv(long dividend,int divisor); ; ; [BP+8]:[BP+6] - dividend ; [BP+10] - divisor ; proc _mydiv far push bp mov bp,sp .. mov dx,[bp+8] ; example of a dowubleword argument spread mov ax,[bp+6] ; across two stack locations div [bp+10] ; stack locations can be used as operands .. pop bp ret mydiv endp ; ; char mystr="Hello, how are you today!?$" ; printstr(mystr); ; ; ; void printstr(char *str); ; ; [BP+6] - offset of string to print ; proc _printstr far push bp mov bp,sp ; set standard stack frame .. mov si,[bp+6] ; Offset of message .. PrintLoop: mov dl,[si] ; Read character from [DS:offset] cmp dl,'$' je PrintLoopDone call dspout inc SI jmp PrintLoop .. PringLoopDone: pop bp ret _printstr endp ; ; PrintTheAnswer("fifty-seven"); ; ; ; void PrintTheAnswer(char *str); ; ; Like above, but prepends output with 'The Answer is: ' ; ; [BP+6] - offset of string to print ; OutMessage db 'The Answer is: ',$ proc _PrintTheAnswer far push bp mov bp,sp push ds ; Must preserve default segment in C call mov ax,cs mov ds,ax ; Load default segment for OutMessage mov ax, offset OutMessage push ax ; Push offset of OutMessage Call _printstr ; Print 'The Answer is: ' pop ax ; cleanup stack pop ds ; restore DS mov ax, [bp+6] push ax Call _printstr ; Print acutal message pop ax pop bp ret _PrintTheAnswer endp