TR is used to translate one string of characters to another string of characters based on a translate table which defines the substitutions which should occur. For instance, TR could be used to convert a string of characters from lower case to upper case, or from ASCII to EBCDIC.

 

Operand 1 designates a string contain in memory which is to be translated. Operand 2 designates the translate table. This table is also called a table of functions. TR translates one byte at a time, starting with the leftmost byte of Operand 1, proceding from left to right. Each byte that is translated is used as a displacement into the table. The function byte that is found in the table is substituted for the byte in Operand 1. Since a byte can contain any value from X00 to XFF, the table of functions is usually 256 bytes long to accommodate the range of addresses from table + X00 to table + XFF.

 

Let us consider how a particular byte is translated using a table of functions called TABLE. For example, how would a byte containing XA2 be translated? Since XA2 = 162 in base 10, XA2 would be replaced by the byte at address TABLE+162. In other words, the byte we are translating acts as a displacement into the table, and is replace by the table byte in that position.

 

Consider the following example. To keep things simple, we begin with a small ( 5 bytes ) table and assume that the bytes in the string which is being translated generate displacements that stay inside the table. ( For safety, most TR tables are 256 bytes in length. ) We assume the following definitions.

 

STRING DC X030201

TABLE DC XFF01AABB00

 

We issue the following command.

 

TR STRING,TABLE

 

The execution of this instruction is graphically illustrated on the next page. Let us consider a byte by byte description of the execution of TR. The first byte of String, x03, is used as a displacement into TABLE. The byte at address TABLE+3, which is XBB, replaces the first byte in STRING. This means the string temporarily looks like XBB0200. Next, the second byte of STRING, X02, is used as a displacement into the table. As a result the byte at TABLE+2, which is XAA, replaces X02 in string. Finally, the third byte in STRING, X01, is used as a displacement into the table and the byte at TABLE+1, X01, replaces X01 in STRING. After the TR has executed, STRING contains XBBAA01.

To be safe when using TR you should always code a translate table that is 256 bytes long so that you can handle any possible displacement that might be used in the translation. The only exception to this rule occurs when you are sure that the bytes you are translating fall within a specified range.

 

How could you define a translate table that translates every character to itself? Since each character would be used as a displacement to itself, a translate table of this type would look like X000102030405060708090A0B0C0D0E0F10.... There is an easy way to construct such a table: TABLE DC 256AL1(*-TABLE)

This technique works by defining 256 byte address constants of length 1. When defining the first byte in the table the asterisk refers to the same address as TABLE, and so *-TABLE is 0. After defining the first byte the location counter advances and *-TABLE is 1 when defining the second byte. Continuing in this fashion, the expression *-TABLE takes on all the values from 0 to 256. As a result, we create a table that translates every character to itself. This is important because in many applications, most of the characters we encounter are left unchanged by TR.

 

For example, suppose we want to translate lower case letters to upper case. To do this we use the following table definition.

 

TABLE DC 256AL1(*-TABLE)

ORG TABLE+Ca

DC CABCDEFGHI

ORG TABLE+Cj

DC CJKLMNOPQR

ORG TABLE+Cs

DC CSTUVWXYZ

ORG

 

Notice that most bytes translate to themselves. An originate directive is used to position to the table position that contains a lower case a. This is followed by a DC that defines the upper case letters A - I. This technique is repeated for j and s. Since the lower case letters occur in 3 blocks ( A - I, J - R, and S - Z ) the DCs above provide for the conversion from lower to upper case.

 

Some Unrelated TRs:

TABLE DC X0302010300 VERY SMALL TRANSLATE TABLE

A DC X040404

B DC X000003020201

C DC X00000000

D DC X01010101

E DC X020202

F DC X010203

... Result:

TR A,TABLE A = X000000

TR B,TABLE B = X03030301010102

TR C,TABLE C = X03030303

TR D,TABLE D = X02020202

TR E,TABLE E = X010101

TR F,TABLE F = X020103

 

1. Start with a table that translates each byte to itself ( TABLE DC 256AL1(*-TABLE) ). Use ORG to position yourself to an appropriate character ( ORG TABLE+CX positions you at X.) Redefine the area with a DC.

 

2. Avoid translation errors by defining all translate tables with 256 bytes.