First the details of execution control in Assembler.
![]() |
Mov eAx, 0 Call WriteDec Inc eAx Mov eCx, 4 Lea eDx, Done Call WriteString Output: 0 Done |
Mov eAx, 0 A: Call WriteDec Inc eAx Jmp A Mov eCx, 4 Lea Di, Done Call WriteString Output: 0 1 2 ... |
Mov eAx, 0 A: Call WriteDec Inc eAx Cmp eAx, 10 JL A Mov eCx, 4 Lea Di, Done Call WriteString Output: 0 1 2 ... 8 9 Done |
A: Call WriteDec Inc eAx Jmp A |
Recall that the IP always points to the next instruction to be fetched. The unconditional branch instruction is executed by changing the IP to the address of the label. Consider the following code which shows the effects on the IP of the unconditional Jmp A execution. The steps are:
After Fetch/Before Execute 0002 A: Call WriteDec 0005 Inc eAx 0006 Jmp A IP -> 0009 Call WriteDec |
After Execute IP -> 0002 A: Call WriteDec 0005 Inc eAx 0006 Jmp A 0009 Call WriteDec |
eAx = 0; A: cout << eAx; eAx++;
cout << "Done"; |
Mov eAx, 0 A: Call WriteDec Inc eAx
Mov eCx, 4 Lea Di, Done Call WriteString |
Ah changes Mov Ah, 00000101B = 5 Sub Ah, 00000010B = 2 Ah = 00000011 = 3 CF = 0 OF = 0 ZF = 0 SF = 0 |
Ah no change Mov Ah, 00000101B = 5 Cmp Ah, 00000010B = 2 Ah = 00000101 = 5 CF = 0 OF = 0 ZF = 0 SF = 0 |
| Relation | Condition | Flag values for Condition to be True |
| 5 == 2 | False | ZF = 1 |
| 5 != 2 | True | ZF = 0 |
| 5 < 2 | False | CF = 1 |
| 5 > 2 | True | ZF = 0 and CF = 0 |
| 5 <= 2 | False | ZF = 1 or CF = 1 |
| 5 >= 2 | True | CF = 0 |
A: Call WriteDec Inc eAx Cmp eAx, 10 JL A Mov eCx, 4 |
|
|||||||||||||||||||||||||||||
|
12 0005 74 09 Je A 13 14 0007 EB 00 10 Jmp A 15 16 000A C7 06 0000r 000A Mov X, 10 17 18 0010 C7 06 0000r 000B A: Mov X, 11 19 20 0016 C7 06 0000r 000C Mov X, 12 21 22 001C 74 F2 Je A |
| Problem | Solution |
A: More than 127 bytes Je A Mov X, 12 |
A: More than 127 bytes Jne Aa Jmp A Aa: Mov X, 12 |
The following gives the general form of assembly instructions necessary to abstract common structured constructs. As a general programming rule, one should solve the programming problem first in a pseudocode language using structured methods then translate the pseudocode to a target language. This holds doubly true for assembly language as the myriad of details involved in simultaneously designing and implementing an algorithm directly in assembly can be overwhelming.
The figure below illustrates the advantage of good structure and naming
conventions for improved readability and programming correctness.
Structured C++ int X = -5; if (X < 0) X = -X; X++; |
Structure not obvious Mov X, -5 Cmp X, 0 JGE Positive Neg X Positive: Inc X |
Structured but logic inverted Mov X, -5 if: Cmp X, 0 JGE endif Neg X endif: Inc X |
Structure obvious Mov X, -5 if: Cmp X, 0 JL then Jmp endif then: Neg X endif: Inc X |
The error is caused when the number of bytes between the conditional branch and the branch label exceeds this limit. This problem can occur for any conditional branch, an example implementing the do-while is:**Error** for.asm(13) Relative jump out of range by 0018h bytes
This can be easily corrected by at least three methods:do: ; do { : : : :while: Cmp eAx, 5 : } while( Ax != 5 ); Jne do endwhile:
while: Cmp eAx, 5 Je endwhile Jmp do endwhile:
while: Cmp eAx, 5 Jne intermediate Jmp endwhile intermediate: Jmp do endwhile: