Mixed C and MASM with MASM Main Language, No C Run-Time (86815)



The information in this article applies to:

  • Microsoft Macro Assembler (MASM) 5.0
  • Microsoft Macro Assembler (MASM) 5.1
  • Microsoft Macro Assembler (MASM) 5.1a
  • Microsoft Macro Assembler (MASM) 6.0
  • Microsoft Macro Assembler (MASM) 6.0a
  • Microsoft Macro Assembler (MASM) 6.0b
  • Microsoft Macro Assembler (MASM) 6.1

This article was previously published under Q86815

SUMMARY

The following steps should be used when doing mixed-language programming between the Microsoft Macro Assembler (MASM) and Microsoft C with MASM as the main language and when no C run-time will be used:
  1. Include the statement

    .MODEL <model>

    in the assembly module to ensure that the modules use the same default segments. The <model> will be small, medium, compact, or large.
  2. Use the END directive in the assembly module to specify the entry point.
  3. Compile the C module with /Gs to avoid generation of calls to the stack checking routine.
  4. If the C compiler is version 5.1, include the following statement in the C module to ensure that the startup code is not brought in:
          int _acrtused = 0;
    						
  5. Assemble the assembly module with /Mx to preserve the case of nonlocal names. If MASM 6.0 or later is being used, use /Cx to preserve the case of nonlocal names.
Note that the only contributions to the stack segment come from the assembly module.

MORE INFORMATION

The following is a mixed-language sample. There is one C module and one assembly module that must be compiled and then linked together. No special link options are needed.

The sample declares two words, arg1 and arg2, converts them to dollar-terminated strings, prints out their values to the screen, and passes their addresses to a C routine. The C routine swaps the values of arg1 and arg2. The values of arg1 and arg2 are printed out a second time to show that they have been swapped.

NOTE: The EXTRN directive changed to EXTERN in MASM 6.1 All instances of EXTRN should be changed to EXTERN in the sample code below if you are using MASM version 6.1 or later.

Sample Code

/* Compile options needed: /Gs
*/ 

/* Uncomment the following line for C 5.1 to ensure that the startup
   code is not brought in:

      int _acrtused = 0;
*/ 

void ptrswap( int *ptr1, int *ptr2 )
{
    int temp;

    temp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = temp;
}

----------------------------------------------------------------------

; Assemble options needed: /Mx

    .MODEL small

Display MACRO string              ; Print a "$" terminated string
    MOV ah, 9
    MOV dx, offset string
    INT 21h
    ENDM

    .STACK
    .DATA

arg1    DW 1234
arg2    DW 4321
outstr1 DB "Arg1: ", "$"
outstr2 DB "Arg2: ", "$"
newline DB 13, 10, "$"            ; Carriage return-linefeed
converted  DD ?                   ; Will contain arg1 or arg2 after
        DB "$"                    ;    they are converted

    .CODE

EXTRN   _ptrswap:proc             ; External C routine

cnvrt   PROC

; ********     Convert a word to a dollar-terminated string.    *******

    PUSH   bp                 ; Establish
    MOV    bp, sp             ; stack frame

    MOV    ax, [bp+4]         ; Get first argument off stack
    MOV    bx, offset converted
    MOV    cx, 10
    MOV    si, 3              ; Index for storing in converted
nextdigit:
    MOV    dx, 0
    DIV    cx                 ; Divide ax by cx
    ADD    dl, "0"            ; Convert to ASCII value
    MOV    [bx][si], dl       ; Save digit in converted
    DEC    si                 ; Decrement index
    CMP    si, 0FFFFh         ; Are we done?
    JNZ    nextdigit

    ADD    sp, 2              ; Destroy argument
    RET                       ; Return
cnvrt   ENDP
; ********************************************************************

start:
    MOV    ax, @data          ; Load the data
    MOV    ds, ax             ;    segment register

; Print "Arg1: <value>"  where <value> is the value of arg1

    Display outstr1           ; Use display macro
    MOV    ax, arg1
    PUSH   ax                 ; Push argument
    CALL   cnvrt              ; Call the convert procedure
    Display converted         ; Use display macro
    Display newline           ; Use display macro

; Print "Arg2: <value>"  where <value> is the value of arg2

    Display outstr2           ; Use display macro
    MOV    ax, arg2
    PUSH   ax                 ; Push argument
    CALL   cnvrt              ; Call the convert procedure
    Display converted         ; Use the display macro
    Display newline           ; Use the display macro
    Display newline           ; Use the display macro

; Call the C module to swap the values of arg1 and arg2

    MOV    bx, offset arg2
    PUSH   bx                 ; Push the 2nd argument
    MOV    bx, offset arg1
    PUSH   bx                 ; Push the 1st argument
    CALL   _ptrswap           ; Call the C routine

; Print out arg1 again, to show that it has changed

    Display outstr1           ; Use display macro
    MOV    ax, arg1
    PUSH   ax                 ; Push argument
    CALL   cnvrt              ; Call the convert procedure
    Display converted         ; Use display macro
    Display newline           ; Use display macro

; Print out arg2 again, to show that it has changed

    Display outstr2           ; Use display macro
    MOV    ax, arg2
    PUSH   ax                 ; Push argument
    CALL   cnvrt              ; Call the convert procedure
    Display converted         ; Use display macro
    Display newline           ; Use display macro

    MOV    ah, 4ch            ; Terminate program
    int    21h

    END    start              ; Specify entry point as _start
				

Modification Type:MajorLast Reviewed:10/17/2003
Keywords:KB86815