LC3 how do I print user input to screen? - lc3

This is what I have so far:
.orig x3000
Lea r0, EnterString
puts
LOOP
getc
add r1, r0, -10 ;subtract 10 to identified if enter is pressed
brz OUTSIDE ;if yes, go out of the loop
out
brnzp LOOP
OUTSIDE
Lea r1, InputString
puts
Lea r0, EnterString
out
Halt
EnterString .stringz "Please enter a string: "
InputString .stringz "\nThe text you have typed is: "
.end
I am trying to have user input of upto 99 characters and then print it, but after when i try and print whats been inputted it just prints some weird boxes after the InputString "\nThe text you have typed is: " gets printed.
I think its got something to do with me perhaps accidentally cleaing my EnterString? r0?
Am I close to having it sorting?
I wanted to put a screenshot but I can't because my ranks too low.

Your general approach isn't correct. Here's what you have right now:
Print out welcome string
Get character
If character is a newline, exit loop, otherwise get another character
Print out "your string is"
Output (incorrectly) welcome string again.
All PUTS does is to take the effective address stored in r0 and print each character in it, one at a time, until it reaches a '\0' character. All GETC does is to get a single character and store it into r0. It does not create a stack or a string and it cannot store multiple characters.
In order to store a string from the console, you need to define a place to put it and physically put it there. You'll need to create a BLKW with the number of characters that you want to store (plus room for a null character), then you'll need to:
load the address of this BLKW into a register
move the character from r0 into this address (hint: use STR)
increment the address so that you're still pointing at an empty position
In order to print it out again, load the effective address of your memory space and call PUTS, as you did with the welcome string.

Related

How to Iterate over the ASCII characters with LC3 laguage?

Please write machine code following this outline:
Initialize index to zero
Iterate over the ASCII characters until the null terminator (zero) is found
Add the index to the current character being processed
Output the result of the previous statement as an ASCII character
Increment the index
Halt
This is a question on my homework, and it requires only the language of LC3 to traverse and find 0. I want to know how to load ASCII files into the program using only basic languages such as (AND/ADD/LD/LEA/LDI/LDR...)?
Put a string into memory like so:
STR1 .stringz "Hello"
then you can load the string and set R1 to point to it:
LEA R1, STR1 ;R1 points to STR1
Now R1 is equivelent to the Ascii code for "H", R1 + 1 would be ascii for "e". Then you just need some looping and comparisons until you know R1 = 0.
Remember that .Stringz will put a Null terminating string into memory.

Why is this giving me a illegal operands errors?

I'm trying to write a code in lc3 that will output a block letter using different ASCII characters. When I try to compile my code, I get a ton of errors in the first pass stating I have illegal operands and I'm not sure why.
Here's my code, FONT_DATA points to a bunch of .FILL lines representing the different ASCII characters which I haven't included here:
;Creates the offset needed to find the 16 rows corresponding to the x5002 input
.ORIG x3000
LDI R6,LETTER
AND R8,R8,#0
ADD R8,R8,#16
MULTIPLY ADD R8,R8,#0
BRz ENDOFFSET
ADD R6,R6,R6
ADD R8.R8,#-1
BRnzp MULTIPLY
;Starts the code for the counters
ENDOFFSET ADD R2,R6,FONT_DATA
LDR R5,R2,#0
AND R3,R3,#0
ADD R3,R3,#16
ROWCHECK BRz DONE
AND R4,R4,#0
ADD R4,R4,#8
ROW BRz ROWDONE
;starts code for printing the characters
;this code will print anything with value 0
LDR R5,R5,#0
BRn CHARACTER
LDI R0,NEGCHAR
OUT
BRnzp ENDPRINT
;this code will print anything with value 1
CHARACTER LDI R0,CHAR
OUT
BRnzp ENDPRINT
;this will shift the string and decrement the R4 counter
ENDPRINT ADD R5,R2,R2
ADD R4,R4,#-1
BRnzp ROW
;This will start the next row and increment the string value
ROWDONE ADD R2,R2,#1
ADD R3,R3,#-1
BRnzp ROWCHECK
DONE HALT
CHAR .FILL x5000
NEGCHAR .FILL x5001
LETTER .FILL x5002
Here's my error:
error message
Basically I get "illegal operands for AND" on line 11, and "illegal operands on ADD" for lines 11, 13, 16, and 21. In the first pass
Alright
ADD R8,R8,#16
Firstly the lc-3 has only 8 registers. They are named R0-R7. R8 isn't a valid register.
Secondly the #16 is too big of an immediate value for use with the ADD instruction. The range of values supported needs to fit in 5 bits. That means that the minimum is -16 and the maximum is 15 as these are the numbers you can represent as a 5 bit 2's complement number.
That applies to other instructions where you used R8, or an immediate value higher than 15.
Next this instruction ADD R2,R6,FONT_DATA
Add only accepts a hardcoded number in the immediate value version of the instruction. I suppose you are trying to add the contents of the label pointed to by FONT_DATA and add it to R6. You will need to use the LD instruction to load the value at that address into a register then you can use the ADD instruction with 2 registers.

Calculating checksum or XOR operations

