Writing Functions

If you write a function with inline assembly code, it's a simple matter to pass arguments to the function and return a value from it. The following examples compare a function first written for a separate assembler and then rewritten for the inline assembler. The function, called power2, receives two parameters, multiplying the first parameter by 2 to the power of the second parameter. Written for a separate assembler, the function might look like this:

; POWER.ASM

; Compute the power of an integer

;

PUBLIC _power2

_TEXT SEGMENT WORD PUBLIC 'CODE'

_power2 PROC

push bp ; Save BP

mov bp, sp ; Move SP into BP so we can refer

; to arguments on the stack

mov ax, [bp+4] ; Get first argument

mov cx, [bp+6] ; Get second argument

shl ax, cl ; AX = AX * ( 2 ^ CL )

pop bp ; Restore BP

ret ; Return with sum in AX

_power2 ENDP

_TEXT ENDS

END

Summary: Function arguments are usually passed on the stack.

Since it's written for a separate assembler, the function requires a separate source file and assembly and link steps. C function arguments usually are passed on the stack, so this version of the power2 function accesses its arguments by their positions on the stack. (Note that the MODEL directive, available in MASM and some other assemblers, also allows you to access stack arguments and local stack variables by name.)

The POWER2.C program below writes the power2 function with inline
assembly code:

/* POWER2.C */

#include <stdio.h>

int power2( int num, int power );

void main( void )

{

printf( "3 times 2 to the power of 5 is %d\n", \

power2( 3, 5) );

}

int power2( int num, int power )

{

__asm

{

mov ax, num ; Get first argument

mov cx, power ; Get second argument

shl ax, cl ; AX = AX * ( 2 to the power of CL )

}

/* Return with result in AX */

}

The inline version of the power2 function refers to its arguments by name and appears in the same source file as the rest of the program. This version also requires fewer assembly instructions. Since C automatically preserves BP, the __asm block doesn't need to do so. It can also dispense with the RET instruction, since the C part of the function performs the return.

Because the inline version of power2 doesn't execute a C return statement, it causes a harmless warning if you compile at warning levels 2 or higher:

warning C4035: 'power2' : no return value

The function does return a value, but QuickC cannot tell that in the absence of a return statement. Simply ignore the warning in this context.