% Format: LaTeX \documentclass{lab} \usepackage{lgrind,emlines2,multicol,verbatim,rcs,prog,nbox,cols,xr} % Turn off lgrind's special handling of the vertical bar: %|- % $Header: C:/MICROP/ENLAB4/RCS/asmprim.tex 1.5 1995/02/13 07:23:46 Nick Exp Nick $ % For the external references (xr.sty): \externaldocument[enl4s:]{enl4s} \RCS$Revision: 1.5 $ \RCS$Date: 1995/02/13 07:23:46 $ \newcommand{\revision}{ver \RCSRevision{}% ,\hspace{0.8ex} \RCSDate% } % \setlength{\extrarowheight}{4pt} % \newcommand{\nBox}[2][40mm]{\parbox[c][3\baselineskip][c]{#1}{\centering#2}} % \DeclareRobustCommand{\inst}[1]{\texttt{#1}} % Font for showing instructions. % \newenvironment{prog}{\small\begin{alltt}}{\end{alltt}} \DeclareRobustCommand{\referenceNum}{EE/27/LA/21/95} % 6, 7,..., 21. \begin{document} \labHead \labTitle{0}{Lab primer: MC68000 assembly language} % For extended, inter-file cross references, need to fix the % lab number in the page \renewcommand{\thepage}{W0-\arabic{page}} \textbf{This lab primer is \emph{not} to be handed in. You need to bring this to every lab class, or you will find it hard to do your lab work. There is only one copy available for each person. If you forget to bring it with you to the lab, we may not have another to give to you.} \tableofcontents %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Introduction} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% This lab primer introduces many new concepts that you will apply in the laboratory. Your lab sheets will refer to this primer. You need to read the parts referred to by your lab sheets \emph{before} you come into the lab. I suggest that you use a highlighter as you read, highlighting the important points in different colours so that you can find them easily when you are in the lab. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{The 68000 \up} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The \CPU is the heart of the microcomputer system. We also call the \CPU a \up. A \up is a \CPU that is made in one integrated circuit, or \IC. We will look at how it works and how to program it. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \CPU registers} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:registers} There are 18 special storage locations in the 68000 called \emph{registers}. Figure~\vref{fig:registers} shows the arrangement of these registers and how they can be accessed by you, the programmer. \begin{figure} \begin{center} \input{register.pic} \end{center} \caption{Registers in the 68000. PC is program counter. A7 is the stack pointer. All registers are 32 bits wide, except for the status register which is 16 bits wide.} \label{fig:registers} \end{figure} Registers are very special storage locations: each has its own name. They are all located inside the \up. The \CPU can move data to and from the registers \emph{much} faster than to or from memory. For that reason, we try to keep data in \CPU registers while we can. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{Accumulator} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% An \emph{accumulator} is a special \CPU register which is used in nearly all arithmetic and logic instructions as one of the operands. In other \up systems, there may be only one accumulator. The 68000 has eight accumulators: D0, D1, D2, D3, D4, D5, D6 and D7\e. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{I/O ports and the 68230 parallel interface/timer chip} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:ioports} An \emph{I/O port} is a special memory location in an input or output hardware interface. An I/O port is a connection between a computer and the outside world. For instance, the keyboard, printer and mouse on a desktop computer all are connected to the PC through I/O ports. When we read from an input port, we cause input from something outside the computer. Data is transferred from outside to inside the computer through the input port. An input is a special sort of read operation. When we write to an output port, we cause data to be transferred from the computer to hardware that is outside the computer. An output is a special sort of write operation. In a memory-mapped I/O computer, such as the Flight-68k in our labs, we use ordinary data movement instructions to do input and output, such as \texttt{move} or \texttt{clr}. An input or output port has an ordinary address, like memory. The only difference is that an address decoder selects an I/O chip such as the 68230 PI/T instead of a memory chip. The I/O chip is connected to external hardware so that it may perform input and output. The special memory locations in the 68230 are called registers---they are all listed in table~\vref{tab:registerAddr}. You may read some more about them in the Flight-68k manual, in chapter 11 Here are some examples of input and output operations, as in our lab work: \begin{prog} move.b #$f,leds(a6) OUTPUT: Turn on the four LEDs on the right. move.b switch(a6),d0 INPUT from the dip switches into D0. clr.b keys(a6) OUTPUT zero to the keypad (port A) \end{prog} The first operation outputs the bit pattern 0000\,1111 to port~B, which is connected to the LEDs. This output operation is performed by writing to the port~B data register, which is at address \$800013\hex---see tables~\vref{tab:portAddr} and \vref{tab:registerAddr}. The second operation inputs from port~C, which is connected to the dip switches. This input operation is performed by reading the port~C data register, which is at address \$800019\hex---see tables~\vref{tab:portAddr} and \vref{tab:registerAddr}. The third operation sends the data value 0 out of the port~A data register, which is at the address 800011\hex. The names \texttt{leds}, \texttt{switch} and \texttt{keys} are named constants, defined in the file \texttt{flight.i}. See section~\vref{sec:equates} for more about these names.. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The interface card} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% On the 68000 microprocessor I/O interface card\footnote{I will call the 68000 microprocessor I/O interface card the \emph{interface card} from here on.} there are four devices, two for \emph{input} and two for \emph{output}. The input devices are a bank of eight \emph{dip switches} and a telephone \emph{keypad}. The output devices are a set of eight \emph{LEDs} (Light Emitting Diodes) and a \emph{seven segment display}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The 68230 parallel interface/timer chip} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:68230} All these devices are connected to the 68230 parallel interface and timer (PI/T) chip via a 40 wire \emph{ribbon cable}. The PI/T has three \emph{ports}. On this chip, a port is a set of eight pins. Each of these pins can be individually set up as an input or as an output. This is more flexible than the Intel 8255A parallel chip, in which the pins in one port cannot be assigned as inputs and outputs in any order. The ports are called port~A, port~B and port~C\@. Some of the pins in port~C can be used also as inputs and outputs for the timer, and some others as control signals for transfers to and from ports A and B\@. We use port~C as an input port since it is connected to the dip switches. The 68230 PI/T has a \emph{base address} of \$800\,001. The port~A data register has offset \$10 from the base address of the PI/T, the port~B data register has offset \$12 from the base address, while port~C has offset \$18 from the base address. This means that port~A is at address $\$800\,001 + \$10 = \$800\,011$, while the port~B data register is at address $\$800\,001 + \$12 = \$800\,013$, while the port~C data register is at address $\$800\,001 + \$18 = \$800\,019$. See section~\vref{sec:equates} for how these constants are defined. See table~\vref{tab:portAddr} for a list of the port addresses. \begin{table} \begin{center} \begin{tabular}{|l|l|l|l|} \hline \multicolumn{1}{|c|}{\textbf{register}} & \textbf{address} & \textbf{offset} & \textbf{name} \\ \hline \hline Port A data register & 800011\hex & 10\hex & \texttt{keys} \\ \hline Port C data register & 800019\hex & 18\hex & \texttt{switches} \\ \hline Port B data register & 800013\hex & 12\hex & \texttt{sevSeg} or \texttt{leds} \\ \hline \end{tabular} \end{center} \caption{The port addresses in the 68230 PI/T and their names} \label{tab:portAddr} \end{table} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Register addresses in the 68230 PI/T on the Flight-68k} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% A 68230 PI/T has 23 separate registers. These occupy 64 memory locations. Individual bits in these registers can be set to control the behaviour of the IC\e. Three of them are the data registers used to communicate with the keyboard, dip-switches and LEDs in our lab work. Table~\vref{tab:registerAddr} gives the addresses of the registers in the 68230 on the Flight-68k. \begin{table} \begin{center} \begin{tabular}{|l|l|l|c|} \hline \multicolumn{1}{|c|}{\textbf{register}} & \textbf{address} & \textbf{offset} & \textbf{name} \\ \hline \hline Port general control register & 800001\hex & 0 & \\ \hline Port service request register & 800003\hex & 2 & \\ \hline Port A data direction register & 800005\hex & 4 & \\ \hline Port B data direction register & 800007\hex & 6 & \\ \hline Port C data direction register & 800009\hex & 8 & \\ \hline Port interrupt vector register & 80000B\hex & A\hex & \\ \hline Port A control register & 80000D\hex & C\hex & \\ \hline Port B control register & 80000F\hex & E\hex & \\ \hline Port A data register & 800011\hex & 10\hex & \texttt{keys} \\ \hline Port B data register & 800013\hex & 12\hex & \texttt{sevSeg} or \texttt{leds} \\ \hline Port A alternate register & 800015\hex & 14\hex & \\ \hline Port B alternate register & 800017\hex & 16\hex & \\ \hline Port C data register & 800019\hex & 18\hex & \texttt{switches} \\ \hline Port status register & 80001B\hex & 1A\hex & \\ \hline Timer control register & 800021\hex & 20\hex & \\ \hline Timer interrupt vector register & 800023\hex & 22\hex & \\ \hline Counter preload register, high & 800027\hex & 26\hex & \\ \hline Counter preload register, middle & 800029\hex & 28\hex & \\ \hline Counter preload register, low & 80002B\hex & 2A\hex & \\ \hline Count register, high & 80002F\hex & 2E\hex & \\ \hline Count register, middle & 800031\hex & 30\hex & \\ \hline Count register, low & 800033\hex & 32\hex & \\ \hline Timer status register & 800035\hex & 34\hex & \\ \hline \end{tabular} \end{center} \caption{The addresses of registers in the 68230 PI/T on the Flight-68k} \label{tab:registerAddr} \end{table} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{How the interface card is connected to the parallel chip} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{figure} \begin{center} \input{jump.pic} \caption{The two settings for the jumper on the interface board} \label{fig:jump} \end{center} \end{figure} The keypad is connected to port~A while the LEDs and seven segment display are both connected to port~B\e. The LEDs and seven segment display are selected by jumper; please see figure~\ref{fig:jump}. When the jumper is in the upper position across pins 1 and 2, the LEDs are selected. When the jumper is across pins 2 and 3, the seven segment display is selected. The dip switches are connected to port~C\e. When you read from the port~C data register, you read an 8-bit number with one bit for each of the 8 switches in the dip switch. When you write to the port~B data register, the bottom eight bits cause the corresponding LED to turn on and off, or cause the corresponding segment on the seven-segment display to turn on and off. In both cases, a bit value of `1' means ``on'', a `0' means ``off''. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{The keypad} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% On the interface board, the keypad is connected to port~A of the 68230 parallel interface/\allowbreak{}timer IC\e. \begin{figure} \begin{center} \input{keypad.pic} \caption{The connection of the keypad to the 68230 parallel interface/timer chip} \label{fig:keypad} \end{center} \end{figure} The keypad is connected rather like figure~\vref{fig:keypad}. There is a key in the twelve positions where the vertical wires are shown crossing the horizontal ones. Each key connects the crossing wires when pressed. The columns are set up as outputs while the rows are set up as inputs. When no key is pressed, the row inputs are high. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Scanning the keypad} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% There are twelve keys on the keypad but we only have eight pins in one port. If we connected the key switches directly to twelve port pins, we could read the keys directly. But this will not work with a larger keypad or keyboard. Also port pins are too precious to waste---if possible, we would prefer to save them for another purpose. If we have fewer port pins available, it is still possible to read the keypad by \emph{scanning} it. To scan a $3 \times 4$ keypad, we use $3 + 4$ port pins. We can use $n + m$ port pins to scan a $n \times m$ keypad\footnote{The method shown here is not the \emph{only} way to scan a keypad---it is possible to scan $\frac{1}{2} n(n -1)$ keys with $n$ port pins. For instance, it is possible to read 28 keys with 8 port pins---if you are interested, ask Nicholas Urbanik\e.}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{The method} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:readKeyExplain} The idea is that we output a `1' to two of the column outputs to the keypad while outputting a `0' to each column in turn. After the left-most column is set low, we can read each row in turn. Say the key `4' on the keypad has been pressed (see figure~\vref{fig:keypad}). If we read the rows (\ie port inputs PA$_3$ to PA$_6$), then bits PA$_3$, PA$_5$ and PA$_6$ are all `1's, but PA$_4$ is a zero, because the key has connected the line PA$_4$ to PA$_0$ on which we have output a `0'. The resistance between PA$_0$ and ground is much lower than the value of the resistor between PA$_4$ and $V_{CC}$, so PA$_4$ will have a voltage close to zero volts. Let's look at the steps in scanning the keypad, from a high level point of view. \begin{itemize} \item For each column: \begin{itemize} \item drive that column low and the others high. \item Read the rows. \item For each row \begin{itemize} \item If that row bit is `0', then have found the key---exit. \item increment the key index \end{itemize} \end{itemize} \item If no key was found, then set key index to \texttt{noKey} \item The key index now has a number from 0 to 11 if a key was pressed, or a value of \texttt{noKey} if no key was pressed. \end{itemize} Let's now look at the steps in greater detail. It may help to read the program in section~\vref{enl4s:sec:readKey} in lab~4, \emph{Scanning a keypad in MC68000 assembly language}. \begin{nameList}{step 1xx} \item[step 1] Start by initialising the key index number that indicates the current key, the column counter and the column pattern that we will output to the keypad columns \item[step 2] for each column, starting from PA$_0$, drive that column low while driving the other columns high \item[step 3] Read the pattern of bits from the rows, \ie PA$_3$ to PA$_6$. To do this, we read the 8 bits from the keypad port into a register, then \emph{rotate} the 8 bits three times, so that the bit from the top row is in bit position 0, \ie in the LSB (least significant bit) position. \item[step 4] for each row: \begin{nameList}{step 1xxx} \item[step 4a] Rotate the LSB into the carry flag in the CPU status register. Look up how the \texttt{ror} and \texttt{rol} instructions work in the Flight-68k manual, your text book or any 68000 reference book. \item[step 4b] check whether the carry flag is low. If it is, then the current key has been pressed. \item[step 4c] if the current key has not been pressed, then increment the key index number and try the next row---go to step 4a. \end{nameList} \item[step 5] Roll the bit pattern for the columns one position left so that we are ready to drive the next column low and the other columns high. \item[step 6] If we have read all the columns, then no key was pressed, so put a special value into the key index register to show that no key has been pressed. \item[step 7] We now have the key number. Use this as an index to look up the value of the key in a lookup table. \end{nameList} This list of steps is called a \emph{task list}. We can also express the algorithm in \emph{pseudocode}. Pseudocode is a mixture of English (or you can use Cantonese if you like!) and some programming language. Here I have combined English with Pascal, since you have studied Pascal: \begin{verbatim} Algorithm ReadKey: key = 0, col = 2, columnPattern = $FE while col <> -1 do row = 3 keypad = columnPattern rowPattern = keypad roll port A bit 3 into rightmost bit position of rowPattern while row <> -1 do roll LSB of rowPattern into CPU carry flag if carry flag is clear goto found key := key + 1 row := row - 1 roll columnPattern left one position col := col - 1 key := noKey found: \end{verbatim} I hope that these two ways of showing the algorithm will help you to understand the subroutine \texttt{ReadKey}, first introduced in your lab work in section~\vref{enl4s:sec:readKey} in lab~4. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Debouncing the keys} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:debouncing} However, there is more to it than this. We need to deal with a problem called \emph{key bounce}. When any switch opens or closes, it does not do so at only one moment. A closing switch will bounce open again for a very short time, close again, bounce apart again, and so on. This lasts about 10 milliseconds, depending on the type of switch. We need to be able to tell when a key has been pressed once and is bouncing or if it has been pressed more than once. Small amounts of noise can also be interpreted as keystrokes when there are none. There are many solutions to this problem, some using hardware such as a flip-flop or Schmidt trigger, others using software delay loops. We will take the software approach. If a key has been pressed, we can wait a while and see if it is still pressed some ten or twenty milliseconds later. If it is still seen as pressed, we shall say that this is a genuine keystroke. We can use the \texttt{Delay} macro to create a delay of 20 milliseconds: \begin{verbatim} Delay 20 Delay 20 milliseconds. \end{verbatim} Please read section~\vref{sec:delayMacro} for more about the \texttt{Delay} macro. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{How to detect if any key has been pressed} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:keyPressed} To see how to scan a keypad we look here at the first part of the problem: detecting a keystroke. How can we do this? One simple way is to output a low to all the columns (\ie to bits 0, 1 and 2 of the keypad port, port~A). How do we write the pattern which has bits 0, 1 and 2 low? This is 0. To achieve this step, we can write: \begin{verbatim} clr.b keys(a6) output 0 to keypad columns \end{verbatim} Remember, to \emph{write} to a port register, we put it as the destination operand, \ie on the \emph{left} side of the \texttt{move} instruction. We can then read the keypad port. If any of the row bits (\ie bits 3 to 6) are low, then a key has probably been pressed. How can we do this? We can first input from the keypad into a register: \begin{verbatim} move.b keys(a6),d1 Register D1 contains the column bits \end{verbatim} Now how can we find out if any of the rows are low? Well, first we need to clear our copy of the bits that are not in the rows, \ie that are not bit 3, 4, 5 or 6. We use the \texttt{and} instruction to clear these bits. We can write: \begin{verbatim} andi.b #$78,d1 Clear all the bits that are not row bits \end{verbatim} Finally, we can compare this value read from the rows with \texttt{\$78}. We can tell if a key has been pressed by seeing if these values are the same or different. You will use this algorithm in your experimental work in section~\vref{enl4s:sec:anyKeyPressedProg}, in lab~4. \result[What does it mean if the value is \texttt{\$78}?]{3}{Write here what we can say about the number of keys pressed if the value read from the rows is equal to \texttt{\$78}.}\label{qes:rowtest} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{68000 Assembly language} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Here we look at some topics of assembly language relevant to the work you will do in your laboratory work. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{labels, opcodes, operands and comments} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% A line in a 68000 assembly language program is divided into four parts: labels, opcodes, operands and comments. One or more of these may not be present. The format is:\\[2ex] \begin{tabularx}{\linewidth}{YCYCYCY} \meta{label} & & \meta{opcode} && \meta{operands} && \meta{comments}\\ $\uparrow$ & $\uparrow$ & & $\uparrow$ & & $\uparrow$ & \\ No space or tab & \emph{At least} one space or tab & & \emph{At least} one space or tab & &\emph{At least} one space or tab & \\ Optional & & Required & & May be required; depends on opcode & & Optional \end{tabularx} The assembler divides a line into these fields by considering spaces to separate the fields. For that reason, there must be no space between two operands, otherwise the assembler will consider the second operand to be a comment, and will give a syntax error message complaining that one operand is missing. Many opcodes (and operands too) can have a \emph{suffix},\label{sec:suffix} which may be one of \texttt{.B}, \texttt{.W} or \texttt{.L}. These are shown in the following table. \begin{center} \begin{tabular}{|l|l|c|c|} \hline \bfseries Suffix & \bfseries Means: & \bfseries number of bytes & \bfseries number of bits\\ \hline \ttfamily .B & byte & 1 & 8 \\ \hline \ttfamily .W & word & 2 & 16 \\ \hline \ttfamily .L & long word & 4 & 32 \\ \hline \end{tabular} \end{center} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Comments in programs} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:comments} In the 68000 assembly language, comments can be written in two ways. A whole line comment begins at the left side of the screen with a symbol `\texttt{*}'. Comments can also begin in the fourth field as mentioned in the previous section. A comment is written for the human reader of a program. A comment has absolutely no effect on what the assembler sees; comments are ignored by the assembler. \eemph{You do not need to type the comments from these lab sheets into the computer.} They are there to help you only. When you write bigger programs of your own, then you \emph{should} write comments, especially at the beginning of each subroutine explaining what the subroutine does. This saves a lot of time when you or someone else wants to change the program a year later. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Integer numbers in programs} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:constants} Integer numbers can be expressed in decimal (the default), hexadecimal, octal or binary. There is a choice of suffixes and prefixes to show which representation is being used. \vspace{1ex} \newcommand{\num}{\meta{number}} \begin{center} \begin{tabular}{|l|c|>{\ttfamily}l|} \hline \textbf{type} & \textbf{format} & \textrm{\textbf{examples}} \\ \hline \hline decimal & \num, \texttt{\&}\num & 297, \&297 \\ \hline hexadecimal & \texttt{\$}\num, \num\texttt{H} & \$FF, 0FFH \\ \hline octal & \texttt{@}\num, \num\texttt{O}, \num\texttt{Q} & @457, 457O, 457Q \\ \hline binary & \texttt{\%}\num, \num\texttt{B} & \%11011011, 11011011B \\ \hline \end{tabular} \end{center} \vspace{1ex} Notice that if you use \texttt{H}, the first digit must be 0--9, otherwise the assembler will think the value is a label. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Registers in the 68000} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:registers} Inside the CPU there are eight temporary storage places that can each hold a 32-bit number. These are called the \emph{data registers}. They are called D0, D1, D2, \ldots, D7\e. There are also eight temporary storage locations to hold addresses inside the CPU. These are called the \emph{address registers}. They are called A0, A1, A2, \ldots, A7\e. A7 is special purpose and is called the \emph{stack pointer}. The others can be used to hold any address. Note that we are using A6 to hold the base address of the 68230 parallel chip, so it is better not to change that either. There are three other special registers. There is the \emph{program counter}, labelled PC\e. The program counter always holds the address of the next instruction to be executed. See section \vref{sec:stack} for more about the stack pointer register, A7, and the stack. The next section discusses the status register. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{Flags in the status registers} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:statusReg} There is also a \emph{status register} which has a number of \emph{flags}. A flag is a single bit that can have the value 1 or 0. The flags we are interested in here in this lab are those in the lowest four bits. They each have a single letter name: X = extended flag, N = negative flag, Z = zero flag, V = overflow flag and C = carry flag. These five flags are also sometimes called the \emph{condition codes}. These five flags are set or cleared as the result of many instructions. See the Flight-68k manual or your text book to see what effect each instruction has on the flags. This table shows the five condition code flags: \begin{center} \begin{tabularx}{\textwidth}{|l|c|c|X|} \hline \bfseries name & \bfseries letter & \bfseries bit \# & \multicolumn{1}{c|}{\bfseries when set} \\ \hline \hline carry & C & 0 & The current instruction had a carry out of MSB (most significant bit), or if an unsigned subtraction, a borrow. This is equivalent to: the result of the current instruction, considered as an \emph{unsigned operation}, did not fit in the destination.\\ \hline overflow & V & 1 & The result of the current instruction, considered as a \emph{signed operation}, did not fit in the destination. With addition, overflow can only happen when adding two numbers of the same sign. In this case, answer is of the opposite sign if and only if there was overflow.\\ \hline zero & Z & 2 & The result of the last instruction was zero \\ \hline negative & N & 3 & The result of the last operation was negative \\ \hline extend & X & 4 & Used in arithmetic with data bigger than 32 bits to take carries from one long word to the next. \\ \hline \end{tabularx} \end{center} Overflow from addition may \emph{only} happen when two numbers of the same sign are added together. It will \emph{never} happen when two numbers of opposite sign are added together. You can tell if there is overflow yourself, even without looking at the V flag in the 68000. If you add two positive numbers and the result is negative, then you have overflow. If you add two negative numbers and the result is positive, then you have overflow. Overflow is only of interest you consider the numbers you are adding to be \emph{signed} numbers. It indicates that the destination for the instruction was too small to hold the result of a signed operation. Carry is more interesting when you are doing \emph{unsigned} arithmetic---you can completely ignore it when you are doing signed arithmetic. For \emph{unsigned arithmetic}, the carry flag indicates that the destination was too small for the result of an unsigned operation. With subtraction, we have \meta{dest}~=~\meta{dest}~$-$~\meta{src}. The carry flag will be set if the source is greater than the destination, considering both the source and destination as unsigned numbers. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Addressing modes} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The MC68000 has a lot of \emph{addressing modes}: there are 14, of which we use 4 here. In this section we look at these addressing modes and see some examples of their use. An \emph{addressing mode} is a way of specifying the \emph{effective address} of an operand, either in a register or in memory. The effective address tells us where the operand is. There are many addressing modes because there are many different ways of storing data, and addressing modes are designed for accessing data that is stored using these different methods. Chapter 7 of the Flight-68k manual discusses addressing modes. Also see pages 39--48 of Antonakos, \emph{The 68000 microprocessor}, the text book. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{Direct addressing mode} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The first lab used the direct addressing mode most of all. It is perhaps the simplest addressing mode: the assembly language instruction gives the address of the operand. An example is shown here: \begin{verbatim} org data value dc.w org prog move value,d0 value is accessed using direct addressing \end{verbatim} See page 44 of the text, under ``absolute short address'' and ``absolute long address.'' See also the Flight-68k manual on page 7--9 under the same headings. Note that the assembler decides itself whether to use absolute long or absolute short direct addressing; there is no need to specify a ``\texttt{.L}'' or ``\texttt{.W}''as shown in the manual. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{Immediate addressing mode} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:immediate} The first lab also used the \emph{immediate} addressing mode. The value to be loaded is included with the instruction. The mode is indicated with a \# in front of the number: \begin{verbatim} move #1,d0 Put the actual value 1 into D0. \end{verbatim} See page 7--12 of the Flight-68k manual, or page 47 of the text book for some more information. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{Address register indirect with displacement addressing mode} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:ariWDisp} The \emph{address register indirect with displacement} mode is new to you. We use this mode to access the registers of the parallel chip. First, the address register A6 is loaded with the base address of the parallel chip. The offset of the register from the base address is then added to the base address to give the address of the actual register. Here is an example: \begin{alltt} move $18(a6),d0 Load data from address given by * adding 18\(\sb{16}\) to the contents of A6. \end{alltt} Note that in your lab work, you will use the constants \texttt{leds}, \texttt{switches} and \texttt{sevSeg} with this addressing mode. These constants have been defined in the file \texttt{flight.i}. Here is another example, using the name \texttt{leds} defined in the file \texttt{flight.i}: \begin{verbatim} move d0,leds(a6) Copy data from D0 to address given by * adding leds to the contents of A6. \end{verbatim} The value of \texttt{leds} is \$12 --- see section~\vref{sec:equates} and section~\vref{sec:68230}. The \texttt{Init} macro loaded the base address of the parallel chip (\$800\,001) into A6\e. The effective address of ``\texttt{leds(a6)}'' is then $\$800\,001 + \$12 = \$800\,013$, which is the address of the port~B data register in the 68230 parallel chip. See pages 7--7 and 7--8 of the Flight-68k manual, or pages 42--43 of the text book for some more information about this addressing mode. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{Address register indirect with index addressing mode} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:ariWithIndex} The \emph{register indirect with index} addressing mode may also be new to you. In lab~3 we use it for looking up a pattern in a table to copy to the seven segment display. See page 7--8, section 7.6.2.5 of the Flight-68k manual for more information. Here is an example of its use: \begin{verbatim} move $18(a0,d1),d0 \end{verbatim} Here, the hexadecimal value \$18 and the contents of D1 are added to the contents of the register A0 to give the memory address from which the data is \texttt{move}d. How would we use such an addressing mode? An example is looking up a number in a table. Suppose we have a table of bytes, which we could declare as: \verb|table dc.b 1,2,4,8,$10,$20,$40,$80| Now we could load the address of this table, which is given by the label \texttt{table}, into the address register A0: \verb| movea.l #table,a0 Immediate addressing mode| Note that that suffix is an \texttt{.L}, not a \texttt{1}! See section~\vref{sec:suffix}. Now suppose we want the fourth entry in this table. We could put the value 3 into D1 and then use the instruction: \verb| move.b 0(a0,d1),d0 Load value 8 from table into D0| Why did we put \textbf{3} into D0 to access the \emph{fourth} entry in the table? Suppose \verb|#table| has the value \$400500. This means that the first element of the table has the address \$400500, the second has address \$400501, the third \$400502 and the \emph{fourth} has address \$400503. Now the way the addressing mode works is that the number 0 is added to what is in A0, \$400500, and also to what is in D1, 3, to get the address \$400503, which is the correct address. So to access the first item in the table, we would put 0 into D1, and to access the last of the eight items in the table, we would load 7 into D1\e. In lab~4, we will use this addressing mode for the last program in section~\ref{enl4s:sec:lastProg}. See page 7--8 and of the Flight-68k manual, or page 43 of the text book for some more information. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Tables in MC68000 assembly language} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:table} As we use the word here, a \emph{table} is a collection of numbers that are put one after the other in the computer's memory. We use an \emph{index} to access individual numbers in the table. Another word for such a table is \emph{array}. If you have used Pascal or C, you may have seen an array before. In MC68000 assembly language, an array is declared with the \texttt{dc}, declare constant data command, or with the \texttt{ds}, declare storage command. Here are examples of each: \begin{verbatim} org $400500 data starts at this address pattn dc.b $ff,$7f,$3f,$1f,$f,7,3,1 An array of 8 patterns values ds.w 5 An array of 5 words, not initialised. \end{verbatim} If there are initial values the entries in the table should have, then we use \texttt{dc}. If there are no special values the entries should be initialised to, or if the table is very big, we can use \texttt{ds}. We can access the entries in the table using the \emph{register indirect with index} addressing mode. See section~\vref{sec:ariWithIndex}. \begin{comment} implied = inherent rts register = address, data register move D0,D1 immediate = immediate move #$1234,D1 direct = absolute short or long move $1234,D1 pointer = ARI move (A0),D1 autoincrement = ARI witrh postincrement move (A0)+,D1 autodecrement = ARI with predecrement move -(A0),D1 index = ARI with displacement move $1234(A0),D1 relative = PCI with displacement move $1234(PC),D1 short relative = short relative bra alpha ARI = address register indirect \end{comment} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Loops: the \texttt{dbf} instruction} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:dbf} Computers are good at doing repetitive jobs: the loop construction is ideal for implementing such repetitive work. We use two basic kinds of looping operations: conditional and unconditional. An unconditional loop just keeps going forever---or at least, till we press the reset button or turn the computer off. We may implement such loops using the \texttt{bra} instruction (branch always. Every time we execute the \texttt{bra} instruction, the program counter register is loaded with the address given by the label. The program will then execute the instruction with that label. Your lab sheets have many examples of the \texttt{bra} instruction. A conditional loop can be more clever. It can stop looping when a condition is met. We often use a \texttt{cmp} (compare) instruction to set the flags in the status register, then we use a \texttt{b$_\mathtt{cc}$} instruction such as \texttt{beq} to check those flags. The \texttt{b$_\mathtt{cc}$} instruction will choose whether to jump (or `branch') depending on the value of the status flags. These flags are the \textsc{\small Zero}, \textsc{\small Negative}, \textsc{\small Carry}, \textsc{\small oVerflow} and \textsc{\small eXtended} flags. See section \vref{sec:statusReg} for more about the status flags. Another useful kind of looping instruction is the \texttt{db$_\mathtt{cc}$} family of instructions. A very useful member of this family is the \texttt{dbf} or \textsc{\small Decrement and Branch while False} instruction. The \texttt{dbf} instruction takes two operands: a data register, and a label. This instruction does the following: \begin{itemize} \item The value in the data register is decremented by 1. \item If the data register is not $-1$, then the program will branch to the label. \item If the data register $= -1$, then the program will execute the instruction following the \texttt{dbf} instruction. \end{itemize} The \texttt{dbf} instruction can be used as like a \Kf{for} loop in Pascal or C, with a fixed number of times through a loop. There is an example of the use of \texttt{dbf} in section~\vref{enl4s:sec:dbfProg} in lab~4. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{cmp} instruction} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:cmp} The \inst{cmp} instruction works the same as the \inst{sub} instruction, except that the result is thrown away. The syntax of the \inst{cmp} instruction is \hspace*{1cm} \texttt{cmp}\textsf{.s} \hspace{1cm} \meta{ea},\texttt{D}\Vf{n} \textsf{.s} is one of \texttt{.B}, \texttt{.W} or \texttt{.L} \meta{ea} is an effective address given by any addressing mode, specifying the source \meta{src} and \texttt{D}\Vf{n} is any data register, specifying the destination \meta{dest}. The CPU does the subtraction \meta{dest}~$-$~\meta{src}, throws the result away, but sets the flags in the status register. See section~\vref{sec:statusReg} for more about the flags. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{What if you find an instruction you do not know?} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% There are some other instructions introduced in your lab work that you may not have seen before. There are several places to look. The back of the text book (Antonakos, \emph{The 68000 microprocessor}) has details of each 68000 instruction. The Flight-68k manual explains each instruction in chapter 8. There is some online help with the assembler: to use this, at a DOS prompt, type \texttt{asmhelp} \meta{Enter}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Subroutines} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:subroutines} A \emph{subroutine} is a specialised program module that may be called upon from anywhere else in the program outside of the normal sequence of execution. Most programs contain subroutines. Subroutines are often called \emph{functions} or \emph{procedures}, especially in higher level languages. We will talk more about functions later. \begin{figure}[hbpt] \input{coathang.pic} \caption{Executing a subroutine} \label{fig:coathanger} \end{figure} Figure~\vref{fig:coathanger} shows how a subroutine fits into the normal flow of execution of a program. At point $a$ there is a \emph{call} to the subroutine. This causes the next instruction in the execution of the program to be at point $x$. At $y$---the end of the subroutine---there is a \emph{return} instruction, which causes execution to continue at the next instruction after point $a$. Later, at point $b$, there is another call to the same subroutine, so again the processor executes instructions between $x$ and $y$. But this time, execution returns to the instruction immediately after point $b$. \begin{figure}[hbpt] \input{nested.pic} \caption{Executing nested subroutines} \label{fig:nested} \end{figure} Subroutines can also call other subroutines---see figure~\vref{fig:nested}. Here, the first subroutine is executed as in figure~\vref{fig:coathanger}, but when execution reaches instruction $c$, a call is made to a nested subroutine. Execution then starts at instruction $u$, the first instruction in the nested subroutine. At the end of the nested subroutine, a return instruction is executed at $v$, which causes execution to continue at the instruction immediately after instruction $c$. When the first subroutine finishes, the return instruction at $y$ will cause execution to continue at the correct location---the instruction immediately after $a$ or $b$, depending on where the call was made from. You will see that in this particular example, the nested subroutine is executed twice, as is the first subroutine. Notice that when the subroutine finishes, it must return to just after where it was called from. This is different from the way a normal branch instruction works. A special data structure is required to hold the address of the instruction immediately after the calling instruction. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{The stack} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:stack} We could hold the return address of the subroutine in a single fixed location, but this would not allow one subroutine to call another, since each call would overwrite the previous value. A stack data structure is generally chosen to hold these return addresses. The stack is usually in RAM\e. As mentioned in lecture~6, the stack is a \textbf{l}ast \textbf{i}n, \textbf{f}irst \textbf{o}ut (LIFO) structure. A stack has two operations: \begin{emDescrip} \item[push] The push operation adds a data item to the stack. \item[pop] The pop operation removes the most recent value pushed (that has not already been popped). Some texts call this a \emph{pull} operation. \end{emDescrip} LIFO means that the value that is removed with a \emph{pop} operation is the value that was most recently pushed onto the stack. The memory address that holds the last value that was pushed is called the \emph{top of the stack}. Each memory location, as we have discussed earlier, holds one byte and has a unique number called an \emph{address}. A special register called the stack pointer---A7 in the 68000---holds the address of the top of the stack. On some other microprocessors the stack pointer points to the location where the \emph{next} data item \emph{will} be pushed, but on both the 68000 and 8086 \up families, the stack pointer points to the address of the \emph{last} data item \emph{already} pushed onto the stack. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The push operation} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:push} The push operation has two steps. When a data item is pushed onto the stack, \begin{enumerate} \item the stack pointer is decremented by the size of the data item (in bytes) \item the data value is copied into the location whose address is now in the stack pointer register. \end{enumerate} Note that you can only push and pop data values with an even number of bytes. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{An example of a push operation} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% In the 68000, there are a few instructions to push data onto the stack. When using the \texttt{move} instruction, the push operation uses the \emph{address register indirect with predecrement} addressing mode. As an example, the assembly language instruction to push a 32-bit long word value from the D0 register onto the stack is: \begin{verbatim} move.l d0,-(a7) ; Remember A7 is the stack pointer. \end{verbatim} Many registers can be pushed at once with the \texttt{movem} instruction. This example shows the 32-bit long word values in the registers D1, D2, D3, D4 and A0 all being pushed onto the stack: \begin{verbatim} movem.l d1-d4/a0,-(a7) Push all five registers onto the stack. \end{verbatim} Note here that the dash `\texttt{-}' between two registers means a range of registers: \texttt{d1-d4} means registers D1, D2, D3 and D4\e. To specify registers that are not part of a range, separate them with slashes, as shown above. Some of the programs you use in the lab sessions use the \texttt{movem} instruction at the beginning and at the end. This is to make them \emph{transparent}. See section~\vref{sec:transparency} for more about transparency. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The pop operation} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:pop} The pop operation is the reverse of the push operation. When a value is popped from the stack: \begin{enumerate} \item the data value is copied from the top of the stack into another location, either a register or a memory location. \item the stack pointer is incremented---by the size of the data item that was removed, in bytes---to point to the new top of stack. \end{enumerate} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsubsection{An example of a pop operation} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Several instructions in the 68000 pop data from the stack. When using the \texttt{move} instruction, the pop operation uses the \emph{address register indirect with postincrement} addressing mode. As an example, the assembly language instruction to pop a 32-bit long word from the stack into the D0 register is: \begin{verbatim} move.l (a7)+,d0 ; Pop operation. \end{verbatim} Suppose that before this instruction executes that A7 contains the value 4003F0\hex. In this example, the ``\texttt{.l}'' means ``long word'', (4 bytes) so the operation first copies 4 bytes from memory locations 4003F0\hex, 4003F1\hex, 4003F2\hex and 4003F3\hex into the 32-bit D0 register. Then the A7 register is incremented by 4 so that it finally has the value 4003F4\hex. Many registers can be popped at once with the \texttt{movem} instruction. This example shows 5 32-bit long word values being popped from the stack into registers D1, D2, D3, D4 and A0: \begin{verbatim} movem.l (a7)+,d1-d4/a0 Pop all five registers from the stack. \end{verbatim} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Preserving registers: transparency} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:transparency} Very often we use registers to hold variables in programs. There are many advantages to this: registers are quickly accessible---they are already inside the CPU\e. A program that keeps its variables all in registers will run faster than if it keeps many variables in memory. There is one problem here---there is a limited number of registers. The 68000 has more registers than many \up, but we can still run out. We may need to program other \up{}s with fewer registers. We may want to use a register for more than one variable. Another problem is \emph{local variables} in subroutines. The problem is that one subroutine may need five registers, and may call other subroutines that also need a few registers. Suppose the second subroutine changes a register that the first subroutine was using? A solution to all these problems is to make the subroutines ``transparent''. We make a subroutine \emph{transparent} by saving all the registers that it uses. Where do we save them? The system stack is a very convenient place. The subroutine can push all the registers it uses onto the stack as the very first action it does, then, at the very end, just before the \texttt{rts} instruction, it pops the the same registers in exactly the opposite order. A convenient instruction to do this is the \texttt{movem} instruction, which will push or pop as many registers as you want, always taking care of doing these operations in the correct order. Please see the sections \ref{sec:push} and \vref{sec:pop} for more information about these operations. All the subroutines used in lab~4 are as `transparent' as possible. Most of the macros used in the lab also begin with push and end with pop operations. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Subroutine calls, parameters and return values} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:parameters} Sometimes a subroutine does not need any information to do its job; if \texttt{Init} were a subroutine, it would need no extra information---it would just initialise the parallel chip. However, some other subroutines \emph{do} need to pass some information in or out to be useful. For example, the \texttt{ReadKey} subroutine in section~\ref{enl4s:sec:readKeySub} of lab~4 needs to let us know what the key was that it read. It does this by putting the key index into the D0 register. We say that it \emph{returns} the key index in D0, or that the key index is its \emph{return value}. Similarly, the \texttt{GetKey} subroutine, also in section~\vref{enl4s:sec:readKeySub} of lab~4, returns a key index in register D0\e. Information may be passed to a macro or subroutine through registers. An example is the \texttt{Transl} macro, described in section~\vref{sec:translMacro}. \texttt{Transl} takes a key index in register D0 and returns a number, also in D0, that corresponds to the value on the top of the key. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Subroutine calls and the stack} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:subStack} When a subroutine call is executed, the processor saves the return address on the top of the stack. When the most recent subroutine call finishes, the last stored return address is retrieved from the top of the stack. In this way, subroutines that call other subroutines (nested subroutines, as in figure~\vref{fig:nested}) will also return to the correct location, since the first subroutine call will be the last one to return. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{bsr} and \texttt{jsr} instructions} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% In the 68000, the call operation is implemented by either the \texttt{bsr} instruction or the \texttt{jsr} instruction. Both do the same thing, except that \texttt{bsr} can only use relative addressing modes, whereas \texttt{jsr} can use many addressing modes. To see the difference, refer to the Flight-68k manual, chapter 8, or the text book. Here we are interested in what these instructions do with the stack. Suppose a subroutine is called \texttt{sub1}. Then a call to this subroutine with either \texttt{jsr sub1} or \texttt{bsr sub1} will: \begin{enumerate} \item push the address of the instruction immediately following the call instruction onto the stack. \item load the address of the first instruction in the subroutine into PC. \end{enumerate} The first step saves the return address of the subroutine on the stack. Because the return address is a long word (4 bytes), the push operation will decrement the stack pointer by 4 before copying the return address to the stack. The second step causes execution of the instructions in the subroutine to begin. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{rts} instruction} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Every subroutine must end with the \texttt{rts} (\textbf{r}e\textbf{t}urn from \textbf{s}ubroutine) instruction. When the \texttt{rts} instruction executes, it simply pops the long word (32-bit) value from the top of the stack into PC (the program counter register). The effect is to cause program execution to continue from the instruction immediately after the instruction that called the subroutine. That is, \begin{enumerate} \item the four bytes at the top of the stack are copied into the program counter \item the stack pointer is incremented by 4 \end{enumerate} Hence, the \texttt{rts} instruction is simply a pop operation. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The subroutine must leave the stack as it found it} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% An important requirement is that when execution reaches the \texttt{rts} instruction, the stack \emph{must} be exactly the same as it was immediately after the subroutine was called. If it is not, then something else will be popped into the PC, and the computer is likely to `hang'. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{An example showing a subroutine call} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:subCall} \begin{figure}[htb] \input{stackcal.pic} \caption{The stack before and after the call to subroutine \texttt{sub1}.} \label{fig:stackCall} \end{figure} A subroutine \inst{sub1} at address 400450\hex is called. The instruction \begin{verbatim} jsr sub1 \end{verbatim} is at location 400410\hex. Figure~\vref{fig:stackCall} shows the arrangement of the stack before and after the call. \begin{itemize} \item Before the call, the stack pointer A7 is pointing to the top of the stack, which just happens to be at address 4003F0\hex. \end{itemize} Here are the three steps performed by the CPU when it executes the call instruction: \begin{itemize} \item The stack pointer is decremented by four, since an address occupies 4 bytes \item The return address, 400416\hex is copied from the program counter onto the top of the stack \item The address of the subroutine, 400450\hex is copied into the program counter \end{itemize} \begin{itemize} \item After the call, the value 400416\hex is pushed onto the stack, since the \inst{jsr sub1} instruction at address 400410\hex is 6 bytes long. $400416\hex = 400410\hex + 6$. 400416\hex is the address of the instruction immediately after the \inst{jsr} instruction. The address of the top of the stack is always held in the stack pointer, A7\e. \item Because the program counter holds the address of the first instruction of the subroutine, the CPU executes instructions in the subroutine. \end{itemize} \begin{comment} A subroutine \texttt{sub1} at address 400450\hex is called. The instruction \begin{verbatim} jsr sub1 \end{verbatim} is at location 400410\hex. \begin{itemize} \item Before the call, the stack pointer A7 is pointing to the top of the stack, which just happens to be at address 4003F0\hex. \item After the call, the value 400416\hex is pushed onto the stack, since the \texttt{jsr sub1} instruction at address 400410\hex and is 6 bytes long. $400416\hex = 400410\hex + 6$. 400416\hex is the address of the instruction immediately after the \texttt{jsr} instruction. \item The stack pointer is decremented by four, since an address occupies 4 bytes, then the return address, 400416\hex is pushed onto the stack. \item The new value at the top of the stack is the return address, 400416\hex. The address of the top of the stack is always held in the stack pointer, A7\e. \end{itemize} \end{comment} \begin{comment} Before the call, the stack pointer A7 is pointing to the top of the stack, at address 4003F0\hex. After the call, the value 400416\hex is pushed onto the stack, since the \texttt{jsr sub1} instruction is 6 bytes long. 400416\hex is the address of the instruction immediately after the \texttt{jsr} instruction. The stack pointer is decremented by four, since an address occupies 4 bytes, then the return address, 400416\hex is pushed onto the stack. The new value at the top of the stack is the return address, 400416\hex. The address of the top of the stack is always held in the stack pointer, A7\e. \end{comment} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{The include file, \texttt{flight.i} and the macros} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:macros} You will notice that the programs in labs~3 and~4 all have the line \verb| include flight.i| Also, the first instruction in each program is \verb| Init Initialise the parallel chip| The first instruction opens a file, \texttt{flight.i}, which contains the definition of the names \texttt{leds}, \texttt{sevSeg} and \texttt{switches}. The file also contains the definition of several \emph{macros} called \texttt{Init}, \texttt{Delay}, \texttt{WriteSs}, \texttt{Transl}, \texttt{ShowNum}, \texttt{WNKeyPr} and \texttt{WKeyPr}. You may look at the file \texttt{flight.i} if you like. A \emph{macro} is a sequence of instructions that has a name and that has a single idea or algorithm. A macro can be `called' from anywhere in the program. A macro is rather like a subroutine. The difference from a subroutine is that each time you `call' a macro, the instructions are inserted directly into that location by the assembler. If you call a macro ten times, the code for the macro will be inserted ten times in your program. On the other hand, if you call a subroutine ten times, the code for that subroutine will still only appear once in the program. A subroutine must finish with a \texttt{rts} instruction, while a macro does not. A macro may take one or more \emph{parameters}, such as the \texttt{Delay} macro, described in section~\vref{sec:delayMacro}. The other macros here take no parameters, but some may use information provided in register D0, and some provide information in register D0\e. These macros have been written so that they disturb the rest of your program as little as possible. They do this by pushing all registers that they use (except D0 in most cases, and A6) onto the stack, and then popping the registers back from the stack afterwards. \eemph{I have included these macros to make the lab work quicker for you to do.} To call a macro, simply type the name of the macro in the opcode field of your program, as shown in the programs in your lab sheet. \eemph{It is necessary to type the same case as shown, as this assembler is case sensitive with the names of macros.} Hence it is necessary to type \texttt{Init} and not \texttt{init}, \texttt{WriteSs} and not \texttt{writess}, and so on. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{Init} macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:initMacro} The macro \texttt{Init} initialises the 68230 parallel chip, and also loads its base address into the A6 register for use with the address register indirect with displacement addressing mode---see p.~42--43 of Antonakos (the text book), or p. 7-7 and 7-8 of the \emph{Flight-68k user manual} for more about this addressing mode. \texttt{Init} sets the port connected to the LEDs as outputs, the port connected to the switches as inputs, and also sets the keypad port up correctly, with port bits 0, 1 and 2 as outputs, and the other five bits as inputs. The \texttt{Init} macro contains six instructions. If you single-step through your program, you need to step over these first six instructions. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{Delay} macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:delayMacro} The \texttt{Delay} macro takes one parameter, as mentioned above. The parameter is a counting number, and is provided after the name \texttt{Delay}, like this: \begin{verbatim} Delay 20 Delay 20 milliseconds. \end{verbatim} \texttt{Delay} preserves all the registers it uses. In other words, all registers will have the same value before and after calling \texttt{Delay}. \texttt{Delay} will simply keep the CPU busy counting until the number of milliseconds specified by the parameter has passed. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{WriteSs} macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:writeSsMacro} The \texttt{WriteSs} macro (write to seven segment display) takes a number in register D0 and uses a lookup table to display the value on the seven segment display, as in the last lab session. Only the four right-most bits are used; other bits in D0 are cleared. All other registers are not affected. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{Transl} macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:translMacro} The \texttt{Transl} macro (translate from a key index to key value) is used to interpret the result of \texttt{ReadKey}. ReadKey gives a number in the range 0 to 11, with the following values: \begin{center} \begin{tabular}{|l|c|c|c|c|c|c|c|c|c|c|c|c|} \hline \textbf{Key index:} & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 \\ \hline \textbf{Value printed on the key:} & 1 & 4 & 7 & $*$ & 2 & 5 & 8 & 0 & 3 & 6 & 9 & \# \\ \hline \end{tabular} \end{center} Here, the ``Key index'' is the index returned by \texttt{ReadKey}. The ``Value printed on the key'' is what you see when you look at the telephone keypad yourself. \texttt{Transl} uses a lookup table to take the key index as input (in D0) and provides the actual key value as output (also in D0). For `$*$' it returns \texttt{\$A}, and for `\#' it returns \texttt{\$B}, since the idea is to display the result on the seven segment display, which cannot display a `$*$' or a `\#'. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{ShowNum} macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:showNumMacro} The \texttt{ShowNum} macro takes a value in register D0 and displays the value as a four-digit decimal number on the terminal screen. It does this by serial transfer, using monitor firmware routines, in the ROM on the Flight-68k board. All other registers are preserved besides D0\e. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{WNKeyPr} macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:wNKeyPrMacro} The \texttt{WNKeyPr} macro simply waits till a key is \emph{not} pressed on the keypad. All registers are preserved. It is very similar to the macro \texttt{WKeyPr}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The \texttt{WKeyPr} macro} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:wKeyPrMacro} The \texttt{WKeyPr} macro simply waits till a key \emph{is} pressed on the keypad. All registers are preserved. It uses the algorithm described in section~\vref{sec:readKeyExplain}. You will work with a program to use this algorithm in section~\vref{enl4s:sec:readKey} in lab~4. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Equates} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:equates} \emph{Equates} give a particular constant value to a label. The values of \texttt{leds}, \texttt{sevSeg} and \texttt{switches} are set using \emph{equates}. If you are familiar with Pascal, an equate is like a Pascal constant defined with \texttt{const}. Here is an example of some equates, showing the values given to these names: \begin{verbatim} keys equ $10 Port A data register switches equ $18 Port C data register sevSeg equ $12 Port B data register leds equ $12 Port B data register \end{verbatim} So \texttt{keys} has the value \$10, \texttt{leds} and \texttt{sevSeg} both have the value \$12, and the name \texttt{switches} has the value \$10. These values are the \emph{offsets} from the \emph{base address} of the 68230 parallel chip. See section~\vref{sec:68230} for more about the 68230 parallel interface/timer chip. Also, see page 11-2 of the Flight-68k manual for a list of all the registers in the PI/T and their addresses on the Flight-68k computer. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{The \texttt{trap} instruction and monitor routines} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:trap} Almost every program here ends with a pair of lines that look like this: \begin{verbatim} trap #11 dc.w 0 \end{verbatim} The \texttt{trap} instruction is used here to call a \emph{monitor} routine. The monitor is a collection of programs that are in the EPROM on the Flight-68k boards. These are mentioned briefly on page~\pageref{pag:monitor}. The number on the line with the \texttt{dc.w} directive indicates which of these monitor programs you want to call. There are 28 of these routines, and they are listed on page 5--3 of the Flight-68k manual. Three of them are used for the \texttt{ShowNum} macro---see section~\vref{sec:showNumMacro} for more about this macro. Each program here terminates with a call to the \textsf{renter} routine, which terminates the program and enters the monitor routine that listens for your keystroke commands, such as when you type \meta{l}\meta{t} to begin a download, or \meta{g}\meta{o} to start a program running. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{The general procedure for editing, assembling, downloading and running an assembly language program} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:genProc} Remember: for each program, you will always use the same five steps: \begin{multicols}{2} \raggedcolumns \begin{thinItemise} \item edit \item assemble \item download \item run \item observe \end{thinItemise} \end{multicols} \begin{enumerate} \item Before the PC is turned on, be sure that you have an interface card plugged into a Flight-68k \up board, and that power is supplied to the \up board and that the serial connection is made to the PC. \item If you switch on the PC, from the MS-DOS Startup Menu, select option 3, ``\texttt{Standalone Workstation}'' \item If you want to output to the seven segment display, set the jumper on the interface board to the seven-segment display position, as in figure~\vref{fig:jump}. If you are using the LEDs, set the jumper to the other position. \item Change to the \texttt{c:\bs 68x} directory by typing: \verb|cd \68x| \meta{Enter} \end{enumerate} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Editing the program} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \label{sec:editing} If your program uses any macros, please read about them in \vref{sec:macros}. Note that you \emph{must} type the macro names in the same case as shown in that section, or you will get an ``illegal opcode'' assembler error message. Here I assume that the program you are working with is called \meta{program}\texttt{.asm}. Just put the name of your own program instead of \meta{program}. We will use the same editor---Q-edit---as for the previous labs. \begin{enumerate} \item Edit a new program using Q-edit by typing \texttt{q }\meta{program}\texttt{.asm} \meta{Enter} \item Type in your program. \item Save this program and exit Q-edit by typing \meta{Alt-x} \end{enumerate} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Assembling the program} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% If the name of your assembly language program is \meta{program}\texttt{.asm} then you can assemble it by: \begin{enumerate} \item At the \verb|C:\68X>| prompt, type \texttt{xasm }\meta{program} \meta{Enter} \item In response to the \texttt{Object file: [}\meta{program}\texttt{.BIN] \_} prompt, press the \meta{Enter} key. \item In response to the prompt for a list file, you can either \begin{itemize} \item press \meta{Enter}, in which case the listing file will be displayed on the screen, or \item type \meta{program} \meta{Enter} in which case a file \meta{program}\texttt{.lst} will be created containing the assembler \emph{listing} output. You can examine this file with an editor if you like. \end{itemize} \item If the assembler reports \texttt{0 errors} and \texttt{0 warnings} then assembly was successful. Otherwise, write down the error messages. These show both the line number and the position in the line where the error was found. Edit the program again. The first error or warning is usually the best place to start. Examine that line and correct the error. Then assemble your program again until there are no errors or warnings. \end{enumerate} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Downloading your program} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Downloading a program is sending the assembler output from the PC to the Flight-68k board by a serial transfer. I assume here that the output from the assembler was the file \meta{program}\texttt{.bin}. If you are working with a different filename, use that name instead of \meta{program}. \begin{enumerate} \item Start the serial communications program at 9600 bits per second. We run the program at a baud rate of 9600 bits per second by typing: \texttt{comm /b9600} \begin{explanation} This program is also called a \emph{terminal} program, since the PC behaves as a terminal for the Flight-68k board. \end{explanation} \item Press the \meta{Enter} key three times until an \verb|F>| prompt appears. \begin{explanation} If no \verb|F>| prompt appears, press the RESET button on the Flight-68k board (not the one on the PC!) then press \meta{Enter} three times. Call the lecturer or technician if you still get no \verb|F>| prompt. \end{explanation} \item Type \meta{l}\meta{t} \begin{explanation} There are some programs in the Flight-68k EPROM\e.\label{pag:monitor} These programs are called the \emph{monitor} programs. They are also called \emph{firmware} because they remain after the power is turned off. The command \meta{l}\meta{t} is a command to the monitor firmware to be ready to receive a serial stream of characters from the PC\e. See also section~\vref{sec:trap} for more information about the firmware. \end{explanation} \item When prompted with: \verb|ENTER OFFSET ( IF NONE) : | press the \meta{Enter} key. \item Now press the \meta{F2} key, and when prompted, enter the name of the program: \meta{program} \begin{explanation} This is a command to the terminal program to start sending characters from the file \meta{program}\texttt{.bin} down the serial cable. \end{explanation} \item The firmware will give a message \texttt{LOAD COMPLETED} indicating that the transfer was successful. \end{enumerate} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Running the program} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{enumerate} \item Type \meta{g}\meta{o} \item In response to the request for a starting address, type \eemph{the number that is the address of the first instruction in your program}. This is given by the \texttt{org} statement in your program that is put immediately before the first instruction. In labs~3 and~4, we will stay with 400400\hex. \item Observe what happens when the program runs. \item To exit from the \texttt{comm} terminal program press the \meta{Esc} key. \end{enumerate} % \vfill % \begin{center} Reference: \referenceNum\\[1ex] \tiny \begin{tabular}{|l|c|c|p{7.5cm}|} \hline \multicolumn{1}{|c|}{Compiled by} & Issue & Date & \multicolumn{1}{c|}{Remark} \\ \hline Nick Urbanik & 1 & 18-10-95 & This is a reworking of workshop 3 for 2540 from 1994/95. Moved the intro to the lab manual. Now for 2540, 2541, 2543. \\ \hline \end{tabular} \end{center} \end{document}