COSC 350: Low Level Programming - Final Exam Study Guide

General Study Tips & Important Notes

  • Supplement this guide with the textbook (Irvine), notes, and assignments.
  • Cumulative Knowledge: Earlier concepts (registers, addressing, instructions) are essential.
  • Active Learning: Practice coding, rework examples, trace execution manually, and use a debugger.
  • Understand Purpose: Focus on why instructions are used and how they affect flags.
  • Allowed to bring 1 handwritten 8.5x11 page of notes to the exam.

Chapter 6: Conditional Processing

  • Decision-making in assembly using conditional jumps based on comparisons.
  • Flags Register: Crucial for conditions.
    • Key flags: ZF (Zero), SF (Sign), OF (Overflow), CF (Carry).
    • Set by CMP and arithmetic instructions.
  • CMP Instruction:
    • Compares destination and source operands: CMP destination, source.
    • Sets flags based on destination - source result but doesn't change destination.
    • Flag Impact:
      • ZF=1 if equal.
      • Unsigned: CF=1 if dest < src.
      • Signed: SF reflects the sign of the result; OF indicates overflow. Combinations of SF and OF determine signed relationships (
  • Conditional Jump Instructions: Transfer control if a specific flag condition is met.
    • Equality: JE/JZ (Jump if Equal/Zero, ZF=1), JNE/JNZ (Jump if Not Equal/Zero, ZF=0).
    • Signed: JG (Greater), JGE (Greater/Equal), JL (Less), JLE (Less/Equal). Based on SF, OF, ZF.
    • Unsigned: JA (Above), JAE (Above/Equal), JB (Below), JBE (Below/Equal). Based on CF, ZF.
    • Other: JMP (Unconditional jump), JCXZ/JECXZ (Jump if CX/ECX is zero - doesn't use flags).
  • Study Focus:
    • Memorize common jump instructions and the conditions they test (especially JE/JNE, JG/JL/JGE/JLE for signed, JA/JB/JAE/JBE for unsigned).
    • Understand how CMP sets the flags based on the relationship between the operands.
    • Write simple IF structures using CMP and conditional jumps.
    • Trace code examples involving conditional jumps.

Chapter 7: Integer Arithmetic, Shifting, and Rotating

  • Covers multiplication, division, and bit manipulation through shift and rotate instructions.
  • Shift Instructions: Move bits left or right within an operand.
    • Useful for multiplication/division by powers of 2 and bit manipulation.
    • SHL destination, count (Shift Logical Left): Shifts bits left, fills with 0s. Last bit shifted out goes to CF. Equivalent to SAL.
    • SHR destination, count (Shift Logical Right): Shifts bits right, fills with 0s. Last bit shifted out goes to CF.
    • SAR destination, count (Shift Arithmetic Right): Shifts bits right, preserves the sign bit (fills with MSB). Last bit shifted out goes to CF.
  • Rotate Instructions: Move bits left or right, wrapping around.
    • ROL destination, count (Rotate Left): Bits shifted out from the left (MSB) enter the right (LSB) and CF.
    • ROR destination, count (Rotate Right): Bits shifted out from the right (LSB) enter the left (MSB) and CF.
    • RCL destination, count (Rotate Carry Left): Rotates left through the Carry Flag (CF acts like a 9th/17th/33rd bit).
    • RCR destination, count (Rotate Carry Right): Rotates right through the Carry Flag.
  • Binary Coded Decimal (BCD): Represents decimal digits (0-9) using 4 bits each.
    • Requires adjustments after standard binary addition/subtraction.
    • DAA (Decimal Adjust after Addition): Adjusts AL after adding packed BCD values.
    • DAS (Decimal Adjust after Subtraction): Adjusts AL after subtracting packed BCD values.
  • Study Focus:
    • Understand the difference between logical and arithmetic shifts (SHR vs SAR).
    • Know how each shift/rotate instruction affects the Carry Flag (CF).
    • Recognize how shifts can perform fast multiplication/division by powers of 2.
    • Be aware of BCD representation and the purpose of DAA/DAS.

Chapter 8: Procedures and Introduction to Java Bytecode

  • Explores structured programming using procedures (subroutines) in x86 assembly and introduces the basics of Java Virtual Machine (JVM) bytecode.

Part 1: Stack Frames and Procedures (x86 Assembly)

  • Stack Frame: A dedicated area on the stack used by a procedure for parameters, return address, local variables, and saved registers.
    • Managed primarily using EBP (Base Pointer) and ESP (Stack Pointer).
  • CALL Instruction:
    • Pushes the return address (address of the instruction after the CALL) onto the stack.
    • Jumps to the procedure's starting address.
  • RET Instruction:
    • Pops the return address from the stack into the instruction pointer (EIP), effectively returning control to the caller.
    • Optional operand (RET n) adds n bytes to ESP after popping the return address (used to clean up stack parameters pushed by the caller).
  • Parameter Passing: Arguments can be passed to procedures via registers or the stack.
    • Stack parameters are pushed by the caller before the CALL (typically in reverse order).
  • Local Variables: Allocated within the stack frame by subtracting from ESP. Accessed using EBP offsets (e.g., [ebp-4]).
  • Register Saving: Procedures should save and restore any registers they modify that the caller expects to remain unchanged (e.g., EBX, ESI, EDI, EBP).
    • Usually done using PUSH at the start and POP (in reverse order) at the end.
  • ENTER Instruction: Automates setting up a stack frame (PUSH EBP; MOV EBP, ESP; SUB ESP, locals_size).
  • LEAVE Instruction: Automates tearing down a stack frame (MOV ESP, EBP; POP EBP). Often used just before RET.

Part 2: Introduction to Java Bytecode (Jasmin)

  • Java Virtual Machine (JVM): A stack-based virtual machine that executes compiled Java bytecode. It has its own instruction set, operand stack, and local variable array.
  • Jasmin: An assembler for JVM bytecode. Allows writing human-readable text files (.j) that assemble into Java class files (.class).
  • Stack-Based Operations: Most JVM instructions operate on the operand stack (pushing values onto it, popping values for calculations, storing results back).
  • Local Variables: JVM methods have an array for local variables (including parameters).
    • Instructions load from (iload, aload) and store to (istore, astore) this array using indices.
  • Common Jasmin Directives/Instructions:
    • .class, .super, .method, .end method: Define class structure and methods.
    • .limit stack, .limit locals: Specify required stack depth and local variable count.
    • ldc: Load constant value onto the stack.
    • iload_n, istore_n: Load/store integer from/to local variable index n (shortcuts for 0-3). iload, istore for other indices.
    • iadd, isub, imul, idiv: Integer arithmetic (pop operands, push result).
    • getstatic: Access static fields (e.g., System.out).
    • invokestatic, invokevirtual: Call static or instance methods.
    • return: Return from a void method. ireturn for integer return.
  • Study Focus:
    • Understand the sequence of events during CALL and RET.
    • Be able to draw stack frames, showing parameters, return address, local variables, and EBP/ESP pointers.
    • Know how to access stack parameters and local variables using EBP.
    • Recognize the purpose of ENTER and LEAVE (details matter).
    • Understand the concept of a stack-based virtual machine (JVM).
    • Be familiar with basic Jasmin syntax and common instructions for loading constants, manipulating local variables, performing arithmetic, and calling methods.
    • Trace simple Jasmin code snippets, tracking the operand stack and local variables.

Chapter 9: Strings and Arrays

  • Focuses on manipulating sequences of data, such as text strings and arrays, using specialized instructions and addressing modes.
  • String Primitives: Instructions optimized for processing data sequences (strings or arrays).
    • Often used with repeat prefixes (REP, REPE/REPZ, REPNE/REPNZ).
    • Assume ESI points to the source and EDI points to the destination. The Direction Flag (DF) controls whether ESI/EDI are incremented (CLD) or decremented (STD).
    • MOVSB/MOVSW/MOVSD: Move byte/word/dword from [ESI] to [EDI].
    • CMPSB/CMPSW/CMPSD: Compare byte/word/dword at [ESI] with [EDI]. Sets flags like CMP.
    • SCASB/SCASW/SCASD: Scan (compare) byte/word/dword at [EDI] with AL/AX/EAX. Sets flags.
    • STOSB/STOSW/STOSD: Store AL/AX/EAX into [EDI].
    • LODSB/LODSW/LODSD: Load byte/word/dword from [ESI] into AL/AX/EAX.
  • Repeat Prefixes: Used before string primitives to repeat the instruction ECX times or until a condition (based on ZF for REPE/REPNE) is met.
    • REP: Repeat ECX times (used with MOVS, STOS).
    • REPE/REPZ: Repeat while equal (ZF=1) or ECX > 0 (used with CMPS, SCAS).
    • REPNE/REPNZ: Repeat while not equal (ZF=0) or ECX > 0 (used with CMPS, SCAS).
  • Array Addressing: Accessing elements within an array typically involves:
    • Base Address: The starting address of the array.
    • Index: The position of the element (often scaled by element size).
    • Addressing Modes: Using base registers (EBX, EBP), index registers (ESI, EDI), and scaling factors (e.g., [ebx + esi*4]).
  • Study Focus:
    • Know the purpose of ESI, EDI, ECX, and the Direction Flag (DF) in string operations.
    • Understand what each string primitive instruction does (MOVSB, CMPSB, SCASB, STOSB, LODSB).
    • Recognize how repeat prefixes (REP, REPE, REPNE) modify the behavior of string primitives.
    • Be able to calculate the address of an array element using base, index, and scale factor.

Chapter 10: Structures and Macros

  • Introduces user-defined data structures (structs) and basic text substitution using macros.

  • Structures (STRUCT / ENDS): Allow grouping related data fields of potentially different types under a single name. Defines a template, not storage.

    • Syntax:

      StructName STRUCT
          fieldName1 type1 ?
          fieldName2 type2 ?
          ; ... more fields
      StructName ENDS
      
    • Instantiation: Declare variables of the structure type:

      • variableName StructName <> (uses default initializers)
      • variableName StructName < value1, value2, ... > (provides initializers)
  • Accessing Structure Fields:

    • Directly: Use the dot (.) operator with the variable name: MOV AX, variableName.fieldName2
    • Indirectly (via Register): If a register (e.g., ESI) holds the base address of the structure variable: MOV AX, [esi].fieldName2 or MOV AX, (StructName PTR [esi]).fieldName2
  • Macros (MACRO / ENDM): Define reusable blocks of code with optional parameters. The assembler replaces the macro invocation with its body text during assembly.

    • Syntax:

      macroName MACRO param1, param2
          ; assembly code using param1, param2
          ; ...
      ENDM
      
    • Invocation: Simply use the macro name, providing arguments: macroName arg1, arg2

    • Purpose: Code reuse, simplifying complex instruction sequences, improving readability.

  • Study Focus:

    • Understand how to define a structure using STRUCT and ENDS.
    • Know how to declare variables (instances) of a structure type.
    • Be able to access structure fields directly (using .) and indirectly (using a register pointer and .).
    • Recognize the basic syntax for defining (MACRO/ENDM) and invoking a simple macro.
    • Understand the fundamental difference between a procedure (CALL/RET) and a macro (text substitution).