X-Instructions

In our class we are using the ASSIST software, which provides a number of extra "pseudo-instructions" for our use. These are not part of the assembly language itself, but they make it easier to do a number of common tasks we need to do. In the actual assembly language, all these things can be done without X-instructions, but some of them are a bit beyond the scope of this course.

We will use XREAD and XPRNT throughout the course, but we will eventually get away from XDECI and XDECO.


XDUMP

XDUMP is intended as a diagnostic tool. We can use it in two ways:

    XDUMP

or

         XDUMP,N

In the first case, XDUMP by itself will simply print out the values of all 16 registers, 8 on one line in two groups of 4 and then 8 on the next line. The values are printed in hexadecial format, 2 hex digits per byte.

In the second case, XDUMP will print out the values of N bytes in memory starting at the address. It prints these in hexadecimal value, two hex digits per byte. It may print more than N values, as it prints out a minimum of 32 bytes at a time. On the left side of the line, it prints the addresses of the bytes involved, and on the right side, between asterisks, we find the printed version of the bytes; most values do not print as anything useful.

If the length is omitted, a default length of 4 is used. The maximum allowable length appears to be 4095.

XDUMP counts the number of times it is called.

XDUMP actually uses another tool, XSNAP, to do its work, so the output from XDUMP refer to XSNAP.


XREAD

XREAD is used for input. The format for it is:

         XREAD address,N

This will read N bytes from "standard input" (a file) and store them in memory in consecutive bytes starting at the given address. Here 1 <= N <= 80. The address is a D(X,B) address.

XREAD will set the condition code:

     CC = 0 if all goes well
     CC = 1 if the end of the file is encountered  
     CC = 2 and CC = 3 are not used

For example:

         XREAD CARD,80

This will read 80 bytes and store them in CARD, which has presumably been declared as:

CARD     DS    80C


XDECI

Once we have read a line of data, we may want to interpret numbers on that line as binary numbers. XDECI will do this for us. The format for it is:

         XDECI register,address
The address is a D(X,B) address.

Suppose we have just read data into CARD, and there should be a number in the data. We use:

         XDECI 4,CARD

XDECI will start looking at bytes at the beginning of CARD. It will skip over blanks until it finds a non-blank character. It expects the first non-blank character to be '+' or '-' or a digit. Assume that happens. XDECI then will read up to 9 digits until it finds a non- digit character (such as a blank), and it will convert this number to binary and store it in register 4.

Along the way, what can happen? If the first non-blank character found is not what it should be, we have an error. The value in the register is not changed. Register 1 is set to the address of the bad character.

If more than 9 digits are found, we have an error. The value in the register is not changed. Register 1 is set to the address of the first character found after the digits.

If no error occurs, register 1 will be set to the address of the first character found after the digits.

Notice that XDECI will always change the value of register 1. Do not use 1 as the register in the XDECI instruction.

XDECI will always set the condition code:

     CC = 0 if the value is 0
     CC = 1 if the value is negative
     CC = 2 if the value is positive
     CC = 3 if an error occurs


XDECO

Suppose we have a value in a register and we want to convert it to a printable form. XDECO will do this for us. The format for it is:

         XDECO register,address

XDECO will convert the signed 32-bit binary value in the register into printable characters (base 10, with a leading minus sign if needed) and store it in the 12 bytes starting at the given address, right- justifed.

The address is a D(X,B) address.


XPRNT

XPRNT is used for printed output. The format for it is:

         XPRNT address,N

This will write the N bytes starting at the address into "standard output" (a file). It is our responsibility to ensure that each byte corresponds to a printable character. Here 2 <= N <= 133. The address is a D(X,B) address.

When we want printed output, we may want to worry about spacing. To handle this, we have carriage-control characters. Suppose we use XPRNT:

         XPRNT PLINE,121

The first character in PLINE will be interpreted as a carriage-control character. An actual mainframe printer will know how to make use of this:

         Value              Action
         -----         ----------------
         blank         single-spacing
          '0'          double-spacing
          '-'          triple-spacing
          '1'          advance the page

If the carriage-control character is interpreted, its value is not also printed. Other values are often also interpreted as single- spacing, but this is not guaranteed, and they will also not be printed. To avoid trouble with this, make sure you know what carriage-control character you are using:

PLINE    DC    C' '     Single-Spacing
         DS    120C

Sometimes if we have a complex line to print, it is a niusance to add up its length. You can actually have the assembler do this for you. We could have:

PLINE    DC    C'0'    Double-Spacing
     (complicated stuff)
     PEND     DC    0C

which we can print with:

         XPRNT PLINE,(PEND-PLINE)

Here the assembler will evaluate each of PEND and PLINE as an address (a number) and subtract to get the length of PLINE.


Example Program

* This program will read lines until it reaches the end of the file.
* Each line contains one integer.  The program finds the sum of the
* integers and prints it.
*
* Register Usage:
*   4 -- Number just read
*   5 -- Sum
*  15 -- Base register
*
IODEMO   CSECT
         USING IODEMO,15
         SR    5,5                 Set Sum = 0
TOPLOOP  XREAD CARD,80             Read a line
         BC    B'0100',ENDLOOP     If we found EOF, end the loop
         XDECI 4,CARD              Extract a number from the line
         BC    B'1110',OKAY        Do we have an error?
         XDUMP                     If so, get a dump and
         BR    B'1111',QUIT        end the program now 
OKAY     AR    5,4                 Accumulate the Sum 
         BC    B'1111',TOPLOOP     Repeat the loop
ENDLOOP  XDECO 5,OUTNUM            Put the Sum on the line
         XPRNT OUTLINE,81          Print the line
QUIT     BR    14                  Return to operating system
CARD     DS    80C                 Input record 
OUTLINE  DC    C'0'                Output line, double-spacing
         DC    10C' '
         DC    CL11'The sum is '
OUTNUM   DS    12C
         DC    CL47' '
         END IODEMO

Work your way through the example and make sure you understand how the pieces fit together.


Read more than one number from a line

Suppose the input line contains several numbers separated by spaces, like this:

         ___12345______6789___-7813___0___523___

We would like to read each of these numbers. How do we do it? Remember that XDECI sets register 1 = the address of the next character after the digits it reads. We can use that to control a loop, provided some non-digit character is eventually found to end the loop.

So declare CARD as follows:

CARD     DS    80C
STAR     DC    CL2' *'

and use two loops:

         SR    5,5                 Set Sum = 0
TOP1     XREAD CARD,80             Read a line
         BC    B'0100',END1        If we found EOF, end loop 1
         XDECI 4,CARD              Extract a number to start loop 2
TOP2     BC    B'0001',END2        On error, end loop 2
         AR    5,4                 Accumulate the Sum
         XDECI 4,0(0,1)            Extract next number
         BC    B'1111',TOP2        Repeat loop2
END2     BC    B'1111',TOP1        Repeat loop1
END1     XDECO 5,OUTNUM            Put the sum on the line
         XPRNT OUTLINE,81          Print the line

Notice that this version does not check much for bad data.

Why do we have ' *' as the marker at the end of CARD instead of just '*'? The reason is that we might have the last number right at the end of the line, so register 1 would be pointing at '*' anyway. We want to be sure that the inside loop ends when we reach the asterisk.