I'm using hyperterminal and trying to send strings a to 6 digit scoreboard. I was sent a sample string from the manufacturer to test with and it worked, but to be able change the displayed message I was told to calculate a new Checksum value.
The sample string is: &AHELLO N-12345\71
Charactors A and N are addresses for the scoreboards(allowing two displays be used through one RS232 connection). HELLO and -12345 are the characters to be shown on the display. The "71" is where I am getting stuck.
How can you obtain 71 from "AHELLO N-12345"?
In the literature supplied with the scoreboard, the "71" from the sample string is described as a character by character logical XOR operation on characters "AHELLO N-12345". The manufacturer however called it a checksum. I'm not trained in this type of language and I did try to research but I can't put it together on my own.
The text below is copied from the supplied literature and describes the "71" (ckck) in question...
- ckck = 2 ASCII control characters: corresponds to the two hexadecimal digits obtained by
performing the character by character logical XOR operation on characters
"AxxxxxxByyyyyy". If there is an error in these characters, the string is ignored
Example: if the byte by byte logical XOR operation carried out on the ASCII codes of the
characters of the "AxxxxxxByyyyyy" string returns the hexadecimal value 0x2A,
the control characters ckck are "2" and "A".
You don't specify a language but here's the algorithm in C#. Basically xor the values of the string all together and you'll end up with a value of 113, 71 in hex. Hence 71 is on the end of the input string.
string input = "AHELLO N-12345";
UInt16 chk = 0;
foreach(char ch in input) {
chk ^= ch;
}
MessageBox.Show("value is " + chk);
Outputs "value is 113"

How do I call writehex on a new line? [duplicate]

This question already has answers here:
Assembly Language New Line
(2 answers)
Closed 3 years ago.
I have a program that takes a string as input and outputs the decimal number representing amount of characters in the string, the hexvalue and the string itself.
The issue I am having is that if use call writedec, I want to be able to use call writehex after it, but print it on a new line. Currently, it prints on the same line.
However, if use mov al, 0ah, call writehex will print 0ah, instead of the hex value of the decimal
call writedec
call writehex
results in 130000000d
but I need:
13
0000000d
call writedec
mov al, 0Ah
call writehex
always results with
13
0000000Ah
Not sure what I did, but I must have been missing something. Works fine with mov al, 0Ah followed by call writechar

How do I get Ruby to search for a pattern on the tail of a local file?

Say I have a file blah.rb which is constantly written to somehow and has patterns like :
bagtagrag" " hellobello " blah0 blah1 " trag kljesgjpgeagiafw blah2 " gneo" whatttjtjtbvnblah3
Basically, it's garbage. But I want to check for the blah that keeps on coming up and find the latest value i.e. number in front of the blah.
Hence, something like :
grep "blah"{$1} | tail var/test/log
My file is at location var/test/log and as you can see, I need to get the number in front of the blah.
def get_last_blah("filename")
// Code to get the number after the last blah in the less of the filename
end
def display_the_last_blah()
puts get_last_blah("var/test/log")
end
Now, I could just keep on reading the file and performing something akin to string pattern search on the entire file again and again. Obtaining the last value, I can then get the number. But what if I only want to look at the added text in the less and not the entire text.
Moreover, is there a quick one-liner or smart command to get this?
Use IO.open to read the file and Enumerable#grep to search the desired text using a regular expression like the following code does:
def get_last_blah(filename)
open(filename) { |f| f.grep(/.*blah(\d).*$/){$1}.last.to_i }
end
puts get_last_blah('var/test/log')
# => 3
The method return the number in from of the last "blah" word of the file. It is reading the entire file but the result is the same as if is done with tail.
If you want to use a proper tail, take a look at the File::Tail gem.
I presume you wish to avoid reading the entire file each time; rather, you want to start at the end and work backward until you find the last string of interest. Here's a way to do that.
Code
BLOCK_SIZE = 30
MAX_BLAH_NBR = 123
def doit(fname, blah_text)
#f = File.new(fname)
#blah_text = blah_text
#chars_to_read = BLOCK_SIZE + #blah_text.size + MAX_BLAH_NBR.to_s.size
ptr = #f.size
block_size = BLOCK_SIZE
loop do
return nil if ptr.zero?
ptr -= block_size
if ptr < 0
block_size += ptr
ptr = 0
end
blah_nbr = read_block(ptr)
(f.close; return blah_nbr.to_i) if blah_nbr
end
end
def read_block(ptr)
#f.seek(ptr)
#f.read(#chars_to_read)[/.*#{#blah_text}(\d+)/,1]
end
Demo
Let's first write something interesting to a file.
MY_FILE = 'my_file.txt'
text =<<_
Now is the time
for all blah2 to
come to the aid of
their blah3, blah4 enemy or
perhaps do blagh5 something
else like wash the dishes.
_
File.write(MY_FILE, text)
Now run the program:
p doit(MY_FILE, "blah") #=> 4
We expected it to return 4 and it did.
Explanation
doit first instructs read_block to read up to 37 characters, beginning BLOCK_SIZE (30) characters from the end of the file. That's at the beginning of the string
"ng\nelse like wash the dishes.\n"
which is 30 characters long. (I'll explain the "37" in a moment.) read_block finds no text matching the regex (like "blah3"), so returns nil.
As nil was returned, doit makes the same request of read_block, but this time starting BLOCK_SIZE characters closer to the beginning of the file. This time read_block reads the 37 character string:
"y or\nperhaps do blagh5 something\nelse"
but, again, does not match the regex, so returns nil to doit. Notice that it read the seven characters, "ng\nelse", that it read previously. This overlap is necessary in case one 30-character block ended, "...bla" and the next one began "h3...". Hence the need to read more characters (here 37) than the block size.
read_block next reads the string:
"aid of\ntheir blah3, blah4 enemy or\npe"
and finds that "blah4" matches the regex (not "blah3", because the regex is being "greedy" with .*), so it returns "4" to doit, which converts that to the number 4, which it returns.
doit would return nil if the regex did not match any text in the file.

Resources