Systems Lecture FRI Sep 11th
Assembly Code Formatting and Syntax Rules
Label Placement and Margins:
Labels must be positioned flush against the far-left margin (Column 1).
The only elements allowed on the far-left margin are labels and comments.
All pseudo-ops (directives) and assembly instructions must be indented using tabs.
Label Uniqueness and Scoping:
Labels act like global variable names and are visible across the entire program.
Every label must map to a unique memory address; a single label name cannot point to multiple addresses.
Multiple distinct labels can point to the exact same address.
Labels cannot be reused (e.g., if an
IFstatement uses an exit label, it must be uniquely designated such asIF_END_1orFN_1so it does not conflict with subsequent logic blocks).
Instruction and Operand Spacing:
Instructions and pseudo-ops must be tabbed over from the left margin.
Operands must be separated by exactly one space.
Commas must immediately follow an operand without preceding spaces (e.g.,
ADD R1, R2).
Comment Formatting:
Comments may begin on the left margin, be tabbed over, or be placed anywhere on a line.
Improper tabbing and formatting lead to point deductions on examinations.
Code Structure and Commenting Best Practices
Program Directives:
Programs begin with an origin directive, such as
.ORIG x3000(or value ), to set the starting memory address.The program terminates with the
.ENDdirective at the bottom of the file.
Program Entry Point:
A
MAINlabel is commonly placed at the start of the executable code block to indicate the program entry point.
High-Level Commenting Philosophy:
Comments should describe the intent and high-level logic of what the code achieves rather than simply restating the low-level assembly instruction.
Bad comment example: Stating that a line "puts into address ".
Good comment example: Explaining that represents an ASCII capital character
'A'(or a negative capital'A'used for character verification).Good comment example: For a sequence involving
NOTandADDinstructions, the comment should stateR0 = R1 - R2to clearly identify the block as a subtraction operation.Explaining complex high-level structures (such as
IFstatements orWHILEloops) keeps the programmer from losing their train of thought during debugging.
LC-3 Assembler Workflow and File Types
Supported File Extensions:
Assembly source code must be saved with a
.asmfile extension (e.g.,test.asm).Operating system settings that hide file extensions can inadvertently create invalid files such as
test.asm.txt, which will fail to open in the assembler.
Assembly Process and Error Checking:
Opening a
.asmfile in the assembler and clicking Reload and Assemble compiles the code.The assembler status line must display
Assembly Completealong with a timestamp to confirm success. If an error message appears, the output files will not be generated properly and the code must be corrected.The timestamp in the assembler updates once per second upon reloading.
Programmers must ensure they are editing and assembling the exact same file rather than editing a copy in a different directory.
Generated Output Files:
.asmFile: The raw assembly source text file..hexFile: An ASCII text representation of hex machine code required by the simulator..objFile: A true binary machine code file storing actual integer values directly executable by the processor..symFile (Symbol Table): Contains mappings of all defined labels to their designated 16-bit memory addresses.
Debugging with Symbol Tables and Simulator Integration:
Inspecting the
.symfile helps identify syntax typos. For example, typingJSRxinstead ofJSR xcauses the assembler to treatJSRxas an unused label assigned to an address.When loading a
.hexfile into the LC-3 simulator, if the corresponding.symfile is present in the same directory, the simulator replaces raw numerical addresses with human-readable label names.The optimal troubleshooting workflow cycle: Edit
.asmsource file Save Click Reload and Assemble in assembler Click Reset in simulator to reload updated machine code.
Subroutines: JSR and JSRR Instructions
Subroutine Overview:
Subroutines function like methods or functions in high-level programming languages.
Subroutines are located between the main program block (after the
HALTinstruction) and the.ENDdirective.
JSRvs.JSRRInstructions:JSR(Jump to Subroutine): Uses an 11-bit PC-relative offset embedded inside the instruction. It is limited in jump range relative to the current Program Counter.JSRR(Jump to Subroutine Register): Obtains the target address directly from a 16-bit register. Because a register holds a full 16-bit address,JSRRcan jump anywhere within the entire () address space.
Control Flow Constraints:
Enter a subroutine exclusively via
JSRorJSRRinstructions.Exit a subroutine exclusively via the
RET(Return) instruction.Never use branch (
BR) instructions to branch out of a subroutine or to branch back intoMAINfrom inside a subroutine. Branching must strictly remain within the internal scope of the subroutine.
Register Parameter Passing and Multiplication Algorithm
Parameter and Return Value Conventions:
Parameters (arguments) are passed into subroutines via designated data registers (e.g.,
R1andR2).Return values are returned to the caller via a designated return register (e.g.,
R0).Built-in system subroutines (TRAPs) follow this exact protocol:
GETCreads a keypress from the keyboard and returns the character inR0;OUTtakes a character stored inR0and prints it to the console.
LC-3 Multiplication Subroutine (
MULT) Implementation:High-Level Call Specification: Pass multiplier and multiplicand in
R1andR2; return product inR0(e.g., computing ).Assembly Setup Code:
Load inputs:
LDR R1, AandLDR R2, B(whereAstores andBstores ).Execute call:
JSR MULT.Algorithm Logic:
Clear
R0to (ADD R0, R0, #0orAND R0, R0, #0).Repeatedly add
R1toR0while decrementingR2by untilR2reachesReturn execution to caller with
R0containing
Register Preservation and Callee-Save Protocol
The Register Modification Problem:
In high-level languages like Java, passing variables
aandbintoc = mult(a, b)does not alteraandbin the calling scope.In assembly, internal execution of
MULTdecrementsR2down to . If the main program depends on the original value ofR2after callingMULT, data corruption occurs.
Callee-Save Protocol:
The subroutine (callee) is responsible for saving any registers it modifies internally to dedicated memory locations at entry, and restoring them prior to returning.
Step 1 (Entry): Store modified registers to memory (e.g.,
ST R2, SAVE_R2).Step 2 (Body): Execute subroutine computational logic.
Step 3 (Exit): Load saved values back into registers from memory (e.g.,
LD R2, SAVE_R2).Step 4 (Return): Execute
RET.From the perspective of
MAIN, register contents remain unchanged across the subroutine invocation.
Selective Preservation Rules:
Only save and restore registers that are explicitly modified inside the subroutine.
Do not save registers that are only read and never altered (e.g., if
R1is unchanged throughout execution, saving it is unnecessary).CRITICAL EXCEPTION: Never save or restore the designated return register (
R0). RestoringR0at exit overwrites the calculated output with the old input value, breaking the subroutine's return mechanism.
Performance and Efficiency Impact:
Indiscriminately saving all registers (e.g., stores and loads = extra instructions per call) introduces severe overhead.
If a subroutine is called inside a loop executing times, saving all registers unnecessarily adds unnecessary instructions to program execution.
Handling Nested Subroutines and TRAP Calls (
R7Preservation):The
JSRinstruction and system TRAP calls (such asGETCorOUT) write the return address into registerR7.If Subroutine A calls Subroutine B or executes a TRAP call within its body, the original return address in
R7needed to return toMAINis overwritten.Any subroutine containing nested
JSRor TRAP calls must saveR7to memory at entry and restoreR7before executing its ownRETinstruction.
Register Storage vs. Stack Architecture:
Passing arguments via fixed memory labels limits subroutines from being called recursively, as subsequent invocations overwrite the static label memory locations.
Dynamic languages utilize a stack frame where arguments and return addresses are pushed and popped per call layer to support recursion.
Audience Interaction & Class Logistics
Student Attendance:
Student Alex Kider was absent due to COVID-19 quarantine and will provide a doctor's note.
Dormitory Housing Discussion:
Students discussed transfer housing arrangements featuring suite-style rooms with private/shared connected bathrooms compared to standard dorm layouts.