I have to do a LC-3 code for this question, and i'm having some trouble since I'm new to LC-3:
Write an LC-3 assembly language program that does the following:
- Output a message to the screen that prompts the user to type in an LC-3 assembly language instruction (like ADD). The user ends their input by pressing Enter/Return.
- If the instruction typed by the user is a legal LC-3 assembly language instruction, your program displays the corresponding 4-bit opcode. For example, if the user types "ADD", the program would print out "0001".
- If the instruction typed by the user is not a legal LC-3 assembly language instruction (for example, "ADDD"), your program displays an appropriate error message.
- After displaying the output, your program loops back to the top, reinitializes anything that needs to be reinitialized, and goes again.
- Your program will exit when the user types the string "QUIT" and presses Enter/Return.
This is my code:
.ORIG x3000
; Constants for comparison
ADD_STR .STRINGZ "ADD"
AND_STR .STRINGZ "AND"
JMP_STR .STRINGZ "JMP"
BR_STR .STRINGZ "BR"
QUIT_STR .STRINGZ "QUIT"
; Memory locations
MESSAGE .STRINGZ "Enter an LC-3 assembly language instruction (type QUIT to exit): "
USER_INPUT .BLKW #20
MAIN
LEA R0, MESSAGE ; Display the prompt message
PUTS
; Read user input
LEA R0, USER_INPUT ; Store user input here
GETC ; Read the first character
OUT ; Echo the character
; Loop to read input until Enter/Return is pressed
LOOP
GETC ; Read the next character
OUT ; Echo the character
BRZ END_LOOP ; Exit loop if Enter/Return is pressed
STR R0, R1, #0 ; Store the character in memory
ADD R1, R1, #1 ; Move to the next memory location
BRNZP LOOP ; Repeat the loop
END_LOOP
; Compare user input to known instructions
LEA R1, USER_INPUT ; Load the input string pointer
LEA R2, ADD_STR ; Load ADD instruction pointer
LEA R3, AND_STR ; Load AND instruction pointer
LEA R4, JMP_STR ; Load JMP instruction pointer
LEA R5, BR_STR ; Load BR instruction pointer
LEA R6, QUIT_STR ; Load QUIT instruction pointer
; Compare input with ADD
CMP_ADD
LDR R7, R1, #0 ; Load a character from input
LDR R0, R2, #0 ; Load a character from ADD string
NOT R0, R0 ; Get the 2's complement of ADD character
ADD R0, R0, #1 ; Add 1 to compare with input character
ADD R7, R7, #1 ; Prepare to compare next character
BRnp ADD_CHECK ; Check condition
ADD_CHECK
BRz IS_ADD ; If both characters match, it's ADD instruction
BRnzp CMP_AND ; Else, check for AND instruction
IS_ADD
; Display the opcode for ADD
LEA R0, ADD_STR ; Load ADD instruction string
PUTS ; Display it
BRnzp MAIN ; Go back to the main loop
CMP_AND
; Similar comparison process for AND
; ... (Repeat the above process for AND, JMP, BR, QUIT)
; Handling for other instructions and errors can be written similarly
; Handle QUIT instruction
QUIT_CHECK
; ...
; Other instruction checks and error messages go here
; Loop back to the beginning
BRnzp MAIN
.END
the problem is that the program is not processing the user's input correctly, "Enter an LC-3 assembly language instruction (type QUIT to exit): is printed but when i try putting (e.g. ADD) nothing is returned, as well as the QUIT instruction that's not working. Also i'm not sure how to finish up with my code for this project. i hope someone can help me out. thanks.
First, up your debugging skill, and if you don't know debugging yet, now is a good time learn. Debugging assembly code is much like debugging other languages: single step each line to make sure it is doing what is needed at that point. One missing or bad instruction will ruin the whole program — any given instruction is depending on the prior ones being useful & correct.
Second, don't wait until you've written dozens of lines of code before you first run the debugger. Better practice is to write a few lines of code, then run them single step in the debugger. Observe the effect of the new instructions on CPU registers and data memory. What you learn from that will help guide the development of rest of the project.
If you start the debugger on this code, you'll probably be confused as to why there are hundreds of
NOPinstructions before your code, and that is because you have placed your data at the entry point. The simulator will start the program at x3000 due to the.ORIGstatement, however, that's right where your data is. To remedy is simple and there are two options, either (1) move data to after the code somainis the first actual instruction, -or- (2) don't move the data, but put aBR mainright before the data so the simulator/program skips over the data and on to real code.Jester is right that
BRZis testing for a null character and isn't going to work here, sinceGETCwill never give you a null character.GETCis a console input function and there is no null key on the keyboard for a user to type. A better choice is to test for newline character as that is a real character thatGETCcan give you. Jester is also right that you have some repeated code re:GETCthat seems odd/unwanted — there's no reason to treat the first character of user input as special/different from the rest of them.Your input loop is storing characters using
R1as a pointer, but have not put any particular value intoR1, so that is storing into memory at location 0 and/or whatever is leftover inR1from prior usage, rather than your buffer. Your code later uses the buffer, but that's not where the characters went. This is also observable in single step debugging — R1 doesn't have a value that matches your buffer's addresses, and, the further, store isn't putting characters into your buffer. You can identify your buffer's addresses, and I call this getting to know your data — you can do this in the debugger before stepping instructions of the program, and when you know the addresses for your data, that will help you recognize bad pointers.You're doing 2's complement negation properly to compare the characters, but there's no addition of the characters from the two strings, so effectively, the subtraction isn't happening.
Once you get the subtraction working (by adding the two characters together, one from one string and the other the 2's complement from the other string), that sets the condition codes, so you should do that
addand a conditional branch (e.g.BRZ) as a sequence. If you put other instructions in between (such as pointer increment of one, as you have), that will wipe out the condition codes with a new value — and pointer arithmetic does not set the condition codes usefully. So, you need to either pair together in sequence the finaladd(that does the subtraction/comparison) with the conditional branch, or, retest the result to recover the condition codes (e.g. usingADD R4, R4, #0, which would retest conditions forR4, while otherwise being harmless).If you test each possible command in that manner you're suggesting, you'll have a lot of almost pure duplicated code. There are better approaches, where you'd have only one compare loop, but feed it different starting points to check for the various different strings. But your approach should work, and may be be easier despite the duplication.