This section guides you through setting up VC++ to work with assembly. You'll create a workspace and project. You'll add a .asm and .mak file to the project. When you've completed this section you'll be ready to compile an assembly program.
Start by opening Visual C++. Use FILE->NEW to create a new blank project called 'helloworld'. (see figure 1)
Now we'll add a make file project to this workspace. When the new workspace is open, right click it in the file view and select "Add New Project To Workspace..." (see figure 2)
Choose "Makefile" and set the name to "helloworld". Use the same directory as for your workspace. If your skilled in VC++ do what you want. Change the radio buttons to read "Add to current workspace..." (see figure 3). Accept the defaults on the wizard that follows.
Before we go any further you'll need to have a sample assembly program file and a make file for your project. Code listings and links follow. Save these files to you Workspace/Project folder.
; This is a very simple 32 bit assembly program ; that uses the Win32 API to display hello world on the ; console. TITLE Hello World in Win32 ASM (helloworld.asm) .386 .MODEL flat, stdcall .STACK 4096 ; ---------------------------------------------------------------------------- ; These are prototypes for functions that we use ; from the Microsoft library Kernel32.lib. ; ---------------------------------------------------------------------------- ; Win32 Console handle STD_OUTPUT_HANDLE EQU -11 ; predefined Win API constant (magic) GetStdHandle PROTO, ; get standard handle nStdHandle:DWORD ; type of console handle WriteConsole EQU <WriteConsoleA> ; alias WriteConsole PROTO, ; write a buffer to the console handle:DWORD, ; output handle lpBuffer:PTR BYTE, ; pointer to buffer nNumberOfBytesToWrite:DWORD, ; size of buffer lpNumberOfBytesWritten:PTR DWORD, ; num bytes written lpReserved:DWORD ; (not used) ExitProcess PROTO, ; exit program dwExitCode:DWORD ; return code ; ---------------------------------------------------------------------------- ; ---------------------------------------------------------------------------- ; global data ; ---------------------------------------------------------------------------- .data consoleOutHandle dd ? ; DWORD: handle to standard output device bytesWritten dd ? ; DWORD: number of bytes written message db "Hello World",13,10,0 ; BYTE: string, with \r, \n, \0 at the end ; ---------------------------------------------------------------------------- .code ; ---------------------------------------------------------------------------- procStrLength PROC USES edi, ptrString:PTR BYTE ; pointer to string ; ; walk the null terminated string at ptrString ; incrementing eax. The value in eax is the string length ; ; parameters: ptrString - a string pointer ; returns: EAX = length of string prtString ; ---------------------------------------------------------------------------- mov edi,ptrString mov eax,0 ; character count L1: ; loop cmp byte ptr [edi],0 ; found the null end of string? je L2 ; yes: jump to L2 and return inc edi ; no: increment to next byte inc eax ; increment counter jmp L1 ; next iteration of loop L2: ret ; jump here to return procStrLength ENDP ; ---------------------------------------------------------------------------- ; ---------------------------------------------------------------------------- procWriteString proc ; ; Writes a null-terminated string pointed to by EDX to standard ; output using windows calls. ; ---------------------------------------------------------------------------- pushad INVOKE procStrLength,edx ; return length of string in EAX cld ; clear the direction flag ; must do this before WriteConsole INVOKE WriteConsole, consoleOutHandle, ; console output handle edx, ; points to string eax, ; string length offset bytesWritten, ; returns number of bytes written 0 popad ret procWriteString endp ; ---------------------------------------------------------------------------- ; ---------------------------------------------------------------------------- main PROC ; ; Main procedure. Just initializes stdout, dumps the string, and exits. ; ---------------------------------------------------------------------------- INVOKE GetStdHandle, STD_OUTPUT_HANDLE ; use Win32 to put ; stdout handle in EAX mov [consoleOutHandle],eax ; Put the address of the handle in ; our variable mov edx,offset message ; load the address of the message ; into edx for procWriteString INVOKE procWriteString ; invoke our write string method. ; It'll check EDX INVOKE ExitProcess,0 ; Windows method to quit main ENDP ; ---------------------------------------------------------------------------- END main |
# A very simple make file for a windows 32 bit assembly console program # it assembles and links # nmake help is online at: # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcug98/html/_asug_macros_and_nmake.asp # Assemble the code into coff format producing map and listing files, # including symbolic debugging info. Try "ml /?" for more options # and descriptions # 32 bit link our .obj file with the kernel32.lib file and create an exe file all: helloworld.exe helloworld.exe: helloworld.asm ml /nologo /coff /c /Zi /Fl /Fm $? link32 /nologo /DEBUG /incremental:no /subsystem:console /entry:main /out:debug\helloworld.exe helloworld.obj kernel32.lib |
The next step is to add downloaded files to the project. You'll add our helloworld.asm assembly program. You'll also add an nmake makefile, which is similar so gmake. Right click your project and click "add files.." (see figure 4)
Change the file type to "All files" and select helloworld.asm and helloworld.mak (see figure 5).
Now your workspace should look something like figure 6.
Our final step before we compile is to add paths for executable, library, and include files. This is accomplished via (TOOLS->OPTIONS- >DIRECTORIES). First add the C:\MASM615 path to the executable list (figure 7). Then add C:\MASM615\INCLUDE to the include path (figure 8). Finally add C:\MASM615\LIB to the library path (figure 9). We won't use the include path for this program, but still set it up while we are there.
Great! You've successfully established a framework in which to compile and debug your assembly programs. Now we'll continue to the next section to discuss compilation.