Friday, 20 December 2013

Now create an array of 10 values, starting at location x4000 so that it is “out of reach” of the instructions in your code (which should, as usual, load at address x3000). Using what you learnt of console i/o last week, populate that array with characters input from the keyboard.

    .ORIG x3000
    LD R3,FT        ; load x4000 in R3 as array base address
    LD R2,Count        ; load #10 in R2 as counter from 10 to 1
Loop
    TRAP x23        ; take input from user
    STR R0,R3,#0        ; store inputted chatacter in mem addr stored in R3
    ADD R3,R3,#1        ; increment R3 (mem location)
    ADD R2,R2,#-1        ; decrement R2 (counter)
    BRp Loop
    HALT
FT    .FILL x4000
Count    .FILL #10
    .END

Set up an array of 10 values following your code, and programmatically populate it with the first ten powers of 2, starting with 21 = 2, then read back the last value into register 2.

    .ORIG x3000       
    LD R1,Max       
    LD R0,Zero       
    LD R7,Zero   
Loop:
    LEA R6,Array
    LD R3,Zero
    ADD R4,R0,#0
Inner:
    ADD R3,R3,#2
    ADD R4,R4,#-1
    BRp Inner

    ADD R6,R6,R7
    STR R3,R6,#0

    ADD R2,R0,#0
    AND R0,R0,#0
MostInner:
    ADD R0,R0,#2
    ADD R2,R2,#-1
    BRp MostInner

    ADD R7,R7,#1
    ADD R1,R1,#-1
    BRp Loop


    ; Loading Last value in register R2
    LDR R2,R6,#0

    HALT
Array    .BLKW #10
Max    .FILL #10
Zero    .FILL #0
    .END

a. Using the .FILL & .BLKW pseudo-ops, store the value x4000 in one location, and reserve the following location for storing a result. Label ONLY the .FILL location. b. Use the direct mode to load the stored value into R2. c. Double the number in R2, and use the relative mode to store it to the reserved location (i.e. the address following the .FILL). d. Now use the indirect mode to store the same number to the address x4000.

.ORIG    x3000                ; Starting program from address x3000;
LD R2,ONLY                ; Using Direct mode to store the value of ONLY into R2.

ADD R3,R2,R2                ; Adding R2 and R2 then Storing result in register R3.

LEA R4,ONLY                ; Loading the address stored in lable ONLY into register R4.
STR R3,R4,1                ; Using Relative mode store the value of R3 into
                    ; relative memory address (address stored in register R4+1) which was reserved.

STI R3,ONLY                ; Use Indirect mode to store the value of R3 into memory address stored in Label ONLY (i.e.-x4000). 
HALT
ONLY .FILL x4000            ; Fill the value x4000 into Label ONLY.
.BLKW 1                    ; Reserving 1 block for storing the result;
.END                    ; End of the Program.

Modify your code from exercise 4 so that each output character is separated by a space, or output to a new line.

    .ORIG x3000

; Take Input from user
    LEA R3,Label        ; load array base addr in R3
    LD R2,Ten        ; load 10 in R2 (counter)
Input
    TRAP x23        ; input character
    STR R0,R3,#0        ; store inputted char in memory
    ADD R3,R3,#1        ; increment array base addr
    ADD R2,R2,#-1        ; decrement counter register R2
    BRp Input        ; branch to input if R2 is positive

; Add 1 to each inputted character
    LEA R3,Label        ; load array base addr in R3
    LD R2,Ten        ; load 10 in R2 (counter)
Add1
    LDR R0,R3,#0        ; load value from mem in R0
    ADD R0,R0,#1        ; increment R0 so it'll be plus 1 character
    STR R0,R3,#0        ; store inputted char in memory
    ADD R3,R3,#1        ; increment array base addr
    ADD R2,R2,#-1        ; decrement counter register R2
    BRp Add1        ; branch to Add1 if R2 is positive

; Output resultant Array character each in New Line
    LEA R3,Label        ; load array base addr in R3
    LD R2,Ten        ; load 10 in R2 (counter)
OutputByNewLine
    LDR R0,R3,#0        ; load value from mem in R0
    TRAP x21        ; display character stored in R0 on console
    AND R0,R0,#0
    LD R0,NewLine        ; load ascii value of NewLine in R0
    TRAP x21
    ADD R3,R3,#1        ; increment array base addr
    ADD R2,R2,#-1        ; decrement counter register R2
    BRp OutputByNewLine    ; branch to Output if R2 is positive

; Output resultant Array character each separated by Space
    LEA R3,Label        ; load array base addr in R3
    LD R2,Ten        ; load 10 in R2 (counter)
OutputBySpace
    LDR R0,R3,#0        ; load value from mem in R0
    TRAP x21        ; display character stored in R0 on console
    AND R0,R0,#0
    LD R0,Space        ; load ascii value of Space in R0
    TRAP x21
    ADD R3,R3,#1        ; increment array base addr
    ADD R2,R2,#-1        ; decrement counter register R2
    BRp OutputBySpace    ; branch to Output if R2 is positive

    HALT
Label    .BLKW #10
Ten    .FILL #10
NewLine    .FILL x000A
Space    .FILL x0020
    .END

