How do you compile assembly code using Visual Studio?
I want to compile and run an assembly source file in Visual Studio 2010.
I've created a Visual C++ project and inserted some assembly code in a file code.asm:
.586 ;Target processor. Use instructions for Pentium class machines
.MODEL FLAT, C ;Use the flat memory model. Use C calling conventions
.STACK ;Define a stack segment of 1KB (Not required for this example)
.DATA ;Create a near data segment. Local variables are declared after
;this directive (Not required for this example)
.CODE ;Indicates the start of a code segment.
clear PROC
xor eax, eax
xor ebx, ebx
ret
clear ENDP
END
However the problem is when you try and compile this, you get:
LINK : error LNK2001: unresolved external symbol _mainCRTStartup
I did go and enable the build customization masm.targets (right click project > Build Customizations..), but to no avail.
Sounds to me like the custom build rules for .asm files isn't enabled. Right-click the project, Custom Build Rules, tick "Microsoft Macro Assembler". With the "END clear" directive and disabling incremental linking I'm getting a clean build.
It's different starting from VS2010:
Right-click Project, Build customizations, tick "masm".
Right-click the .asm file, Properties, change Item Type to "Microsoft Macro Assembler".
Command line:
Compile the code with:
ml /c /Cx /coff code.asm
You get code.obj as the output.
Link with:
link code.obj /SUBSYSTEM:console /out:go.exe /entry:clear
You can now run go.exe.
Alternatively, do it all in one go with:
ml /Cx /coff code.asm /link /SUBSYSTEM:console /link /entry:clear
Visual Studio (not solved)
Visual Studio includes the MASM macro assembler. Smaller fragments of assembler code are often written in inline assembly in a C or C++ program.
To integrate an assembler file in a Visual Studio project, create a regular C/C++ project (command line or GUI), and just add a file ending in .asm to the list of source files.
To specify clear as the entry point, follow these instructions:
Open the project's Property Pages
dialog box. For details, see Setting
Visual C++ Project Properties.
Click the Linker folder.
Click the Advanced property page.
Modify the Entry Point property.
(It was taken from the Visual Studio documentation.)
I can confirm Hans Passant's instruction. In addition, according to this article, if you first add the "build customizations" masm checkbox, and then add the file, it will automatically be recognized as an assembler file. Furthermore, not specifying the entry point name in the END directive, but instead specifying it in the project settings also works for me.
here is how to compile nasm assembly source code with vs20xx:
"Excluded From Build" to "No"
"Item Type" to "Custom Build Tool"
Hit Apply
Custom Build Tool -> General -> Command Line:
c:\nasm\nasm -f win64 my_asm.asm
Custom Build Tool -> General -> Outputs:
my_asm.obj
call the function like this:
extern "C" int foo(void); // written in assembly!
https://www.cs.uaf.edu/2017/fall/cs301/reference/nasm_vs/
nasm tutorial:
http://cs.lmu.edu/~ray/notes/nasmtutorial/
The problem is that your assembly code is just a function. To compile and link, you need to have a start procedure just like Main in C/C++. You can specify the start symbol by specifying in your END directive. Like:
END clear
Or if you want, you can link the .obj file generated with the C/C++ generated .obj one.
Related
Why do I have to set a source .asm file's Properties > General > Item Type to Microsoft Macro Assembler, even though I had already selected for the project node, the option Build dependencies > Build Customization > masm.
It may depend on which version of Visual Studio you are using, but I recall what seemed like a one time option to auto-select masm for .asm file with one of the versions. After dealing with multiple versions of Visual Studio and having issues with some versions, I manually set the properties for each .asm file to use a custom build tool (also turn off does not participate in build as commented by John Kalane), which is working for all the versions I have (VS2005, VS2010, VS2015, VS2019).
32 bit debug build, for release build /Zi is not needed:
command line: ml /c /Zi /Fo$(OutDir)\example.obj example.asm
outputs: $(OutDir)\example.obj
64 bit debug build, for release build /Zi is not needed:
command line: ml64 /c /Zi /Fo$(OutDir)\example.obj example.asm
outputs: $(OutDir)\example.obj
I'm working on a cross-platform project which has some hand-written assembly to optimize performance for various CPU architectures. I'm converting this project to CMake from a proprietary build system, starting with compiling using Visual Studio on Windows. For x86 and AMD64, I've been able to assemble and link everything just fine, but I can't get it to work on ARM64 (or presumably ARM32, though I haven't tried that yet).
I'm including the ASM files in my sources as follows:
if(CMAKE_SYSTEM_PROCESSOR MATCHES "AMD64")
list(APPEND SOURCES
amd64/aesasm.asm
...)
set_source_files_properties(
amd64/aesasm.asm
...
PROPERTY LANGUAGE ASM_MASM)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "X86")
# ...
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
list(APPEND SOURCES
arm64/fdef_asm.asm
...)
set_source_files_properties(
arm64/fdef_asm.asm
...
PROPERTY LANGUAGE ASM_MASM)
Then in my top-level CMakeLists.txt, I enable MASM using enable_language(ASM_MASM). For x86 and AMD64, CMake automatically finds ml/ml64.exe, configures the Visual Studio project correctly, and everything works.
But for ARM64, if I try the same thing, I get this error from Visual Studio when trying to build: MSB3721: The command "echo MASM not supported on this platform. As far as I can tell, this is because Visual Studio considers ARM assembly to be a different dialect, "MARMASM", with a different executable name for the assembler (armasm/armasm64.exe).
I tried setting enable_language(ASM_MARMASM) in my ARM64 toolchain file, but CMake does not recognize this as an ASM dialect, and gives me this error:
CMake Error: Could not find cmake module file: CMakeDetermineASM_MARMASMCompiler.cmake
CMake Error: Could not find cmake module file: F:/os/src/symcrypt/bin/CMakeFiles/3.15.3/CMakeASM_MARMASMCompiler.cmake
CMake Error at CMakeLists.txt:49 (enable_language):
No CMAKE_ASM_MARMASM_COMPILER could be found.
I also tried manually setting the assembler:
get_filename_component(VS_TOOLS_DIRECTORY ${CMAKE_LINKER} DIRECTORY)
find_file(ARM64_COMPILER "armasm64.exe" HINTS ${VS_TOOLS_DIRECTORY})
set(CMAKE_ASM_MARMASM_COMPILER ${ARM64_COMPILER})
enable_language(ASM_MARMASM)
message(STATUS "Manually set assembler to ${CMAKE_ASM_MARMASM_COMPILER}")
But this does not work either; I still get an error that No CMAKE_ASM_MARMASM_COMPILER could be found.
How can I include ARM/ARM64 assembly in my project?
Looks like CMake (still) does not have support for this. I found some bits in the .NET source code to work around it:
https://github.com/dotnet/runtime/blob/f8f63b1fde85119c925313caa475d9936297b463/eng/native/functions.cmake#L173-L207
and
https://github.com/dotnet/runtime/blob/f8f63b1fde85119c925313caa475d9936297b463/eng/native/configurecompiler.cmake#L611-L626
edit: As reference, here's the commit for a project I had this requirement for: https://dyncall.org/pub/dyncall/dyncall/rev/451299d50c1a
I wrote a simple program in assembly language which will simply display a message box in windows 7 32 bit
.386
.model flat, stdcall
option casemap :none
extrn MessageBoxA#16 : PROC
extrn ExitProcess#4 : PROC
.data
HelloWorld db "Welcome to SecurityTube.net!", 0
MsgTitle db "First MessageBox", 0
.code
start:
mov eax, 0
push eax
lea ebx, MsgTitle
push ebx
lea ebx, HelloWorld
push ebx
push eax
call MessageBoxA#16
push eax
call ExitProcess#4
end start
I use following command for assembling and linking
ml /c /coff helloworld.asm
link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib helloworld.obj
Program assembled perfectly. However, while linking, i got this error:
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
LINK : fatal error LNK1104: cannot open file "kernel32.lib"
Why i am getting this error and how to mitigate it?
The command you're looking for is:
ml.exe helloworld.asm
/coff
/link
/subsystem:windows
/defaultlib:kernel32.lib
/defaultlib:user32.lib
/libpath:C:\...somewhere...
helloworld.obj
Note that instead of running ml first with the /c switch (which assembles only without linking), and then running link, I've just combined it all into a single command line. This will run MASM to assemble the code, and then immediately link it.
The magic sauce is the /link switch, which passes every argument that comes after it to the linker.
Notice the other new switch that you did not have: /libpath. This is the one that tells the linker where the LIB files can be found. They are part of the Windows SDK, so you'll need to locate that directory on your hard disk and substitute that path for C:\...somewhere.... The exact location differs depending on which version of the SDK you have installed and how you installed it (separately, or as part of Visual Studio). If you don't have the SDK, download it here for Windows 10, or for earlier versions. (Note that the latest version is sufficient; you do not need to download every version. It supports multi-targeting.)
The documentation for MASM is all available online, including a comprehensive listing of command line options. Same thing for the linker; its options are here.
An even easier solution would be to open the Visual Studio Command Prompt and do all of your assembling and linking from there. This actually runs a batch file that sets up the environment for you so that you don't have to worry about specifying the path to all of the required SDK files (headers, libraries, etc.). You'll find this in your Start menu, or manually run:
C:\Program Files (x86)\Microsoft Visual Studio x.x\VC\bin\vcvars32.bat
to set up a 32-bit build environment.
Did you check Visual Studio's directory structure and look for $(WindowsSdkDir)\lib to see if they exist?
If not install http://msdn.microsoft.com/en-us/windows/desktop/bg162891.aspx
When creating a new C-Win32 project in Mingw (gcc) I accidentally added a cpp file as one source file to the other C files.
Now Mingw compiles my c code as c++. I found out by testing that __cplusplus returns true.
I've looked all the project settings in my Codeblock IDE and compared then to other projects that compile as C.
How do I tell Codeblocks/Mingw/GCC to compile it as C source and turn off __cplusplus?
First change the file's extension from .cpp to .c. To do this:
Close file.cpp in the Code::Blocks editor, if it is open.
Right click on file.cpp in the projectname -> Sources
tree-view.
From the menu select Rename file... and name it file.c
That should be a sufficient hint to Code::Blocks that you want the
file compiled with the C compiler and not the C++ compiler, but it isn't.
When you add file.cpp to a project, C::B registers it for compiling
with the C++ compiler and it sticks to that even if you rename the file
to file.c.
To make it change its mind you must also do this:
After renaming the file to file.c, once again right-click on it in the project tree-view
and this time choose Properties...
In the Properties dialog, click the Advanced tab.
Change the value of Compiler variable from CPP to CC, then OK out.
Now the file will be compiled with the C compiler.
How do you compile assembly code using Visual Studio?
I want to compile and run an assembly source file in Visual Studio 2010.
I've created a Visual C++ project and inserted some assembly code in a file code.asm:
.586 ;Target processor. Use instructions for Pentium class machines
.MODEL FLAT, C ;Use the flat memory model. Use C calling conventions
.STACK ;Define a stack segment of 1KB (Not required for this example)
.DATA ;Create a near data segment. Local variables are declared after
;this directive (Not required for this example)
.CODE ;Indicates the start of a code segment.
clear PROC
xor eax, eax
xor ebx, ebx
ret
clear ENDP
END
However the problem is when you try and compile this, you get:
LINK : error LNK2001: unresolved external symbol _mainCRTStartup
I did go and enable the build customization masm.targets (right click project > Build Customizations..), but to no avail.
Sounds to me like the custom build rules for .asm files isn't enabled. Right-click the project, Custom Build Rules, tick "Microsoft Macro Assembler". With the "END clear" directive and disabling incremental linking I'm getting a clean build.
It's different starting from VS2010:
Right-click Project, Build customizations, tick "masm".
Right-click the .asm file, Properties, change Item Type to "Microsoft Macro Assembler".
Command line:
Compile the code with:
ml /c /Cx /coff code.asm
You get code.obj as the output.
Link with:
link code.obj /SUBSYSTEM:console /out:go.exe /entry:clear
You can now run go.exe.
Alternatively, do it all in one go with:
ml /Cx /coff code.asm /link /SUBSYSTEM:console /link /entry:clear
Visual Studio (not solved)
Visual Studio includes the MASM macro assembler. Smaller fragments of assembler code are often written in inline assembly in a C or C++ program.
To integrate an assembler file in a Visual Studio project, create a regular C/C++ project (command line or GUI), and just add a file ending in .asm to the list of source files.
To specify clear as the entry point, follow these instructions:
Open the project's Property Pages
dialog box. For details, see Setting
Visual C++ Project Properties.
Click the Linker folder.
Click the Advanced property page.
Modify the Entry Point property.
(It was taken from the Visual Studio documentation.)
I can confirm Hans Passant's instruction. In addition, according to this article, if you first add the "build customizations" masm checkbox, and then add the file, it will automatically be recognized as an assembler file. Furthermore, not specifying the entry point name in the END directive, but instead specifying it in the project settings also works for me.
here is how to compile nasm assembly source code with vs20xx:
"Excluded From Build" to "No"
"Item Type" to "Custom Build Tool"
Hit Apply
Custom Build Tool -> General -> Command Line:
c:\nasm\nasm -f win64 my_asm.asm
Custom Build Tool -> General -> Outputs:
my_asm.obj
call the function like this:
extern "C" int foo(void); // written in assembly!
https://www.cs.uaf.edu/2017/fall/cs301/reference/nasm_vs/
nasm tutorial:
http://cs.lmu.edu/~ray/notes/nasmtutorial/
The problem is that your assembly code is just a function. To compile and link, you need to have a start procedure just like Main in C/C++. You can specify the start symbol by specifying in your END directive. Like:
END clear
Or if you want, you can link the .obj file generated with the C/C++ generated .obj one.