Compile Assembly Output generated by VC++?
Asked Answered
P

2

7

I have a simple hello world C program and compile it with /FA. As a consequence, the compiler also generates the corresponding assembly listing. Now I want to use masm/link to assemble an executable from the generated .asm listing.

The following command line yields 3 linker errors:

\masm32\bin\ml /I"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include" /c /coff asm_test.asm
\masm32\bin\link /SUBSYSTEM:CONSOLE /LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\lib" asm_test.obj

indicating that the C-runtime functions were not linked to the object files produced earlier:

asm_test.obj : error LNK2001: unresolved external symbol @__security_check_cookie@4 asm_test.obj : error LNK2001: unresolved external symbol _printf LINK : error LNK2001: unresolved external symbol _wmainCRTStartup asm_test.exe : fatal error LNK1120: 3 unresolved externals

Here is the generated assembly listing

; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01 

    TITLE   c:\asm_test\asm_test\asm_test.cpp
    .686P
    .XMM
    include listing.inc
    .model  flat

INCLUDELIB OLDNAMES

PUBLIC  ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@   ; `string'
EXTRN   @__security_check_cookie@4:PROC
EXTRN   _printf:PROC
;   COMDAT ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@
CONST   SEGMENT
??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@ DB 'hello world!', 0aH, 00H ; `string'
CONST   ENDS
PUBLIC  _wmain
; Function compile flags: /Ogtpy
;   COMDAT _wmain
_TEXT   SEGMENT
_argc$ = 8                      ; size = 4
_argv$ = 12                     ; size = 4
_wmain  PROC                        ; COMDAT
; File c:\users\octon\desktop\asm_test\asm_test\asm_test.cpp
; Line 21
    push    OFFSET ??_C@_0O@OBPALAEI@hello?5world?$CB?6?$AA@
    call    _printf
    add esp, 4
; Line 22
    xor eax, eax
; Line 23
    ret 0
_wmain  ENDP
_TEXT   ENDS
END

I am using the latest masm32 version (6.14.8444).

Update:

As suggested by Cogwheel, I included an INCLUDELIB msvcrt.lib in the asm source. The program compiles and an executable is created, but the linker generates a warning:

msvcrt.lib(crtmanifestrtm.obj) : warning LNK4044: unrecognized option "manifestdependency:type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'"; ignored

When i start the executable, the C runtime generates the following error:

Runtime error: R6034 An application has made an attempt to load the C runtime library incorrectly

Phenice answered 12/5, 2010 at 1:35 Comment(2)
You've provided the path to the libraries but you didn't list any of the libraries themselves that you want to link to. I'm not sure the name of the libraries you would need to link to though (hence the comment instead of an answer).Indurate
Well, it certainly has something to do with the manifest files, but I'm pretty well stumped at this point. Maybe create a simple plain C++ project and look through the linker settings for clues?Indurate
A
2

I did this recently. It turns out you can still do this in 32-bit mode in MSVC2012 but I think 64-bit mode is hopeless.

For 32-bit mode here is what you do.

Create an empty project and a source file Source.cpp

 #include <stdio.h>
 int main() {
     printf("hello world\n");
     return 0;
 }
  1. Right lick on your project and select "Build Customization" and
    select masm as described here http://www.masm32.com/board/index.php?topic=9231.0
  2. Under C++/OutputFiles select Assembly Output /FA
  3. Comipile in 32-bit mode Release mode
  4. Load the Source.asm file into MSVC so you can view it. It won't work yet. A few changes are necessary.
  5. Under C++/Optimization turn off Whole Program Optimization (removes /GL). This adds the line INCLUDELIB MSVCRT
  6. In the Linker/Advanced set the last option "Image Has Safe Exception Handlers"to No (/SAFESEH:NO)
  7. Now you should have a Source.asm file which will do the same thing that Source.cpp file did. Copy the Source.cpp from the Release directory to the same directory as Source.cpp (so it's not deleted when you build/clean).
  8. Add Source.asm (as an existing file) to the Source Files and remove Source.cpp from the build.
  9. Rebuild and you should see "Hello World" without having to change any assembly lines by hand.

I have used this for more complicated functions. I usually do it on a separate module and use extern "C" on the function name to remove the C++ name mangling.

Anitaanitra answered 18/1, 2014 at 12:45 Comment(0)
S
0

Remove listing.inc Remove security_check_cookie reference add INCLUDELIB MSVCRT ...et Robert est ton oncle!

Also you can add: EXTERN _getchar:PROC and just before ret: call _getchar This will wait for a key press before the program closes.

Honkjonk.

Somnolent answered 21/4, 2013 at 8:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.