We can very easily turn the array created in exercise 3 into a c-string: just make it an 11 element array, with the last element a null (remember that in the LC-3, each 8-bit character occupies the lower byte of a 16-bit word, so the last word in the array will be x0000). Adjust your code from exercise 3 to create a 10 character c-string (i.e. 10 input characters terminated with the null character). Load the starting address of the string into R0, then use TRAP x22 to output it to the monitor, just as you did with the c-string constructed by the .STRINGZ pseudo-op.

    .ORIG x3000

; take 10 character input from user
    LEA R3,Label    ; load array base addr in R3
    LD R2,Ten    ; load 10 in R2 (counter)
Input
    TRAP x23    ; input character
    STR R0,R3,#0    ; store inputted char in memory
    ADD R3,R3,#1    ; increment array base addr
    ADD R2,R2,#-1    ; decrement counter register R2
    BRp Input    ; branch to input if R2 is positive
    LD R0,Null    ; load Null in R0
    STR R0,R3,#0    ; store Null at end of array
       
    LEA R3,Label    ; load array base addr in R3
    LD R2,Ten    ; load 10 in R2 (counter)

; add 1 to each character
Add1
    LDR R0,R3,#0    ; load value from mem in R0
    ADD R0,R0,#1    ; increment R0 so it'll be plus 1 character
    STR R0,R3,#0    ; store inputted char in memory
    ADD R3,R3,#1    ; increment array base addr
    ADD R2,R2,#-1    ; decrement counter register R2
    BRp Add1    ; branch to Add1 if R2 is positive

; output characters by using TRAP x22 from memory address stored in R0 to Null
    LEA R0,Label    ; store base array addr in R0
    TRAP x22    ; display output from memory address from R0 untill it founds Null

    HALT
Label    .BLKW #11
Null    .FILL x0000
Ten    .FILL #10
    .END

Now write a routine that takes a sequence of 10 characters from the keyboard (echoing each character as it is input) and stores them in an array. Set up a loop that traverses the array adding 1 to each value (this will have the effect of turning a into b, L into M, 8 into 9, etc.) Finally, traverse the array again and output the 10 new characters to the screen. A simple way to set up an array is to use the .BLKW pseudo-op: label .BLKW #10 This sets aside 10 locations in memory, starting at the address "label". You can then load this address into a register using the LEA instruction: LEA R4, label This decodes "label" to the memory address it stands for, and loads that address into register 4 (note that this is quite different from LD, which loads the contents of the memory location "label" into the register; LEA doesn't read anything from memory, it just decodes the address itself).Once you have the starting address of the array in a register, you can use LDR & STR instructions to access it. How will you access the successive addresses? (Note: you may hard-code the number 10 as the loop counter).

    .ORIG x3000

; take 10 character input from user
    LEA R3,Label    ; load array base addr in R3
    LD R2,Ten    ; load 10 in R2 (counter)
Input
    TRAP x23    ; input character
    STR R0,R3,#0    ; store inputted char in memory
    ADD R3,R3,#1    ; increment array base addr
    ADD R2,R2,#-1    ; decrement counter register R2
    BRp Input    ; branch to input if R2 is positive

; add 1 to each inputted character
    LEA R3,Label    ; load array base addr in R3
    LD R2,Ten    ; load 10 in R2 (counter)
Add1
    LDR R0,R3,#0    ; load value from mem in R0
    ADD R0,R0,#1    ; increment R0 so it'll be plus 1 character
    STR R0,R3,#0    ; store inputted char in memory
    ADD R3,R3,#1    ; increment array base addr
    ADD R2,R2,#-1    ; decrement counter register R2
    BRp Add1    ; branch to Add1 if R2 is positive

; output each new character
    LEA R3,Label    ; load array base addr in R3
    LD R2,Ten    ; load 10 in R2 (counter)
Output
    LDR R0,R3,#0    ; load value from mem in R0
    TRAP x21    ; display character stored in R0 on console
    ADD R3,R3,#1    ; increment array base addr
    ADD R2,R2,#-1    ; decrement counter register R2
    BRp Output    ; branch to Output if R2 is positive

    HALT
Label    .BLKW #10
Ten    .FILL #10
    .END

You should be familiar with c-strings from C or C++. They are simply a sequence of characters terminated with a null character ( x00). The LC-3 pseudo-op .STRINGZ takes a text string as a parameter and builds a c-string: label .STRINGZ "Hello world!" ;you're probably sick of "hello world" by now ... ; so make your own message! This pseudo-op stores the characters of the string, one per memory location, starting with the location "label". A null (x00) is written to the memory location following the last character. The TRAP x22 instruction will take the contents of R0 to be the starting address of a c-string, and output each character of the string until it hits the null. Write code that creates a message using .STRINGZ and outputs it to the screen using TRAP x22. Examine the memory locations starting with "label" to make sure you understand how the assembler has set up the string.

    .ORIG x3000
    LEA R0,Label    ; load array base addr in R3
    TRAP x22    ; output from address in R2 untill it gets x0000 (null)
    HALT
Label    .STRINGZ "Hello World!"    ; create string array in memory
    .END