350 likes | 515 Views
Flow Control Instructions and Addressing Modes. Chapter 3. Jumps and Loops. The basic instructions for branching are jumps and loops Loops are instructions to repeat a block of code a certain number of times
E N D
Jumps and Loops • The basic instructions for branching are jumps and loops • Loops are instructions to repeat a block of code a certain number of times • Jumps are instructions that branch to a distant labeled instruction when a flag condition is met • Status flags are modified by arithmetic instructions so these are normally used just before a jump • Example: the JNZ (jump if not zero) instruction jumps to the destination-label if ZF = 0. Usage: • JNZ destination-label
Simple Example Using JNZ • This program prints all the lower case letters in increasing order • We jump to again whenever ZF=0 (when ebx != eax) • We do not jump (and execute ret) when ZF=1 (when ebx = eax) • The code would be simpler if the sub instruction would not change the value of the destination operand • We do have such an instruction. It is the CMP (compare) instruction. .386 .model flat include csi2121.inc .code main: mov eax,61h ;char 'a' again: mov ebx,7bh ;one after 'z' putch eax inc eax sub ebx,eax jnz again ret end
The CMP Instruction • Usage: • cmp destinat,source • Performs: destination - source but does not store the result of the subtraction into destination • But the flags are affected just like SUB • Same restrictions on operands as for SUB • Very often used just before performing a jump • The previous program is now simpler .386 .model flat include csi2121.inc .code main: mov eax,61h ;char'a' again: putch eax inc eax cmp eax,7bh jnz again ret end
Single-Flag Jumps • These are jumps where the flag condition consist of a single flag. The following are often used: Instruction Description Condition for Jump JZ / JE Jump if zero ZF = 1 Jump if equal JNZ / JNE Jump if not zero ZF = 0 Jump if not equal JS Jump if negative SF = 1 JNS Jump if nonnegative SF = 0 JO Jump if overflow OF = 1 JNO Jump if no overflow OF = 0 JC Jump if carry CF = 1 JNC Jump if no carry CF = 0 Note: sometimes the same instruction has 2 different mnemonics (like JZ and JE)
Jumping on a Register Condition • There exists two jumps where the condition for jumping is given by a register • The JCXZ instruction jumps if the content of register CX is zero. Usage: • JCXZ destination-label • The JECXZ instruction jumps if the content of register ECX is zero. Usage: • JECXZ destination-label
Jumping on a Inequality Condition • Often, we need to branch when some value is larger (or smaller) than an other. Ex: • CMP eax, ebx • ;now jump somewhere when eax > ebx • However, integer order (larger or smaller) depends on the chosen interpretation • Ex: if AL contains 05h and BL contains A0h. Then: • AL > BL for a signed interpretation • AL < BL for a unsigned interpretation • Hence, we have these two types jumps: • Unsigned comparison jumps: for an unsigned interpretation of a comparison used just before the jump (ex: with CMP) • Signed comparison jumps: for a signed interpretation of a comparison used just before the jump (ex: with CMP)
Unsigned Comparison Jumps Instruction Description Jump Condition JA / JNBE Jump if above (if op1>op2) CF=0 and ZF=0 Jump if not below or equal JAE / JNB Jump if above or equal CF=0 Jump if not below JB / JNAE Jump if below (if op1<op2) CF=1 Jump if not above or equal JBE / JNA Jump if below or equal CF=1 or ZF=1 Jump if not above Each of these instructions have 2 different mnemonics We normally used them just after a CMP op1,op2 instruction and the jumping condition is given by a unsigned interpretation of the comparison
Signed Comparison Jumps Instruction Description Jump Condition JG / JNLE Jump if greater (op1>op2) ZF=0 and SF=OF Jump if not less or equal JGE / JNL Jump if greater or equal SF=OF Jump if not less JL / JNGE Jump if less (if op1<op2) SF!=OF Jump if not greater or equal JLE / JNG Jump if less or equal ZF=1 or SF!=OF Jump if not greater Each of these instructions have 2 different mnemonics We normally used them just after a CMP op1,op2 instruction and the jumping condition is given by a signed interpretation of the comparison
Using Comparison Jumps • CMP is normally used before a comparison jump • Ex: to branch to exit when AX > BX under a signed interpretation (ex: AX=1, BX=FFFFh): • cmp ax,bx • jg exit • But to branch to exit when AX > BX under a unsigned interpretation: • cmp ax,bx • ja exit • Note that the jump is not performed when AX=1 and BX =FFFFh
Unconditional Jump • Sometimes we need to jump without any condition • Just use the JMP instruction. • JMP destination .386 .model flat include csi2121.inc .code main: jmp over msg db "hello!",0 over: putstr msg ret end
Application: an Echo Program • The input buffer is initially empty. So getch returns only when the user press <CR> • The macro putch prints the first character entered. • When getch is executed again, then the next character in the input buffer is printed. • Hence this program echoes on the screen the user string entered on the keyboard • But if the user press <ctrl-z>, then getch returns –1 in eax and the program exits. • Try it! .386 .model flat include csi2121.inc .code main: getch cmp eax,-1 ;<ctrl-z> ? je exit ;yes then exit putch eax ;no, print char jmp main exit: ret end
File Redirection of I/O • I/O operations done with macros in csi2121.inc can be redirected to/from files. If the previous (executable) program is called echo1.exe, then • echo1 < infile > outfile • Takes its input from the file infile and writes its output to the file outfile • If infile is a text file, then outfile will be an identical copy • because getch return –1 when the EOF is reached • But if infile is a binary file, then outfile will generally not be an identical copy because: • getch returns –1 if it reads 1Ah (the ASCII code of <ctrl-z>) from infile. So echo1 will exit on the first occurrence of 1Ah in infile • When getch reads 0Ah, putch will output 0Dh, 0Ah • Each 0Dh on input will be ignored by getch • This does not occur in Unix and an equivalent C program that uses getchar() and putchar() can copy any file
Exercise 1 • Without modifying the content of AX, write a sequence of 2 instructions that will transfer the execution to the instruction labeled by L1 when: • (a) the signed value of AX is greater than –128 • (b) the unsigned value of AX is lower or equal to 255 • (c) AL contains an upper case letter (supposing that AL always contains a letter) • (d) AL contains an lower case letter (supposing that AL always contains a letter)
High-Level Flow Control Structures • High-level languages uses high-level structures such as if-then-else, case, while... to control the flow of execution • algorithms are normally expressed in terms of these high-level structures • Processors only provide conditional and unconditional jumps and loops • thus we need to decompose the high-level control flow structures into low-level ones • We give here a few examples on how this can be done by using jumps
If-Then-Else • HLL Observation If Condition { Code-Block-1 } else { Code-Block-2 } The programbranchesto Code-Block-2 ifConditionisFalse The programbranchesto Code-Block-2 ifcce.g.,JE or JNZ,isTrue • Assembler Observation • Jcc Code-Block-2 • ThereforeHLL notCondition Assembler Jcc
Example: if (op1 < op2) then statement 1 else statement 2 end if Analysis: there is a conditional jump (JXXX) to else when op1 >= op2 there is a unconditional jump (JMP) from end of statement 1 to end_if ASM solution for signed comparison: cmp op1,op2 jge else_ ;statement 1 jmp end_if else_: ;statement 2 end_if: Note: “else” is a ASM reserved word. We use “else_” instead If-Then-Else (Continued…)
Example : do while (op1 < op2) statement end do Analysis: JXXX to end_do when op1 >= op2 JMP from end_do to while ASM solution for an unsigned comparison: do_while: cmp op1,op2 jae end_do ;statement jmp do_while end_do: While
Example: case input of ‘A’ :DestA ‘B’ :DestB ‘C’ :DestC end case Analysis: CMP and JXXX for each case ASM solution: cmp input,’A’ jne L1 JMP DestA L1: cmp input,’B’ jne L2 JMP DestB L2: cmp input,’C’ jne L3 JMP DestC L3: Case
Case (Continued…) • ASM solution 2: cmp input,’A’ jne L1 DestA Code Jmp L3 L1: cmp input,’B’ jne L2 DestB Code Jmp L3 L2: cmp input,’C’ jne L3 DestC Code L3: • Example: case input of ‘A’ :DestA ‘B’ :DestB ‘C’ :DestC end case • Analysis: CMP and JXXX for each case
The LOOP Instruction • LOOP provides the easiest way to repeat a block of statements a specific number of times. Usage: • LOOP destination-label • where the destination-label must precede LOOP by less than 128 bytes of code • This restriction does not exists for jumps (conditional and unconditional) • The execution of LOOP produces the following sequence of events: • (1) ECX is decremented by 1 • (2) IF (ECX=0) THEN go to the instruction following LOOP, ELSE go to destination-label
Example: the following code fragment will print all the ASCII codes by starting with 7Fh: mov ecx,7Fh next: putch ecx loop next If (instead) ECX would be initialized to zero, then: after executing the block for the 1st time, ECX would be decremented by 1 and thus contain 0FFFFFFFFh. the loop would thus be repeated again 0FFFFFFFFh times!! Hence, if ECX contains an unspecified value, it is better to write: ;a loop to be ;executed ECX times jecxz over next: putch ecx loop next over: The LOOP Instruction (cont.)
Conditional Loops .386 .model flat include csi2121.inc .code main: mov ecx,7Fh next: putch ecx cmp ecx,20h loopnz next ret end • LOOPZ and LOOPE continues a loop while ZF=1 and ECX!=0 • ECX is first decremented, then the condition is tested (a trivial extension of LOOP) • LOOPNZ and LOOPNE continues a loop while ZF=0 and ECX != 0 • Syntax (same as LOOP): • loop** dest-label • The dest-label must precede loop** by < 128 bytes • The following program will print character 20h before exiting
Exercise 2 • Write a small piece of code that will display the character in AL iff it is an uppercase letter • Write a small piece of code that will count the number of characters in a user input line
Addressing Modes • Operands specify the data to be used by an instruction • An addressing mode refers to the way in which the data is specified by an operand • An operand is said to be direct when it specifies directly the data to be used by the instruction. This is the case for imm, reg, and mem operands (see previous chapter) • An operand is said to be indirect when it specifies the address (in virtual memory) of the data to be used by the instruction • To specify to the assembler that an operand is indirect we enclose it between […] • Indirect addressing is a necessity when we want to manipulate values that are stored in large arrays because we need then an operand that can index (and run along) the array • Ex: to compute an average of values
Register Indirect Addressing • When a register contains the address of the value that we want to use for an instruction, we can provide [reg] for the operand • This is called register indirect addressing • The register must be 32 bits wide because offset addresses are on 32 bits. Hence, we must use either EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP • Ex: Suppose that the double word located at address 100h contains 37A68AF2h. • If ESI contains 100h, the next instruction will load EAX with the double word located at address 100h: • mov eax,[esi] ;EAX=37A68AF2h (indirect addressing) • In contrast, the next instruction will load EAX with the double word contained in ESI: • mov eax, esi ;EAX=100h (direct addressing)
Getting the Address of a Memory Location • To use indirect register addressing we need a way to load a register with the address of a memory location • For this we can use the OFFSET operator. The next instruction loads EAX with the offset address of the memory location named “result” • .data • result dd 25 • .code • mov eax, offset result • ;EAX now contains the offset address of result • We can also use the LEA (load effective address) instruction to perform the same task • lea eax, result • ;EAX now contains the offset address of result • In contrast, the following transfers the content of the operand • mov eax, result ; EAX = 25
Ex: Summing the Elements of an Array .386 .model flat include csi2121.inc .data arr dd 10,23,45,3,37,66 count dd 6 ;numb of elmts .code main: mov ebx, 0 ;holds the sum mov ecx, count mov eax, offset arr next: add ebx,[eax] add eax,4 loop next putint ebx ret end • Register EBX holds the sum • Register ECX holds the number of elements to sum • Register EAX holds the address of the current double word element • We say that EAX points to the current double word • ADD EBX, [EAX] increases EBX by the number pointed by EAX • When EAX is increased by 4, it points to the next double word • The sum is printed by • putint ebx
The Type of an Indirect Operand • The type of an indirect operand is determined by the assembler when it is used in an instruction that needs two operands of the same type. Ex: • mov eax,[ebx] ;a double word is moved • mov ax,[ebx] ;a word is moved • mov [ebx],ah ;a byte is moved • However, in some cases, the assembler cannot determine the type. Ex: • mov [eax],1 ;error • Indeed, how many bytes should be moved at the address contained in EAX? • Sould we move 01h? or 0001h? or 00000001h ?? Here we need to specify explicitly the type to the assembler • The PTR operator forces the type of an operand. Hence: • mov byte ptr [eax], 1 ;moves 01h • mov word ptr [eax], 1 ;moves 0001h • mov dword ptr [eax], 1 ;moves 00000001h • mov qword ptr [eax], 1 ;error, illegal op. size
The LABEL Directive • It gives a name and a size to an existing storage location. It does not allocate storage. • It must be used in conjunction with byte, word, dword, qword... .data val16 label word;no allocation val32 dd 12345678h ;allocates storage .code mov eax,val32 ;EAX = 12345678h mov ax,val32 ;error mov ax,val16 ;AX = 5678h • val16 is just an alias for the first two bytes of the storage location val32
Indirect Addressing with Displacement • We can add a constant (positive or negative) and a variable name to a register indirect operand. These are called displacements. • Here are some forms that are permitted: • .data • A dw 10,20,30,40,50,60 • .code • mov ebp, offset A • mov esi, 2 • mov ax, [ebp+4] ;AX = 30 • mov ax, 4[ebp] ;same as above • mov ax, [esi+A] ;AX = 20 • mov ax, A[esi] ;same as above • mov ax, A[esi+4] ;AX = 40 • Mov ax, [esi-2+A];AX = 10 • We can also multiply by 1, 2, 4, or 8. Ex: • mov ax, A[esi*2+2] ;AX = 40
Using Indirect Addressing with Displacement • This is the same program as before for summing the elements of an array • Except that the loop now contains only this instruction • add ebx,arr[(ecx-1)*4] • It uses indirect addressing with displacement and a scaling factor • It should be more efficient than the previous program .386 .model flat include csi2121.inc .data arr dd 10,23,45,3,37,66 count dd 6 ;numb of elmts .code main: mov ebx, 0 ;holds the sum mov ecx, count next: add ebx,arr[(ecx-1)*4] loop next putint ebx ret end
Indirect Addressing with Two Registers* • We can also use two registers. Ex: • .data • A DB 10,20,30,40,50,60 • .code • mov eax, 2 • mov ebx, 3 • mov dh, [A+eax+ebx] ;DH = 60 • mov dh, A[eax+ebx] ;same as above • mov dh, A[eax][ebx] ;same as above • A two-dimensional array example: .data arr db 10h, 20h, 30h db 0Ah, 0Bh, 0Ch .code mov ebx, 3 ;choose 2nd row mov esi,2 ;choose 3rd column mov al, arr[ebx][esi] ;AL = 0Ch add ebx, offset arr ;EBX = address of arr+3 mov ah, [ebx][esi] ;AH = 0Ch
Exercise 3 • We have the following data segment : • .data • YOU dw 3421h, 5AC6h • ME dd 8AF67B11h • Given that MOV ESI, OFFSET YOU has just been executed, write the hexadecimal content of the destination operand immediately after the execution of each instruction below: • MOV BH, BYTE PTR [ESI+1] ; BH = • MOV BH, BYTE PTR [ESI+2] ; BH = • MOV BX, WORD PTR [ESI+6] ; BX = • MOV BX, WORD PTR [ESI+1] ; BX = • MOV EBX, DWORD PTR [ESI+3] ; EBX =
Exercise 4 • Given the data segment • .DATA • A DW 1234H • B LABEL BYTE • DW 5678H • C LABEL WORD • C1 DB 9AH • C2 DB 0BCH • Tell whether the following instructions are legal, if so give the number moved • MOV AX,B • MOV AH,B • MOV CX,C • MOV BX, WORD PTR B • MOV DL, WORD PTR C • MOV AX, WORD PTR C1 • MOV BX,[C] • MOV BX,C