11.3.2 Variables, assignment, and sequence
This part of Section 11.3 explores how the instructions presented above can be used to construct simple assembly language programs. The programs we describe here will be limited to declaring and initializing variables, simple assignment, and sequence. Later parts of this section examine more advanced concepts, such as how selection and repetition can be implemented in assembly language
Figure 11.3 contains a complete assembly language program that implements the high-level language assignment statement:
total = abc + xyz;
This statement is written in the Watson JavaScript language, which was introduced in Chapter 8, as are all other high-level language statements used in this chapter. As you will recall from your study of JavaScript, this statement adds the current value of the variable abc to the current value of the variable xyz and places the result into the variable total. Of course, abc and xyz must contain valid data when this statement is executed in order for a meaningful result to be assigned to total. Let’s assume for the purposes of this example that abc contains the value 2 and xyz the value 3. After this statement executes the value of total should be 5.
Figure 11.3: Assembly language version of the statement: total = abc + xyz;
How can the actions of this high-level assignment statement be implemented using low-level assembly language instructions?
The first thing that must be addressed is how variables such as total, abc, and xyz can be set up and initialized. As you know, variables are simply “named locations in memory that hold a value of a particular type.” The Watson Assembly Language supports only one type of data, integers.[1] Hence all that need concern us here is the fact that a variable is a named location in memory.
Watson Assembly Language contains two separate statements for “reserving” and naming memory locations. These statements are: .BLOCK and .WORD. They have the following general forms:
The first statement, .BLOCK, reserves a block of memory some number of words long and gives that block a label or name by which it may be referred. A “word” is the amount of space normally needed to store an integer value. So, for example, the statement:
TOTAL .BLOCK 1
reserves a block of memory one word long and gives it the name “total”. The effect of this statement is essentially to declare a variable named “total”. Hence, it is roughly equivalent to the Watson JavaScript statement:
var total; // Numeric
with the exception that the variable “total” can only hold whole numbers (not fractions) since Watson Assembly Language supports integers as its only “data type”.
While the .BLOCK statement declares a variable, it does not initial it. To both declare and initialize a variable, the Watson Assembly Language includes a .WORD statement. The .WORD statement always reserves exactly one word of memory for a variable but it also allows the programmer to specify an initial value for that variable. For example, the statements:
ABC .WORD 2
XYZ .WORD 3
not only reserve one word of memory for each of the variables ABC and XYZ, but also initialize ABC to the integer value 2 and XYZ to the integer value 3. These statements have essentially the same effect as the Watson JavaScript statements:
in that both groups of statements declare the variables and initialize them. There are, however, subtle differences in the ways these two groups of statements accomplish their goals. The high-level statements first declare the variables and then, in separate statements, initialize those variables. The assembly language statements declare and initialize the variable in a single “step”. Since Watson JavaScript does not support declaring and initializing variables in a single instruction, there is no “direct” translation of .WORD to Watson JavaScript. Regardless, these four Watson JavaScript statements do accomplish the same tasks that the two .WORD assembly statements do.[2]
Now that we have seen how variables can be declared and initialized in assembly language, we can return to the problem at hand, which is trying to figure out how the assignment statement: total = abc + xyz; can be translated into assembly language.
Like most assembly languages, Watson Assembly Language has very limited support for directly manipulating the values stored in the computer’s main memory. Operations involving main memory are essentially limited to copying information back and forth between CPU registers and memory locations. The operation of copying a value from a memory location to a CPU register is known as “loading” a register. Copying the contents of a CPU register into a memory location is known as “storing” a register.
As discussed in Section 11.2, all mathematical and logical operations supported by the Watson Virtual Machine must be performed on registers, not memory locations. This means that variables (named locations in memory) cannot be directly manipulated in Watson Assembly Language. Instead, in order to use the contents of a variable, the value of that variable must first be copied into a register. The register may then be used as a “stand in” for the actual variable in mathematical and logical operations. If the contents of the register that represents the variable changes in any way, then the contents of that register must be copied back to the variable’s main memory location.
So, in order to add ABC and XYZ together, each must first be loaded into a register. The general form of the LOAD statement is:
LOAD destination register, source variable label
The Watson Virtual Machine supports sixteen general-purpose registers labeled 0-9 and A-F. As long as we ensure that ABC and XYZ are placed into different registers, it does not matter which registers we choose. (If we tried to place both values into the same register, the first value would be destroyed when the second was loaded.) The following two assembly language instructions copy the values held in the memory locations labeled ABC and XYZ into registers D and E, respectively.
LOAD REGD, ABC
LOAD REGE, XYZ
The first statement may be read as “load into register D the value of variable ABC”. The second one reads similarly. After these statements execute, register D will contain the value 2 and register E will contain the value 3, since ABC was initialized to 2 in its .WORD declaration and XYZ was initialized to 3 in its .WORD declaration.
We are now ready to add the two values together. The form of the ADD statement is:
ADD result register, first operand register, second operand register
Any of the sixteen general-purpose registers in the Watson Virtual Machine could serve as the result register, including register D or E. Assuming we choose register F to hold the result, the ADD statement would have the following form:
ADD REGF, REGD, REGE
When this statement is encountered register D will contain a 2 and register E will contain a 3, so the value 5 will be placed into register F.
Many people find the form of the ADD statement initially confusing due to the fact that the result register is listed first. Their confusion often clears up when they realize that the registers are in exactly the same order that they would appear if the ADD statement were written in a more “high-level” syntax like:
result register = first operand register + second operand register ;
or in the current example:
REGF = REGD + REGE ;
At this point, the value of variables ABC and XYZ have been successfully added; their sum placed into register F. All that remains is for this sum to be stored into the variable TOTAL. The general form of the STORE statement is:
STORE source register, destination variable label
In order to store the contents of register F into the memory location associated with the variable TOTAL, a statement of the following form will be required:
STORE REGF, TOTAL
Finally, the HALT statement, which signals the logical end of the program, must be included in the program. Execution of the program ceases whenever the Watson Virtual Machine encounters a HALT statement.
To briefly recap, the Watson Assembly Language program of Figure 11.3 implements the assignment statement total = abc + xyz; by loading the value of ABC into register D and the value of XYZ into register E. The contents of both of these registers are added together with the sum placed into register F. The contents of register F are then stored into variable TOTAL and the program halts. This process of copying values from the main memory locations that represent variables into CPU registers, manipulation of those values by “register-based” instructions, and then copying of results back to main memory is typical of most assembly language programs.
Another assembly language program is presented in Figure 11.4. This program is similar to the program of Figure 11.3 in that it too implements a single high-level assignment statement. In this case the statement is: x = x - 1;
The assembly language program begins by declaring the variable X and initializing it to 15, in preparation for implementing the actions of the assignment statement. The second line of the program loads the value currently held in X, 15, into register A. The third line of the program loads the value 1 into register B via the “load immediate” statement:
LOADIMM REGB, 1
The general form of the load immediate statement is:
LOADIMM destination register, value
Figure 11.4: Assembly language version of the statement: x = x - 1;
While the standard version of the LOAD statement contains the label of the memory location where the value to be loaded is held, the LOADIMM statement includes the value to be loaded directly in the statement – the value to be loaded appears in the statement “immediately” following the destination register. Load immediate statements are quite useful, but the values they can contain are generally limited to a rather narrow range. For example, the Watson Assembly Language limits load immediate values to the range –128 to +127.
The fourth line of the program
SUBTRACT REG0, REGA, REGB
subtracts the value held in register B from the value held in register A and places the difference in register 0. Since register A contains 15 (the current value of X) and register B contains 1, the value 14 will be placed into register 0 when this statement executes.
The general form of the subtract statement is:
SUBTRACT result register, first operand register, second operand register
As with the ADD statement, the registers of SUBTRACT appear in the same order they would if the statement were written in a more “high-level” form such as:
result register = first operand register - second operand register ;
Keeping this “high-level” form of the SUBTRACT statement in mind should help you to remember the correct order of the registers.
The fifth line of the program of Figure 11.4 copies the contents of register 0 into the main memory location associated with the variable X. This line has the effect of updating the value of the X to be one minus its previous value, thus completing the actions of the high-level assignment statement. Finally, line six of the program issues the HALT command causing execution to terminate.
Exercises for Section 11.3.2
Write an assembly language program to implement the high-level assignment statement:
diff = xyz – abc;
Write an assembly language program to implement the high-level assignment statement:
num = num + 4;
Write an assembly language program to implement the high-level assignment statement:
A = ( B + C ) - D;
Write an assembly language program to implement the high-level assignment statement:
A = 2 * ( B + C );
Footnotes
[1] Represented as two’s complement binary numbers. See Section 11.4.1 for details.
[2] It should be noted that true JavaScript, as well as many other common programming languages, like Java and C++, do support the ability to declare and initialize variables in a single statement.