Art of Assembly/Win32 Edition is now available. Let me read that version.
PLEASE: Before emailing me asking how to get a hard copy of this text, read this.
Important Notice: As you have probably discovered by now, I am no longer updating this document. The reason is quite simple: I'm working on a Windows version of "The Art of Assembly Language Programming". In the past I have encouraged individuals to send me corrections to this text. However, as I am no longer updating this material, don't expect those correctioins to appear in a future release. I am collecting errata that I will post to Webster someday, so feel free to continue sending corrections to AoA/DOS (16-bit) to rhyde@cs.ucr.edu. If you're more interested in leading edge material, please see the information about the Win/32 edition, above.
if..then..else
, case
(switch
), while, for
etc., into equivalent assembly language sequences. This chapter also discusses techniques you can use to improve the performance of these control structures. The sections below that have a "*" prefix are essential. Those sections with a "o" discuss advanced topics that you may want to put off for a while.
if..then..else
statement in Pascal:
IF (condition is true) THEN stmt1 ELSE stmt2 ;
Assembly language, as usual, offers much more flexibility when dealing with conditional statements. Consider the following Pascal statement:
IF ((X<Y) and (Z > T)) or (A <> B) THEN stmt1;
A "brute force" approach to converting this statement into assembly language might produce:
mov cl, 1 ;Assume true mov ax, X cmp ax, Y jl IsTrue mov cl, 0 ;This one's false IsTrue: mov ax, Z cmp ax, T jg AndTrue mov cl, 0 ;It's false now AndTrue: mov al, A cmp al, B je OrFalse mov cl, 1 ;Its true if A <> B OrFalse: cmp cl, 1 jne SkipStmt1 <Code for stmt1 goes here> SkipStmt1:
As you can see, it takes a considerable number of conditional statements just to process the expression in the example above. This roughly corresponds to the (equivalent) Pascal statements:
cl := true; IF (X >= Y) then cl := false; IF (Z <= T) then cl := false; IF (A <> B) THEN cl := true; IF (CL = true) then stmt1;
Now compare this with the following "improved" code:
mov ax, A cmp ax, B jne DoStmt mov ax, X cmp ax, Y jnl SkipStmt mov ax, Z cmp ax, T jng SkipStmt DoStmt: <Place code for Stmt1 here> SkipStmt:
Two things should be apparent from the code sequences above: first, a single conditional statement in Pascal may require several conditional jumps in assembly language; second, organization of complex expressions in a conditional sequence can affect the efficiency of the code. Therefore, care should be exercised when dealing with conditional sequences in assembly language.
Conditional statements may be broken down into three basic categories: if..then..else
statements, case
statements, and indirect jumps. The following sections will describe these program structures, how to use them, and how to write them in assembly language.
if..then
or if..then..else
statement. These two statements take the following form shown below:The if..then
statement is just a special case of the if..then..else
statement (with an empty ELSE block). Therefore, we'll only consider the more general if..then..else
form. The basic implementation of an if..then..else
statement in 80x86 assembly language looks something like this:
{Sequence of statements to test some condition} Jcc ElseCode {Sequence of statements corresponding to the THEN block} jmp EndOfIF ElseCode: {Sequence of statements corresponding to the ELSE block} EndOfIF:
Note: Jcc
represents some conditional jump instruction.
For example, to convert the Pascal statement:
IF (a=b) then c := d else b := b + 1;
to assembly language, you could use the following 80x86 code:
mov ax, a cmp ax, b jne ElseBlk mov ax, d mov c, ax jmp EndOfIf ElseBlk: inc b EndOfIf:
For simple expressions like (A=B)
generating the proper code for an if..then..else
statement is almost trivial. Should the expression become more complex, the associated assembly language code complexity increases as well. Consider the following if
statement presented earlier:
IF ((X > Y) and (Z < T)) or (A<>B) THEN C := D;
When processing complex if
statements such as this one, you'll find the conversion task easier if you break this if
statement into a sequence of three different if
statements as follows:
IF (A<>B) THEN C := D IF (X > Y) THEN IF (Z < T) THEN C := D;
This conversion comes from the following Pascal equivalences:
IF (expr1 AND expr2) THEN stmt;
is equivalent to
IF (expr1) THEN IF (expr2) THEN stmt;
and
IF (expr1 OR expr2) THEN stmt;
is equivalent to
IF (expr1) THEN stmt; IF (expr2) THEN stmt;
In assembly language, the former if
statement becomes:
mov ax, A cmp ax, B jne DoIF mov ax, X cmp ax, Y jng EndOfIf mov ax, Z cmp ax, T jnl EndOfIf DoIf: mov ax, D mov C, ax EndOfIF:
As you can probably tell, the code necessary to test a condition can easily become more complex than the statements appearing in the else
and then blocks. Although it seems somewhat paradoxical that it may take more effort to test a condition than to act upon the results of that condition, it happens all the time. Therefore, you should be prepared for this situation.
Probably the biggest problem with the implementation of complex conditional statements in assembly language is trying to figure out what you've done after you've written the code. Probably the biggest advantage high level languages offer over assembly language is that expressions are much easier to read and comprehend in a high level language. The HLL version is self-documenting whereas assembly language tends to hide the true nature of the code. Therefore, well-written comments are an essential ingredient to assembly language implementations of if..then..else
statements. An elegant implementation of the example above is:
; IF ((X > Y) AND (Z < T)) OR (A <> B) THEN C := D; ; Implemented as: ; IF (A <> B) THEN GOTO DoIF; mov ax, A cmp ax, B jne DoIF ; IF NOT (X > Y) THEN GOTO EndOfIF; mov ax, X cmp ax, Y jng EndOfIf ; IF NOT (Z < T) THEN GOTO EndOfIF ; mov ax, Z cmp ax, T jnl EndOfIf ; THEN Block: DoIf: mov ax, D mov C, ax ; End of IF statement EndOfIF:
Admittedly, this appears to be going overboard for such a simple example. The following would probably suffice:
; IF ((X > Y) AND (Z < T)) OR (A <> B) THEN C := D; ; Test the boolean expression: mov ax, A cmp ax, B jne DoIF mov ax, X cmp ax, Y jng EndOfIf mov ax, Z cmp ax, T jnl EndOfIf ; THEN Block: DoIf: mov ax, D mov C, ax ; End of IF statement EndOfIF:
However, as your if
statements become complex, the density (and quality) of your comments become more and more important.