====== Programming in Assembler for x64 ====== In this section, we will show some examples of programs written purely in assembler or in connection with other programming languages, including C++ and C#. We assume that the reader is familiar with the coursebook, instructions and directives used to write the assembler programs. We will describe the use of the integrated development environment (Visual Studio) and methods to assemble programs with the command line only.We will also show how to create the static and dynamic library written in assembler for use in assembler or in other compilers. ===== Introduction to the x64 Assembler programming in MASM - Microsoft Visual Studio Community Edition ===== In the following chapter, we explain how to write, assemble, link, and execute assembly-language programs for x64 processors. We assume that the reader is familiar with the most important processor instructions and MASM directives. To write a program in assembler, it is convenient to use a Visual Studio IDE: either commercial or free (Community Edition). The following section presents the installation of Visual Studio Community Edition on Windows. Visual Studio Community, Professional, and Enterprise are other products than Visual Studio Code. Here, we do not use Visual Studio Code! ==== Installing VS Community ==== Installation requires the following simple steps: - Download installer executable from: [[https://visualstudio.microsoft.com/free-developer-offers/]] - **Mind to choose Community Edition (purple), not Code (blue)!** as in figure {{ref>vscommunityinstall1}}. - Run the installer, let it download and install. - Configure components - a minimal set of development platforms for our laboratory exercises requires: - full install of C++ development platform in native code for Windows (remember to click additional components as in the figure {{ref>vscommunityinstall2}}), - default install of the C# development platform in managed code for Windows.
caption
{{:en:multiasm:exercisesbook:virtualbox_windows_10_edu_assembler_09_05_2026_14_11_34.png?400|}} caption
This scenario concerns the implementation of a command-line Windows x64 application written in pure Assembler. Assembling, debugging, disassembly window, register view, memory view - data section, TO BE DONE ===== Visual Studio Community solution with static assembly library for C++ ===== In this section, we'll go through the process of creating a solution with a C++ main file and a static assembler library.\\ **1.** Create the solution. You can create a simple "Hello world" example written in C++ for execution in a console window.\\
{{:en:multiasm:exercisebook:pc:create_sln.png?400|Creating new solution in Visual Studio 2026. Step 1 - Click the option "Create a new project".}} Creating new VS2026 solution
{{:en:multiasm:exercisebook:pc:console_app.png?400|Creating new solution in Visual Studio 2026. Step 2 - Choose the option "Console App" and click "Next".}} Choosing solution type of VS2026 solution
{{:en:multiasm:exercisebook:pc:namee_app.png?400|Creating new solution in Visual Studio 2026. Step 3 - Set the name of a solution and click "Create".}} Setting the VS2026 solution name
At this stage, you can test the application. It should print "Hello World" in a console window. **2.** Add assembler module with library functions.
{{:en:multiasm:exercisebook:pc:add_prj.png?400|Adding the assembler project to the solution. Step 1. Right-click the solution and choose the option "Add" and "New Project".}} Adding the assembler project to VS2026 solution
This time, choose the Empty Project option.
{{:en:multiasm:exercisebook:pc:create_asm.png?400|Adding the assembler project to the solution. Step 2. Choose the option "Empty project" and click "Next".}} Adding the empty project to VS2026 solution
{{:en:multiasm:exercisebook:pc:name_asm.png?400|Adding the assmebler project to the solution. Step 3. Name the project, e.g., "Library1" and click "Create".}} Naming the empty project
We need to enable MASM in build customisations.
{{:en:multiasm:exercisebook:pc:build_customisation.png?400|Adding the assembler project to the solution. Step 4. Customise build options to add MASM. Right-click project name and click "Build customisations".}} Customise the build to enable MASM
{{:en:multiasm:exercisebook:pc:masm_customisation.png?400|Adding the assmebler project to the solution. Step 5. Toggle "masm" option on and click "OK".}} Enabling MASM
Add an assembly file to the MASM project. You can add a new item of a type of plain text, and name it with an asm extension. For example "library1.asm".
{{:en:multiasm:exercisebook:pc:add_asm_item.png?400|Adding the assmebler project to the solution. Step 6. Right click "Source files" in a project tree in "Solution Explorer", choose "add" and click "New Item".}} Adding MASM file to a project
{{:en:multiasm:exercisebook:pc:name_asm_file.png?400|Adding the assembler project to the solution. Step 7. Choose the file type "Utility" and "Text File". Name the file, e.g., "library1.asm". Confirm with the "Add" button.}} Adding MASM file to a project
**3.** Set the output file type for the assembler project.\\ The project build generates the exe file by default. We need to change the configuration type to static library (*.lib file).
{{:en:multiasm:exercisebook:pc:select_lib_properties.png?400|Setting the output file type for assembler projet. Step 1. Right-click the project name in the "Solution Explorer" and click the "Properties" option.}} Selecting properties for a assembler project
{{:en:multiasm:exercisebook:pc:select_lib_type.png?400|Setting the output file type for assembler projet. Step 2. Modify the "Configuration Type" to "Static library" and click "OK".}} Selecting properties for a assembler project
**4.** Set references and dependencies between solution modules.\\ The C++ program relies on an assembler library, so the references and dependencies should be properly set. First, add the reference to a library.
{{:en:multiasm:exercisebook:pc:add_reference.png?400|Setting the dependencies in a solution. Step 1. Right-click the C++ project name in the "Solution Explorer", choose "Add", and click the "References" option.}} Adding reference to a assembler library for a C++ project
{{:en:multiasm:exercisebook:pc:set_reference.png?400|Setting the dependencies in a solution. Step 2. In an "Add reference" window, mark the library name and click the "OK" button.}} Setting reference to a assembler library for a C++ project
Next, check if dependencies between both modules are properly set.
{{:en:multiasm:exercisebook:pc:select_dependencies.png?400|Setting the dependencies in a solution. Step 3. Right-click the solution name in the "Solution Explorer" and click the "Project Build Dependencies" option.}} Selecting build dependencies for a solution
{{:en:multiasm:exercisebook:pc:set_dependencies.png?400|Setting the dependencies in a solution. Step 4. Choose the C++ project name in the "Projects" drop-down list and select the assembler library project name in the "Depends on:" box. Click "OK".}} Setting build dependencies for a C++ project and assembler library
**5.** Write the software.\\ It's time for coding. Let's start with the code of a library function. Let's write a simple function adding two arguments. According to Windows ABI, the first two arguments are passed by **rcx** and **rdx** registers. The return value should be stored in **rax**. We will use the **int** C++ data type, which is stored using 32 bits. We should make calculations with 32-bit registers **ecx**, **edx**, and **eax**. The assembler file can look like the following code. .CODE func_add PROC mov eax, ecx add eax, edx ret func_add ENDP END We will expand the default "Hello world" C++ file with our assembler function call. #include #include "Assembler1.h" int main() { std::cout << "Hello World!\n"; std::cout << func_add(123, 456); } Calling a library function requires a prototype. We will declare it in the header file, which we need to add to the C++ project. It can be named "Assembler1.h". #pragma once extern "C" int func_add(int a, int b); After finishing all the steps, we should be able to properly compile the solution and observe results in a console window. ===== Dynamic lib in C++ ===== ===== Dynamic lib in C# ===== ===== Standalone assembly ===== It is possible to use command-line MASM tools to assemble, link, and create libraries written in assembly language. You can use any editor to create the assembler source code and translate it into machine code. The tools required are integral elements of the Visual Studio Community installation, installed with the option "Desktop development with C++". For the default VS installation, you can find them in the following folder (it can change due to different version numbers). C:\Program Files\Microsoft Visual Studio\18\Community\VS\Tools\MSVC\14.50.35717\bin\Hostx64\x64 To use statically included Windows libraries, you need lib files. The essential library is kernel32.lib, but for other Windows functions, you will also need some additional libraries. All are available in the following folder (it can change due to different version numbers). C:\Program FIles (x86)\Windows Kits\10\Lib\10.0.26100.0\um\x64 For assembling the source file, the ML64.exe program is used. This program has many options, which you can see executing: ML64.exe /? After assembling, ML64 can call the linker automatically. An exemplary MASM execution command to assemble and link the file named source.asm can look like this: ml64 /Fl /Zi /Zd source.asm /link /entry:main The options used explanation: * /Fl - generate listing file. MASM will output the source.lst file with the report on the assembling process. * /Zi - add symbolic debug info. MASM will add to the object file names of symbols defined in the program. It will allow debuggers to name user-defined symbols during debugging. * /Zd - add line number debug info. MASM will add to the object file source code line numbers. * /link - MASM will call the linker. * /entry:main - option for the linker, which informs about the entry point of the program. If you prefer another name than "main" as the entry point for your console program, you will need to specify the type of the system for the resulting code. For a console application, you need to add /SUBSYSTEM:CONSOLE. The easiest way is to put all required files in the same folder on the disk. This is not the case for more complex projects, so file names should be preceded by their full paths.