News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

compile a *.asm file to a *.obj file

Started by zoncpp, February 03, 2009, 12:20:02 PM

Previous topic - Next topic

zoncpp

Hi!
how do i compile a *.asm file to a *.obj file?
i want to use this object file in other projects (VC project or delphi project).

evlncrn8

ml blah.asm

should make blah.obj....

this is pretty rudimentary :)

zoncpp

please explain more. i am a VC programmer and i start learning assembly language.


this command :  \masm32\bin\ml /c /coff test.asm  , create an obj file, but this obj file is not valid for other project for using.
i want an object file (created of *.asm) that i add this file in other project (VC or Delphi). how do i create this object file?

MichaelW

#3
How did you determine that the object module (file) was not valid?

As a simple example I took the MASM32 dwtoa source (\masm32\m32lib\dwtoa.asm):

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

  ; ---------------------------------------------------------------
  ; This procedure was written by Tim Roberts
  ; Minor fix by Jibz, December 2004
  ; ---------------------------------------------------------------

    .486
    .model flat, stdcall  ; 32 bit memory model
    option casemap :none  ; case sensitive

    .code

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

align 4

dwtoa proc dwValue:DWORD, lpBuffer:DWORD

    ; -------------------------------------------------------------
    ; convert DWORD to ascii string
    ; dwValue is value to be converted
    ; lpBuffer is the address of the receiving buffer
    ; EXAMPLE:
    ; invoke dwtoa,edx,ADDR buffer
    ;
    ; Uses: eax, ecx, edx.
    ; -------------------------------------------------------------

    push ebx
    push esi
    push edi

    mov eax, dwValue
    mov edi, [lpBuffer]

    test eax,eax
    jnz sign

  zero:
    mov word ptr [edi],30h
    jmp dtaexit

  sign:
    jns pos
    mov byte ptr [edi],'-'
    neg eax
    add edi, 1

  pos:
    mov ecx, 3435973837
    mov esi, edi

    .while (eax > 0)
      mov ebx,eax
      mul ecx
      shr edx, 3
      mov eax,edx
      lea edx,[edx*4+edx]
      add edx,edx
      sub ebx,edx
      add bl,'0'
      mov [edi],bl
      add edi, 1
    .endw

    mov byte ptr [edi], 0       ; terminate the string

    ; We now have all the digits, but in reverse order.

    .while (esi < edi)
      sub edi, 1
      mov al, [esi]
      mov ah, [edi]
      mov [edi], al
      mov [esi], ah
      add esi, 1
    .endw

  dtaexit:

    pop edi
    pop esi
    pop ebx

    ret

dwtoa endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end


And this source file (test.c):

#include <windows.h>
void _stdcall dwtoa( int dwValue, char *lpBuffer );
int main(void)
{
    char buffer[20];

    dwtoa( 123456, &buffer[0] );
    printf( "%s\n", &buffer[0] );

    getch();
    return 0;
}


And assembled, compiled, and linked with this batch file:

if exist dwtoa.obj del dwtoa.obj

\masm32\bin\ml /c /coff dwtoa.asm

pause

Set PATH=C:\Program Files\Microsoft Visual C++ Toolkit 2003\bin;%PATH%
Set INCLUDE=C:\Program Files\Microsoft SDK\include;%INCLUDE%
Set LIB=C:\Program Files\Microsoft SDK\lib;%LIB%

cl test.c dwtoa.obj

pause


And there were no error messages from the assembler, compiler, or linker, and the EXE ran OK.

Note that the calling conventions used by the called procedure and the caller must match. In this case I left dwtoa.asm as is, and as you can see the STDCALL calling convention is specified as the default in the .MODEL directive. Because of this I had to specify that dwtoa used the STDCALL calling convention in the C source. This effectively told the compiler that the name in the object module was _dwtoa@8 and that it should not remove the parameters from the stack after the call returns (in the STDCALL calling convention the called procedure is responsible for doing this). I think it would probably be more normal to use the C calling convention for a procedure that will be called from C. This could be done simply by changing the procedure definition to this:

dwtoa proc C dwValue:DWORD, lpBuffer:DWORD

Where the "C" langtype argument would override the default calling convention, forcing the use of the C calling convention. This would cause ML to use a RET instruction that does not remove the parameters from the stack (in the C calling convention the caller is responsible for doing this) and to use the name _dwtoa in the object module. The _stdcall could then be removed from the function prototype:

void dwtoa( int dwValue, char *lpBuffer );

Which would cause CL to use the C calling convention, so the procedure name and the method of removing the parameters from the stack in the C module would match those in the ASM module.
eschew obfuscation

psault

I spent some time trying to duplicate MichaelW's results by linking some C++ code to an .OBJ from assembler source.  I was unable to get them to link.  I discovered that the procedure does work so long as I am compiling C code instead of C++ code.  I used my own files, so I got this specific error: 'testlink.obj : error LNK2019: unresolved external symbol "void __stdcall start(void)" (?start@@YGXXZ) referenced in function _main' 

I'm guessing that there might be an easy fix to this.  Can anyone tell how to link C++ code?

~psault


MichaelW

In a C++ source I think you would need to declare the ASM procedure (that uses the C calling convention) in an extern "C" block.

http://msdn.microsoft.com/en-us/library/0603949d(VS.71).aspx
eschew obfuscation

GregL

psault,

Decorated names are different for C and C++. MASM uses C style decorated names.

    Format of a C Decorated Name
    Format of a C++ Decorated Name

Like Michael said, you would need to use extern "C" void __stdcall start(void); in your C++ code to specify that the MASM .obj file has C style decorated names.



psault

Thanks, yes... the extern "C" does the trick.
And "decorated names" sounds so much friendlier than "name mangling" as one of my C++ books refers to it!

~psault

zoncpp

but my VC++ project has this error :
fatal error LNK1104: cannot open file "\masm32\lib\masm32.lib"

MichaelW

If the VC++ linker cannot open "\masm32\lib\masm32.lib", then I would guess that MASM32 is not installed on the same drive as VC++. You could try specifying the full path, including the drive.
eschew obfuscation

zoncpp

i created myFile.lib with this code:
\masm32\bin\ml /c /coff myFile.asm
\masm32\bin\lib myFile.obj /out:myFile.lib


and i used this lib file in my VC project. :U