Introduction
Most programmers shy away from Assembler (or assembly language). People tend to consider it as a very difficult language to understand and use. Moreover, anyone who knows how to use it is tended to be regarded with some reverence by other programmers in his community.
This tutorial is the first in a series that will attempt to dismiss these misgivings about Assembler and demonstrate that, in actual fact, it’s not difficult to use; quite the contrary. It will demonstrate the tools that greatly simplify the authoring of Assembler, and show you how to integrate these with Visual Studio.
First, what is Assembler? Put quite simply, it’s the language of the processor. You can’t get any lower level than this (except for possibly the actual byte values of the instructions). Every command (mov, add, and so forth) is translated by an Assembler program directly into a number that, in turn, is fed to the processor on execution.
The advantage of using Assembler over other languages is speed. Sheer, raw, unmitigated speed. Even with the modern compiler’s ability to optimise code, the code that it produces would have trouble competing with the same written and optimised by hand in Assembler.
Now, Assembler isn’t for every job. It is possible to write whole applications in Assembler, but with C++ and the other high languages available today, it’d be masachistic to do so. For the vast majority of applications, the speed of C++ and even the .NET languages is quite acceptible.
Where Assembler comes into its own is when speed is essential; for instance, in graphics applications. For writing small, incredibly fast functions addressing large blocks of memory, Assembler can’t be beaten. Bitmap manipulation is a typical example of where a knowledge of how to use Assembler can reap huge rewards.
So, now that I’ve covered what Assembler is and what its advantages are, how do you use it?
Writing Assembler in Visual C++
The first way that you can write Assembler in C++ is by using __asm blocks:
DWORD Function(DWORD dwValue) { __asm { mov eax, dwValue add eax, 100 mov dwValue, eax } return dwValue; }
Here, you can see a few Assembler instructions enclosed in an __asm block. The C++ compiler will translate these directly into their machine language codes.
Don’t worry about what it means. Just know that ‘add’ is an add instruction and ‘mov’ is a move instruction that moves values about. The code above just adds 100 to the value passed in.
So, that’s it, you might have thought. Well, you’d be wrong. Writing code in __asm blocks is all right for small chunks of Assembler, but if you want to write any functions of length, it starts to become somewhat tedious. For, instance an ‘if..else’ statement would look something like this:
DWORD Function2(DWORD dwValue1, DWORD dwValue2) { DWORD dwValue3 = 0; #if 0 // this is the Assembler if (dwValue1 == dwValue2) { dwValue3 = 1; } else { dwValue3 = 2; } #endif __asm { mov eax, dwValue1 ; this is the test of the values, i.e. if dwValue1 == dwValue2 cmp eax, dwValue2 ; jump to 'Else' if they are not equal jne Else mov eax, 1 jmp EndIf Else: mov eax, 2 EndIf: mov dwValue3, eax } return dwValue3; }
Again, don’t worry too much about the actual instructions, but can you imagine having to do something like this for every if statement?
Using __asm code blocks is like writing C++ using Notepad and the command prompt. Yes, you can do it, but it is a lot more time-consuming than using a dedicated tool for the job.
So, what dedicated tools are there? Well, there’s the Microsoft Macro Assembler. Yes, you did hear right. Microsoft has an Assembler. In fact, they’ve had an Assembler since 1980; it’s just that not many people know about it. And what’s more, it’s freeware. And, even better, it’ll produce .obj files that are compatible with the Visual C++ linker. It’ll even produce .obj files containing debug information so you can step through your code.
It’s called MASM32 and is available at http://www.masm32.com/.
I strongly recommend that you download and install it now before proceeding.
So, what’s so good about it?
First, it comes with an extensive set of help files available in the msasm32help directory.
Second, it has macros defined for just about every single job you might want to do. Not only that, but if you use the macros, you know you’ll always be using the most efficient method of performing each task.
For example, look at the preceding code written using MASM:
Function proc dwValue1:DWORD, dwValue2:DWORD mov eax, dwValue1 .if eax == dwValue2 mov eax, 1 .else mov eax, 2 .endif ret Function endp
I think that you’ll agree that this is a lot more readable.
So, now that you’ve downloaded and installed the assembler, I’ll take you through a step-by-step guide of adding an Assembler file to an existing C++ project, what to enter into the project settings to compile it, and how to access functions written in Assembler in C++.