R0/R1
and results will be returned in register(s). You may find that you do not
have enough registers to keep all of your variables in registers. In this case,
you will create variables to hold them.
The following list is the set of subroutines you must implement.
strlen(s)
- On entry R0
contains the
address of a valid (null terminated) C string. On exit, R0
contains the length.strcpy(dest, src)
- On entry R0
contains
a pointer to the destination string (dest
), and R1
contains a pointer to the source string (src
).
On exit, src
has been copied to dest
and
R0
contains a pointer to dest
.strcat(dest, src)
- On entry R0
contains
a pointer to the destination string (dest
), and R1
contains a pointer to the source string (src
).
On exit, src
has been appended to the end of dest
and R0
contains a pointer to dest
.strcmp(s1, s2)
- On entry R0
contains
a pointer to a string (s1
), and R1
contains
another pointer to a string (s2
). On exit R0
contains a negative number if s1 < s2
, zero if s1 == s2
and a positive number if s1 > s2
, based on the lexigraphic
ordering.printCC()
- Print the word NEGATIVE, ZERO, POSITIVE
depending on the value in register R0
. At exit, register
R0
contains the original value. Each word is followed by a
newline. Do not depend on the condition code being set on entry.
The test of strcmp()
uses this method.pack(b1, b0)
- Pack (combines) the lower 8 bits of R0
and the lower 8 bits of R1
and pack them into a single
16 bit quantity in R0
. The lower 8 bits of R0
will be in the upper 8 bits of the result.unpack(b)
- Unpack the 16 bits in R0
into
registers R0/R1
such that the upper 8 bits of R0
are stored in the lower 8 bits of R0
and the lower 8 bits
of R0
are stored in the lower 8 bits of R1
.getsp(dest)
- On entry R0
contains the
address of a buffer. Read characters from the keyboard until a newline
(ASCII 10
). Each pair of characters is packed into a single 16
bit value and stored in the memory pointed to by dest
. The newline
is not stored. On exit R0
contains dest
pointer.
You will need to experiment with LC-3 to determine the order of 8 bit characters
in the 16 bit word. Alternatively, you may read the lc3os.asm
for the PUTSP
trap instruction.strunpack(dest, src)
- On entry R0
contains
a pointer to the destination string (dest
) and register
R1
contains a pointer to the source string (src
).
The source is a packed string containing two characters per 16 bit word.
On exit, the packed string has been unpacked (one character per 16 bit word)
into dest
, followed by a null termination, and R0
contains the dest
pointer.
Enter
key. As with any
project, incremental development will improve your efficiency.
You might first write pseudo-code in a C or Java syntax to understand the algorithum for a subroutine. If your pseudo code uses variables, you may want to declare these variables for you subroutine. Declare them before the first statement of the subroutine. Although using variables may make your code a little longer, it is likely that you will get correct results more quickly if you use them. When you need a value, simply load it from the memory. When you update the value, write it back to memory. This is the load/store model.
When you write the LC-3 code for a subroutine, you may find it helpful if you
add comments in each subroutine that explain how you are allocating the registers.
For example, you might write ; R4 holds the count
.
Testing/debugging each individual subroutines follows a pattern:
lc3as
.Option
to the index of the routine you wish
to test. You may want to change the .FILL
value so that
you do not need to continually reset it as you write, and debug your
subroutine.Continue
the simulator/debugger. If you have set a breakpoint,
it will stop when your program reaches that line. Use Step/Next
to watch your code execute and examine registers and memory locations for
correctness. You will want to use Next
so that you do NOT
step into the traps GETS, PUTS, PUTSP, GETC, OUT
. You may step
into them, but you will find them very tedious to step through.
You may want to call one subroutine from another, or add subroutines to
accomplish specific tasks. Do not duplicate code in multiple places. Recall that
calling a subroutine from another subroutine requires careful handling of the
return address (R7
), and that registers from the calling routine
may be overwritten.
string.asm
using the Checkin tab of the
course website.