CSCI 2400: Assembly Class 5

Conditionals and Flow Control


Any but the most trivial programs require flow control to control how code executes. In assembly this is accomplished through the use of conditional jumps that select code to execute based on the status of the processor flags from the previous class.

In today's class you will:

  1. Use conditional test instructions such as cmpl and testl
  2. Use conditional branches such as je, jne, and more
  3. Write a function that compares two integers with an if/then/else flow.
  4. Write a loop that prints the numbers 1 to 100.

Exercises

  1. Login to hopper.slu.edu- remember you can login with:

    ssh username@hopper.slu.edu

  2. Now, download a new program for today's class:

    wget http://cs.slu.edu/~dferry/courses/csci2400/asm/flow.s

    In order to create conditionally executed code, we first have to understand how program execution can be modified. Assembly programming doesn't have high-level constructs like if-else statements or for loops. The only tool available to modify the way a program executes is jumps, which would be considered goto statements in higher level languages.

    To use a jump, you need to define a jump target (or label). For example, consider the following simple program:

    main:
    	pushl	%ebp
    	movl	%esp, 	%ebp
    
    	movl	$0,	%eax
    target:
    	call 	print_eax
    	incl	%eax
    	jmp target
    
    	leave
    	ret
    

    This program starts executing at the start of main, and continues executing through the target: statement. That target: statement does not affect execution at all- it simply gives us a way to refer to that specific section of code. Thus, the program skips directly from executing the movl instruction to executing the call instruction. However, when the program later gets to the jmp instruction, the program then jumps back up to the target: line and begins executing again from there.

  3. How many times does the jump instruction execute in this program?

  4. What is the output of this program?

  5. Make your own infinite loop program using the code above and run it. You can kill the program in Linux using the key combination CTRL+C

  6. Our first conditional instruction is the compare instruction:

    cmpl b, a

    This is a useful all-purpose instruction for comparing two signed or unsigned integers. Under the hood, this instruction computes the result of a - b without storing the result. Then, If a == b then ZF is set to 1. If a < b then SF is set to 1, and if b < a then SF is set to 0.

    Write a short bit of code to test all three situtations where operand A is less than, equal to, or greater than operand B. Use the print_all function to confirm your results.

  7. Putting the previous exercises together, we can execute conditional jumps based on the state of the processor's flags. These jumps are designed to work with the comparison instructions. For example, the instruction je is a jump if equal instruction. In the following code the program will jump to label_1 if the contents of EAX and EBX are equal.

    cmpl	%eax,	%ebx
    je	label_1
    js	label_2
    
    #execute section 3
    jmp next
    
    label_1:
    #execute section 1
    jmp next
    
    label_2:
    #execute section 2
    
    next:
    #continue executing
    
    

    What C-style construct does the above code correspond to? Write a bit of pseudocode giving the high-level behavior of this program. Ask the instructor if you're unsure about the operation.

  8. At the top of the program is a mostly empty function called compare. Finish writing this function so that, when called, it prints the message:

    Testing A=%d and B=%d

    Followed by one of the messages:

    A is greater than B
    B is greater than A
    the arguments are equal

    as is appropriate.

  9. Test your function by calling it multiple times such that it generates at least one of each result message.

  10. The testl b, a instruction is also used to compare values. This instruction computes the bitwise-AND of operand A and operand B. If this value is zero then it sets ZF to one, and otherwise ZF to zero. You can then use the jz (jump if zero) and jnz (jump if not zero) instructions to control your program.

    One special use of testl is as a loop index. The instruction

    testl %eax, %eax

    will set the zero flag only if the register %eax is zero. Use the testl, decl, and jz instructions to create a loop that prints the values from 100 to 1 in order from highest to lowest. Feel free to use a function such as print_eax to accomplish this.

  11. Keep your source code and answers, they will be submitted at the end of the course assembly programming segment.