Section 9.2
Assembling and running CSC-1 programs

You can assemble and execute CSC-1 programs using a simulator. Your instruction will tell you how you to the simulator and what the commands are to use it. This section will discuss basics.

First, let's go over once again a few particulars about the memory organization and data in the CSC-1 computer.

This last means that the values that can be stored in registers and in memory words are:

-32768 to +32767      for signed values (2's complement)
0 to 65535            for unsigned values

All values are actually stored as unsigned. The C, N, Z and V bits are set appropriately when the A register is changed. You may input numbers as signed (within the range -32768 to +32767) and the program will convert them to their unsigned counterparts. For example, -1 is 65535.

Here are some more details of the CSC-1 Assembler Language. These issues relate only to syntax and format of the source programs.

The basic line of an assembler program consists of:

label:    opcode    operand     ; comments

The opcode is a 2 or 3-letter code, such as NOP, ADD, or JMP. All of them are listed below.

A pseudo-op called NUM is not a machine instruction of the CSC-1, but instead tells the assembler to set aside one word of memory and put the indicated value into it. The values which follow NUM may be signed integers from -32768 up to +32767, or unsigned integers from 0 to 65535, in which case the letter "u" appears at the end, or unsigned binary numbers from 0 up to 1111111111111111 (16 ones) which is 65535. The letter "b" appears at the end of such binary numbers.

A:        NUM   10010b
B:        NUM   45389u
C:        NUM   -2738

Labels must be alphanumeric, starting only with a letter and followed by 0 or more letters or digits. When labels are declared, they end in a colon. Labels may be declared only once, although they may be referenced any number of times from the operand field of an instruction.

Operands are either labels or numbers. If they are labels, then they are turned into numbers by the assembler. The numbers into which labels are translated are the addresses at which those labels were declared. The LDI instruction must not have a label as its operand, since it loads a constant number into the A register. Other instructions such as RET and HLT must not have any operand at all.

Comments begin with a semicolon and go to the end of the line. A line may be entirely blank or may begin with a semicolon, in which case the whole line is treated as a comment and no code is generated for it.

You can tell the assembler to put a label at a certain location in memory by starting the line with =nnn where nnn is an integer and specifies an address. For example, to place a list of 3 integers at location 1000, do:

=1000
NUMBERS:   NUM 17
           NUM 256
           NUM -4

It is also common to tag at least the first instruction with a label, as shown above. The number 17 will be placed into word 1000, 256 into word 1001, and -4 into word 1002.

Since addresses go from 0 up to 4095 inclusive, no number greater than 4095 may appear after the equals sign.

Complete programs will be shown in the next section.


Here are all the CSC-1 instructions:

LOD  X           *Load direct                 A <- m[X]
STD  X            Store direct                m[X] <- A
LDS              *Load secondary              A <- m[S]
LDI  X           *Load immediate              A <- X
STS               Store secondary             m[S] <- A
A2S               A to S                      S <- A
S2A              *S to A                      A <- S

ADD  X           *Add                         A <- A + m[X]
SUB  X           *Subtract                    A <- A - m[X]
AND  X           *And (bitwise)               A <- A and m[X]
OR   X           *Or (bitwise)                A <- A or m[X]
NOT  X           *NOT (bitwise)               A <- not m[X]
SHL              *shift left (1 bit)          A <- A * 2
SHR              *shift right (1 bit)         A <- A / 2
NOP               null operation              do nothing, waste time

JMP  X            jump                        PC <- X
JZ   X            jump if Z bit is set        if Z=1 then PC <- X
JV   X            jump if V bit is set        if V=1 then PC <- X
JC   X            jump if C bit is set        if C=1 then PC <- X
JN   X            jump if N bit is set        if N=1 then PC <- X
JP   X            jump if N bit is not set    if N=0 then PC <- X
HLT               halt                        stop executing
CAL  X            call subprogram             S <- PC + 1; PC <- X
RET               return from subprogram      PC <- S

* = this instruction sets the CNZV bits

The "X" following some instructions denotes an address, which can be between 0 and 4095 inclusive. For LDI, the "X" is a constant integer value, also between 0 and 4095 inclusive.


Now we will discuss a few details of how to run the simulator. First you must start it. Then you load a source file written in CSC-1 assembler language. This file's name must always end with the extension .as When you load the assembler file, the software automatically assembles it into machine code and checks for errors. This phase writes a file whose extension is .o (for output of the assembler phase.)

Then you will run it by pressing buttons. You can run the program until it finishes by pressing the RUN button, or you can run only the next line of machine code by pressing 1 step. If you press the RUN button, you can interrupt it to regain control or stop a runaway program.

As the program executes it prints one line per instruction. The line tells how many time ticks have occurred since the program started and also what memory address the instruction came out from. Then the instruction is displayed in assembler form, although any preceding label is not shown. Only the opcode and operand are given. Next the contents of the A and S registers are given in both binary and unsigned decimal.

There is a big long textfield at the bottom into which you can type more commands. One of these is the m command which allows you to look at memory. Specify the single memory location's address right after the m. For example, to look at the byte value in location 1000, type

>> m1000

and press RETURN.


You can also change the contents of a memory word by putting =value
after the m command.  For example to store 28 into memory word
1000, type

>> m1000=28

You can store negative integers from -32768 to +32767, or positive integers
from 0 up to 65535.  However, if you put in positives greater than 32767,
you must put a "u" at the end to indicate this is an unsigned value:

>> m1000=48031u

And you can store binary numbers directly into memory.  You must suffix them
with "b":

>> m1000=1101010000b

All binary values are treated as unsigned numbers, with the maximum being
65535, or 1111111111111111 (16 ones).

You can change the three main registers: a, s and pc, although it is not
recommended that you do this unless you really know what you are doing.
Following are some examples of putting a new value into a, s and pc:

>> a=873 >> a=-1 >> s=65536u >> pc=4095

The program counter cannot be given a negative number, and its maximum value
is 4095, since there are 4096 words in memory.

To restart the current program, press the RESTART button.
This leaves the same program in
memory, sets all the registers to 0 and starts at the beginning.
It reloads the program from the .o file and resets all memory
locations.

Another handy feature is the ability to set a breakpoint, which is a location
at which the computer will stop after it executes.  To set a breakpoint, type
"b" followed by the memory address:

>> b15

In order to know where you want to set it, you must study the .lis file.
Then use "xx" to execute a bunch of commands.  When the computer is just about
to execute the instruction at address 15, it will halt and give you back the
prompt, at which point you can use any commands, inspect memory, change
things and possibly change the breakpoint.  If you don't change the breakpoint
it stays in effect.  To get past the breakpoint, just type "x" to do the next
instruction, or "xx" to continue.

To see what the breakpoint is currently set to, use

>> b?

and to remove the breakpoint entirely, use

>> b-

You can always set it later to some valid address.  There is only one
breakpoint available in this computer.