You are to write several macros that deal with input and output, to make them part of a macro library, and to compile, link and execute a program that has been written to rely on these macros in order to work. In the PROJECT directory, you will find a file named MYMACROS.MAR that contains four macros designed to deal with input from a file in much the way such input would be handled by C++. Here is a brief description of each macro that you are given and its arguments.
OPENIN stream, filedescThis macro is used to open a file for input; it takes two arguments - the first is the name to be associated with the input stream; the second is the label on a fixed length string descriptor for the file's name. OPENIN opens the file and associates it with the stream name. It also defines several storage areas that are used by other macros; these areas have labels that include the stream name as part of the label. These areas are
FLAG'STREAM an indicator for whether or not the buffer is empty SIZE'STREAM holds the number of bytes remaining in the buffer POS'STREAM location in the buffer where the next byte will come from STREAM'BUF the file buffer (capable of holding 200 bytes) STREAM an indicator for whether or not end-of-file has been reached
CLOSEIN streamThis macro closes the input file and terminates the association of the stream name with the file that was specified in the OPENIN.
READREC streamThis macro reads one record from the file into the STREAM'BUF area, appends a blank character to the end of the bytes input, sets SIZE'STREAM to the number of bytes read in + 1 for the blank, sets POS'STREAM to zero (beginning of the buffer), and sets FLAG'STREAM to indicate the buffer is not empty. If the attempt to read from the file fails, READREC sets the end-of-file indicator, STREAM.
BEOF stream, destinationThis macro tests the STREAM indicator and branches to the destination if the indicator shows that end of file has been reached.
CHARIN stream, chThis macro takes the next character from the input stream (the next buffer position) and puts it in ch. If it is necessary to refill the buffer, CHARIN does this. When the last character in the buffer is taken, CHARIN sets FLAG'STREAM to indicate another file read is needed.
You are to add five macros to this library; below are their descriptions.
STRINGIN stream, stringThis macro is to take a sequence of characters from the STREAM and put them into STRING, storing them as a null-terminated string. STRINGIN must skip leading white space (blanks) until a non-blank character is found to begin the string and then put all characters taken into STRING until a blank character is taken. Because of the actions of READREC, even the end of a line is marked by a blank character. The suggested way to write STRINGIN is to use CHARIN in two loops: the first loop skips white space; the second loop takes characters for the string until white space is reached. After moving the characters to STRING, STRINGIN must place a null character (#0 byte) after the last character.
STRLEN string, lengthThis macro is to count the number of characters in a null-terminated string at STRING. The suggested way to do this is to make a counting loop that looks for the null character at the end of the string. Then, put the count in LENGTH. You should assume that LENGTH is a longword; however, it may be in memory or a register.
INTIN stream, numberThis macro is to take a sequence of digit characters from the STREAM, convert them to a longword integer and store them at NUMBER. NUMBER may be a label on memory or a register. The suggested way to write INTIN is to use STRINGIN to move a sequence of digit characters into a storage area within INTIN, determine the length of the sequence with STRLEN, and then convert the leading separate numeric string to a longword using the two conversion instructions.
FILEIN stream, form, locationThis macro is to accept a character, string, or longword integer from STREAM and store the value at LOCATION. The value of FORM must be a C(c) to indicate input of a character, S(s) to indicate input of a string, or I(i) to indicate an integer. The suggested way to write FILEIN is to make a decision based on the FORM, using the CHARIN macro to get a character into LOCATION, using the STRINGIN macro to get a string into LOCATION, and using the INTIN macro to get an integer into LOCATION. For characters and integers, LOCATION is allowed to be a register or a memory location; for strings, LOCATION must refer to memory.
SCREENOUT form, locationThis macro is to output (using writestr and writeint) a character, string, or longword integer held at LOCATION to the screen. The basic idea is similar to FILEIN - the value of FORM must be a C(c) to indicate output of a character, S(s) to indicate output of a string, or I(i) to indicate output of an integer. The LOCATION is allowed to be in any reasonable form for integers and characters - memory, register, even literal. The suggested way to write SCREENOUT is to make a decision based on FORM, using writestr to output a character or string (you will have to determine the length of the string with STRLEN) and using writeint to output an integer (you may assume an 11 digit output field).
Use the techniques described in the hints to create the macro library with all of these macros (the given ones and the ones you add). The library must be named MYMACROS.MLB Then, assemble the program P6DEMO.MAR which you will find in the PROJECT directory. This program uses the macros in MYMACROS.MLB extensively. The program reads a file named THEBIRDS.DAT which you will also find in the PROJECT directory; this file is similar to the file used in project #5. You need to copy all three files, MYMACROS.MAR, P6DEMO.MAR, and THEBIRDS.DAT to your own directory.
Hand in all of the following for this project: a .LIS file for P6DEMO.MAR and a simple printout of MYMACROS.MAR. Also, copy the executable for the program (P6DEMO.EXE) to the HANDIN directory giving it a name based on your own name. If I were copying the file, I would give a command like:
COPY P6DEMO.EXE HANDIN:WOLFE.EXEOn the next page is a copy of the P6DEMO.MAR file.
; This program works with a file that is similar to the one used in
; project 5. This program reads the last name and first name into
; strings (that work a lot like C++ strings) and then reads in the
; five bird counts and sums them together. Finally, the program
; displays the names (first then last) and the total birds seen for
; each person. This program completely relies on macros to work.
;
.title filesummary
.library /project:iopack/
.library /mymacros/
easyio
cr=13
lf=10
first: .blkb 20 ; Watcher's first name
last: .blkb 20 ; Watcher's last name
count: .blkl 1 ; Number of birds seen
crlf: .asciz
title: .asciz /Watcher's Name Total Birds/
thefile: .ascid /thebirds.dat/
.entry start,^m<>
openin watch, thefile ; Open the file
screenout s, title ; Display titles
top: filein watch, s, last ; Read last name
beof watch, fini ; Exit on eof
movab last, r6 ; Replace comma
strlen last, r1
addl2 r1, r6
movb #^a/ /, (r6)
filein watch, s, first ; Read first name
filein watch, i, r10 ; Make 1st the total
movl #4, r6 ; Set loop counter
again: filein watch, i, count ; Read a bird count
addl2 count, r10 ; Add to total
acbl #1, # 1, r6, again
screenout s, first ; Display first name
screenout c, <#^a/ /> ; One space
screenout s, last ; Display last name
strlen first, r6 ; Display sufficient
strlen last, r7 ; spaces to fill out
addl2 r6,r7 ; to 25 characters
incl r7
subl3 r7,#25,r7 ; Display one space
shift: screenout c, <#^a/ /> ; at a time
sobgtr r7, shift
screenout i, r10 ; Display total count
screenout s, crlf ; Finish the line
brw top
fini: closein watch
$exit_s
.end start