The Assembly Programming Master Book

In this chapter, I provide a brief introduction to Assembly language programming tools. This chapter is intended for beginners ; therefore, experienced programmers can skip it.

First, note that the title of this chapter is deceptive because compiling technologies for MS-DOS and for Windows have much in common. However, programming for MS-DOS is gradually becoming a thing of the past.

The First Assembly Program and Its Translation

Fig. 1.1 shows the scheme of translating the module in Assembly language.

Figure 1.1: Scheme of translating an Assembly module

Two main programs correspond to the two stages of translation in Fig. 1.1: the ML.EXE assembler [i] and the LINK.EXE linker (or TASM32.EXE and TLINK32.EXE in Turbo Assembler). Suppose that the source file of your program written in Assembly language is called PROG.ASM. Without diving into details, the first stage of translation will look as follows :

c:\masm32\bin\ml /c /coff PROG.ASM

As a result of this step, the PROG.OBJ module will appear. The second stage will look as follows:

c:\masm32\bin\Link /SUBSYSTEM:WINDOWS PROG.OBJ

As a result of this step, you'll get the executable module: PROG.EXE. You can easily guess that /c and /coff are command-line options of the ML.EXE program and /SUBSYSTEM:WINDOWS is the command-line option for LINK.EXE.

Other command-line options of these programs will be covered in more detail in Chapter 5.

The more I think about this two-pass scheme of translation, the more perfect it seems. The format of the resulting module depends on the operating system. Having specified the requirements for the structure of the object module, you get the following possibilities:

The main advantage here, however, is the possibility of expanding the object module standard for different operating systems. This means that you'd be able to use modules written for different operating systems. [ii]

To understand the translation process, consider several programs that don't appear to do anything useful.

Listing 1.1: The "Do Nothing" program

.586P ; Flat memory model .MODEL FLAT, STDCALL ;--------------------------------------- ; Data segment _DATA SEGMENT _DATA ENDS ; Code segment _TEXT SEGMENT START: RET ; Exit _TEXT ENDS END START

 

The example of a "Do Nothing" program is presented in Listing 1.1. I'll call this program PROG1. Note for future reference that microprocessor commands and macroassembler directives will be written in CAPITAL LETTERS .

Thus, to get the executable module, issue the following commands [i] :

ML /c /coff PROG1.ASM LINK /SUBSYSTEM:WINDOWS PROG1.0BJ

Or, for Turbo Assembler, issue the following:

TASM32 /ml PROG1.ASM TLINK32 -aa PROG1.0BJ

For the moment, take the translation examples for granted and continue your investigations.

Quite often, it is convenient to split the source code into several parts and join them at the first stage of translation. This can be achieved using the include directive. For example, one file might contain the program code, and the constants and data (such as variable definitions) along with the prototypes of external procedures might be placed into separate files. Such files often have the INC filename extension.

Listing 1.2 illustrates this approach.

Listing 1.2: Using the INCLUDE directive

; The CONS.INC file CONS1 EQU 1000 CONS2 EQU 2000 CONS3 EQU 3000 CONS4 EQU 4000 CONS5 EQU 5000 CONS6 EQU 6000 CONS7 EQU 7000 CONS8 EQU 8000 CONS9 EQU 9000 CONS10 EQU 10000 CONS11 EQU 11000 CONS12 EQU 12000 ; The DAT.INC file DAT1 DWORD 0 DAT2 DWORD 0 DAT3 DWORD 0 DAT4 DWORD 0 DAT5 DWORD 0 DAT6 DWORD 0 DAT7 DWORD 0 DAT8 DWORD 0 DAT9 DWORD 0 DAT10 DWORD 0 DAT11 DWORD 0 DAT12 DWORD 0 ; The PROG1.ASM file .586P ; Flat memory model .MODEL FLAT, STDCALL ; Include the file with constants INCLUDE CONS.INC ;------------------------------------------ ; Data segment _DATA SEGMENT ; Include the data file INCLUDE DAT.INC _DATA ENDS ; Code segment _TEXT SEGMENT START: MOV EAX, CONS1 SHL EAX, 1 ; Multiply by 2 MOV DAT1, EAX ;------------------------------------------ MOV EAX, CONS2 SHL EAX, 2 ; Multiply by 4 MOV DAT2, EAX ;------------------------------------------ MOV EAX, CONS3 ADD EAX, 1000 ; Add 1000 MOV DAT3, EAX ;------------------------------------------ MOV EAX, CONS4 ADD EAX, 2000 ; Add 2000 MOV DAT4, EAX ;------------------------------------------ MOV EAX, CONS5 SUB EAX, 3000 ; Subtract 3000 MOV DAT5, EAX ;------------------------------------------ MOV EAX, CONS6 SUB EAX, 4000 ; Subtract 4000 MOV DAT6, EAX ;------------------------------------------ MOV EAX, CONS7 MOV EDX, 3 IMUL EDX ; Multiply by 3 MOV DAT7, EAX ;------------------------------------------ MOV EAX, CONS8 MOV EDX, 7 ; Multiply by 7 IMUL EDX MOV DAT8, EAX ;------------------------------------------ MOV EAX, CONS9 MOV EBX, 3 ; Divide by 3 MOV EDX, 0 IDIV EBX MOV DAT9, EAX ;------------------------------------------ MOV EAX, CONS10 MOV EBX, 7 ; Divide by 7 MOV EDX, 0 IDIV EBX MOV DAT10, EAX ;------------------------------------------ MOV EAX, CONS11 SHR EAX, 1 ; Divide by 2 MOV DAT11, EAX ;------------------------------------------ MOV EAX, CONS12 SHR EAX, 2 ; Divide by 4 MOV DAT12, EAX ;------------------------------------------ RET ; Exit _TEXT ENDS END START

 

The example program in Listing 1.2, like the other programs provided in this chapter, is senseless. However, it demonstrates the convenience of using the INCLUDE directive. I'd like to remind you not to concentrate your attention on the obvious microprocessor commands. I'd only like to draw your attention to the IDIV command.

In this case, the IDIV command carries out the division operation over the operand residing in the EDX:EAX register pair. By resetting EDX to zero, you specify that the entire operand is in EAX.

Program translation is carried out as specified earlier for MASM and TASM.

Note 

Data Types

In this book, you'll mainly encounter three simple data types: byte, word, and double word. The following standard notation is widely used: byte BYTE or DB , word WORD or DW , and double word DWORD or DD . The choice of notation (e.g., DB in one case or BYTE in another) is imposed only by my desire to demonstrate various language capabilities and diversify the description.

[i] Traditionally, programmers have always called translators for assembly languages assemblers rather than compilers.

[ii] This portability is limited, though, because the coordination of system calls in different operating systems can cause considerable difficulties.

[i] If names of modules being compiled and linked contain blanks, then the names of these modules have to be enclosed by quotation marks:

ML /c /coff "MY FIRST PROGRAM.ASM"

Категории