UMBC Decision-Making in Assembly Language Previous | Next


Decision-Making in Assembly Language

All repetition and loops are controlled by conditions. The conditions are evaluated to be true or false. Based on the answer some action is taken. This is the basis of all decision making and is a two step process. First, two numbers are brought into the ALU and one is subtracted from the other with the flags set accordingly. Then a conditional jump is made based on those flags.

The comparison is the same for signed and unsigned numbers, but the conditional jumps are different.

Comparing numbers

The cmp instruction has two operands: cmp reg/mem, reg/mem/constant The computer will perform a subtraction of operand2 from operand1 (but not changing the value of either one) and set the O, S, Z, A, P, and C flags (but does not affect the D and I flags). The results of the subtraction are lost. (The carry flag is set on addition and subtraction by the carry out of the left end. Although the carry is ignored for signed arithmetic, it can be quite useful in other situations.

Danger

In CMSC104 and CMSC201, we do not teach students about the goto statement. There was an article published in the ACM Journal a number of years ago entitled "GOTOs Are Considered Dangerous". It is still true! In assembly language, there is no way to avoid these horrible things! Remember, we taught you that the only acceptable control structures are:

The following will teach you how to do a GOTO. I must emphasis that you use a "Jump" only to implement Repetition and Selection, even though you have the power to do things differently!

General Jumps

Therre are two types of jumps. The first is a conditional jump. The flag is checked and if there is a match for what the instruction specifies, then the computer will jump a distance of up to either -128 or +127 bytes (called a short jump) from the next instruction (remember that the IP register always points to the next instruction to be executed.

Since we want the assembler to compute things for us, we will give the target as a label. (You can do it manually, however, if you go back and change the program later, it might change the distance of the jump and if you forget to make the change, you just broke your program! Therefore, always let the assembler worry about it.) Because of the distance limitation, we will call this a shortlabel. Actually, it could be an address, which is simply a number.

Note: Valid characters in labels are letters, numbers, _, $, #, @, ~, ., and ?. The only characters which may be used as the first character of an identifier are letters

Jumps do not alter the flags.

There is an unconditional jump, or one that is always preformed. The unconditional jump is not not limited to a short jump, and properly coded, can jump anywhere in memory!

The format is:

  jmp label               ; unconditional jump
  jconditional shortlabel ; conditional jump

Flag-based jumps

The jumps based on the flags being set/reset are:
Instruction Description 
JZ shortlabel jump if zero 
JNZ shortlabel jump if not zero 
JS shortlabel jump if sign 
JNS shortlabel jump if not sign 
JC shortlabel jump if carry 
JNC shortlabel jump if not carry 
JO shortlabel jump if overflow 
JNO shortlabel jump if not overflow
JP shortlabel jump if parity 
JNP shortlabel jump if not parity 
JPE shortlabel jump if parity even 
JPO shortlabel jump if parity odd 

Signed Conditional Jumps

To make life easier, there are jumps for both signed and unsigned jumps. Remember: the binary value 10000000 can be -1 or 128, when 01111111 is 127 in either case, but 128 would be large and -1 would be smaller! We want our comparison to give us the correct results.  
Instruction  Symbolic  Description 
JE shortlabel op1 = op2  jump if equal 
JNE shortlabel op1 != op2  jump if not equal 
JG shortlabel op1 > op2  jump if greater than 
JNG shortlabel !(op1 > op2)  jump if not greater than 
JGE shortlabel op1 >= op2  jump if greater than or equal 
JNGE shortlabel !(op1 >= op2)  jump if not greater than or equal
JL shortlabel op1 < op2  jump if less than 
JNL shortlabel !(op1 < op2)  jump if not less than 
JLE shortlabel op1 <= op2  jump if less than or equal 
JNLE shortlabel !(op1 <= op2)  jump if not less than or equal 

Selection

Selection involves choosing one path through the code or another:

Suppose we want to do something in C like:

if (ax < bx)
{
     X = -1;
}
else
{
X = 1;
}
it would look like this:

	cmp 	ax, bx  	
	jl  	axLess          ; go to 'axLess' if ax < bx
	mov 	word [X], 1     ; This is the 'else part 
	jmp 	Both            ; skip the 'then' part 
axLess: 
	mov 	word [X], -1    ; This is the 'then' part
Both:

What if the conditional jump needs a long jump? Change the code to this:
        cmp 	ax, bx  	
	jge 	notLess         ; use a jump with the opposite condition
	jmp 	axLess          ; now do a long jump 
notLess:
  	mov 	word [X], 1     ; This is the 'else part 
	jmp 	Both            ; skip the 'then' part 
axLess:
  	mov 	word [X], -1    ; This is the 'then' part 
Both:  			        ; Everyone back together here 



An Example Program

C


#include 

int main ( void )
{

  short  X;
  short  in1, in2;

  printf( "Please enter two signed 16-bit integers\n" );
  printf( "Enter an integer: " );
  scanf( "%d", &in1 );

  printf( "Enter an integer: " );
  scanf( "%d", &in2 );


  if ( in1 < in2 )
    {
      X = -1;
    }
  else
    {
      X = 1;
    }

  printf( "X = %d\n", X );

  return 0;

}

Assembly Language Version Of The Same Program

I have not been able to get printf to output a short int, but that is not an issue, because I want to look at the alternative solution, namely convert the short to long and put that! Being lazy, I like quick solutions that work, so I will sign extend ax into eax with the cwde instruction that we talked about in division. This example is based on the previous example of when a short jump will not work. I know, the short jump would work here!
section .data
instruct db	'Please enter two signed 16-bit integers', 10, 0
instr1   db     'Enter an integer: ',0
mystring db	10, 'X = %d', 10, 0
instring db     '%d',0

section .bss
X	resw	1
in1	resd	1
in2	resd	1
section .text
    global main                       ;must be declared for linker (ld)

main:  
                               ;tell linker entry point
extern	printf
extern  scanf
;; put your code here

getinput:
	push	instruct
	call	printf
	add	esp, 4

	push	instr1
	call	printf
	add	esp, 4

	push	in1
	push	instring
	call	scanf
	add	esp, 8

getinput2:
	push	instr1
	call	printf
	add	esp,4
	push	in2
	push	instring
	call	scanf
	add	esp, 8

	mov	eax, [in1]
	mov	ebx, [in2]

chkinput:
        cmp 	ax, bx  	
	jge 	notLess         ; use a jump with the opposite condition
	jmp 	axLess          ; now do a long jump 
notLess:
  	mov 	word [X], 1     ; This is the 'else part 
	jmp 	Both            ; skip the 'then' part 
axLess:
  	mov 	word [X], -1    ; This is the 'then' part 
Both:  			        ; Everyone back together here 

	mov	ax, [X]
	cwde			; Since we are printing using %d, we need to convert X
				; to 32 bits.
	
	push	eax
	push	mystring
	call	printf
	add	esp, 8

;; The final part of the program must be a call to the operating system to exit
;;; the program.
        mov     ebx,0   ;successful termination of program
        mov     eax,1   ;system call number (sys_exit)
        int     0x80    ;call kernel

;; Notice the file just ends.


Previous | Next

©2004, Gary L. Burt