CSE 111, Fall 2000

Great Ideas in Computer Science

Lecture Notes #33

MACHINE ARCHITECTURE
AND ASSEMBLY LANGUAGE

6.    Another sample P88 program.

a)    Here's another sample P88 program.  This one
        is the compiled version of the following Pascal
        program (both of which are available from the
        "Comp1" compworks program under the name
        "while.pas"):

        program while;
        var x, y : integer;
        begin
            x := 0;
            while x < 5 do
                x := (x + 1);
            y := 0
        end.

b)    Let's first hand trace this Pascal program;
        note that it just increments x in a while loop,
        and stores the final value in y; it does not
        output anything.

        We only have to keep track of 2 memory
        locations:  x & y, but I will also keep track
        of the Boolean test, and I will add a "comment"
        column:
x y x<5? comments
0     x is initialized to 0 (x := 0)
    true the test is tested; since it's true,
we enter the body of the while
loop;
1     x is incremented (x := x+1)
    true we loop back to the test
it's still true, so we're still in
the loop
2     x := x+1
    true  
3      
    true  
4      
    true  
5      
    false this time, x is not < 5, so the
test is false, we exit the loop,
and go to the next instruction
  5   the final value of x is stored
in y (y := x)

c)    Here's the P88 assembly-language version of
        the program created by compiling the Pascal
        program for our P88 simulated computer:

        line    label   instruction
        ===   =====  =========

         0                  COPY    AX, #C0
         1                  COPY    X, AX
         2      L0        COPY    AX, X
         3                  CMP     AX, #C1
         4                  JNB     L1
         5                  COPY    AX, X
         6                  ADD     AX, #C2
         7                  COPY    _E0, AX
         8                  COPY    AX, _E0
         9                  COPY    X, AX
        10                  JMP     L0
        11      L1         NO-OP
        12                  COPY    AX, X
        13                  COPY    Y, AX
        14                  #C0     0
        15                  #C1     5
        16                  #C2     1
        17                  _E0     0
        18                  X       0
        19                  Y       0
        20                   #L1    2
        21                   #L2    11

OK:  Take a deep breath, and let's hand-trace this:

We need to keep track of 2 CPU registers:  AX & CF,
& we need to keep track of several Memory registers,
some of which will never change their values.

To make it a bit easier (I hope) to follow, I won't
record the registers whose values don't change;
they are #C0, #C1, #C2, #L1, #L2.  (Notice, for what
it's worth, that they are all and only the registers
whose names begin with "#"!)
AX CF _E0 X Y comments
0 NB 0 0 0 these are the initial values
stored in these registers
0         #C0 is copied into AX in
order to make sure that
the 0 that is to be stored
in X is placed in AX
      0   the 0 in AX is stored in X;
thus, the first 2 lines of
the P88 program
correspond to "x := 0"
0         we need to compare X to 5,
so we need to put X in AX
  B       we compare AX to the 5
that is stored in #C1;
since the 0 in AX < the 5 in #C1,
the CMP instruction puts
"B" in the CF register
          next, the JNB L1 command
is fetched, but it is not
executed, since CF <> NB,
so the instruction on the
next line, line 5, is fetched
          this means that we enter
the body of the loop
0         X is stored in AX again,
because we are getting
ready to execute the body
of the loop, which first
requires us to add x+1
1         #C2 (i.e., 1) is added to
the 1 in the AX
(which of course just
came from X),
so we've just done "x+1"
    1     the sum of x+1 is stored in _E0
temporarily
1         the sum, now stored in _E0,
is copied into AX where it belongs
(remember: x := x+1,
so after adding 1 to X,
we store the new value back into X)
      1   we store it in X
          we unconditionally jump back to L0;
thus, we begin the loop again.
Note that to get to L0,
we look up the memory register
whose name is "L0",
find that it contains 2,
put 2 in the IP,
and so that becomes the next instruction
          So as not to bore you
or confuse you
I will not trace the rest of the loop.
Instead, let's assume that we have
just gone through the repetition
in which we finally incremented X to be 5.
So the next line shows the current content of X:
      5   Next, we jump back to L0
5         We copy X into AX
  NB       This time, x is not < 5,
so the CF is set to "NB"
          We next jump on NB to L1
which is instruction 11
          It's a "no-op";
i.e., no operation is performed
5         X is copied into AX
to get it ready for storage in Y
        5 It is stored in Y;
end of program

7.  Another example (not done in lecture):

Here is a program to input a series of non-negative
integers, using a negative integer to let us know when
to stop inputting, multiply each by 3, then add them
up, and print the result:

e.g.)    I/P:    2, 4, 6, -1

            These are converted to:    6, 12, 18
            (the -1 is ignored; it's just there to tell
            the program when the input is finished)

            Then they are added up:    6+12+18=36

In Pascal, this would be:

            sum := 0;
            readln(x);
            while x >= 0 do
                begin {while x >= 0}
                    sum := sum + (3 * x);
                    readln(x)
                end;   {while x >= 0}
            writeln(sum)

You should either type this into Unix, compile it, and
run it, or else handtrace it, to make sure that you
understand how it works and that it does the job.

Here's a P88 version (using the "jump to label start"
technique that I mentioned in lecture), with
comments:

            JUMP START
            SUM 0            ; this is data
START   IN AX            ; get the 1st integer
LOOP    CMP AX, 0      ; loop & maintain sum
                                 ; (if AX < 0, then CF = B
                                 ;                 else CF = NB)
             JB END         ; jump to "end" if a negative
                                ;  integer is input
             MUL AX, 3
            ADD AX, SUM
            COPY SUM, AX
            IN AX             ; get the next integer
            JMP LOOP        ; go back to beginning of
                                    ; while loop
END      COPY AX, SUM
            OUT AX            ; print sum
            HALT

You should handtrace this to make sure you
understand it!
 

8.  Yet another example (also not done in lecture):

This is from Biermann, p. 268, #3:

I/P:    2 integers, call them "small" and "large"
O/P:    small+1, small+2, ..., large-1

e.g.)    I/P = 3, 7
          O/P = 4, 5, 6

e.g.)    I/P = 1, 100
          O/P = 2, 3, 4, ..., 97, 98, 99

In Pascal:

        readln(small);
        readln(large);
        small := small + 1;
        while small < large do
            begin {while small < large}
                writeln(small);
                small := small + 1
            end    {while small < large}

Strategy (in almost-flowchart form):

            input "small"
                    |
                    v
            input "large"
                    |
                    v
            add 1 to small   <----------\
                    |                                    |
                    v                                   |
            result < large?--true--> output result
                     |
                     | (false)
                     v
                   halt

But:  the 2nd time through, we don't want to add 1 to
        "small"; rather, we want to add 1 to the current
        sum.

Solution:    Keep a running total in AX
                    & use "add 1 to AX":

            input "small"
                    |
                    v
            input "large"
                    |
                    v
            AX := small
                    |
                    v
            AX := AX + 1 <-------------\
                    |                                     |
                    v                                    |
               AX < large? -- true --> output AX
                    |
                    | (false)
                    v
                  halt

In P88 code:

                IN AX
                COPY SMALL, AX
                IN AX
                COPY LARGE, AX
                COPY AX, SMALL
increment  ADD AX, 1
                CMP AX, LARGE
                JNB print
                JMP end
print         OUT AX
                JMP increment
end            HALT

Again, make sure you understand this, by handtracing
it.  I suggest you try input 3, 7 as above for one
example, and maybe 1,10 as another example.
 


Copyright © 2000 by William J. Rapaport (rapaport@cse.buffalo.edu)

file: 111F00/lecturenotes33.01dc00.html