Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 15.06.2025
Просмотров: 5277
Скачиваний: 0
8. Assembly language 215
Program 8.3 The relocatable source file sqr.asm.
include "p16f84.inc"
;The SQR subroutine
;************************************************************
; * FUNCTION: |
Squares one byte to give a 2-byte result |
* |
|
; * EXAMPLE : |
X = 10h (16), SQUARE = 0100h (256) |
* |
|
; * ENTRY |
: |
X in W |
* |
; * EXIT |
: |
SQUARE:2 in shared uninitialized data |
* |
;************************************************************
;Static data
udata |
|||
SQUARE |
res |
2 |
; High:Low byte of square |
; Local data |
|||
udata_ovr |
|||
X |
res |
1 |
; Place for X |
X_COPY_L res |
1 |
; Holds a copy of X |
|
X_COPY_H res |
1 |
; Copy X overflow hi byte |
|
TEXT |
code |
||
; Task 1: Zero double-byte |
square |
||
SQR |
clrf |
SQUARE |
|
clrf |
SQUARE+1 |
||
; Task 2: Copy and extend X to 16-bits |
|||
movwf |
X |
; Put X away into Data memory |
|
movwf |
X_COPY_L |
; Copy of X |
|
clrf |
X_COPY_H |
; and extend to double byte |
|
;Task 3: DO
; Task 3A: Shift X right once
SQR_LOOP bcf |
STATUS,C |
; |
Clear carry |
rrf |
X,f |
; |
Shift |
; Task 3B: IF Carry == 1 THEN add 16-bit shifted X to square
btfss |
STATUS,C |
; |
IF C |
== 1 THEN do addition |
|
goto |
SQR_CONT |
; |
ELSE |
skip this task |
|
movf |
X_COPY_L,w |
; |
DO addition |
||
addwf |
SQUARE+1,f |
; |
First the low bytes |
||
btfsc |
STATUS,C |
; |
IF no carry THEN do high bytes |
||
incf |
SQUARE,f |
; |
ELSE |
add carry |
|
movf |
X_COPY_H,w |
; Next |
the high bytes |
||
addwf |
SQUARE,f |
||||
; Task 3C: |
Shift 16-bit copy |
of X right once |
|||
SQR_CONT bcf |
STATUS,C |
; Zero |
Carry-in |
||
rlf |
X_COPY_L,f |
||||
rlf |
X_COPY_H,f |
||||
; WHILE X not zero |
|||||
movf |
X,f |
; Test |
multiplier for zero |
||
btfss |
STATUS,Z |
||||
goto |
SQR_LOOP |
; IF not THEN go again |
|||
FINI |
return |
; ELSE |
finished |
||
global SQUARE, SQR end
DATA). This is similar to udata but indicates to the linker that file registers allocated in this way can be reused by other modules. In the map file of Table 8.6 we see that X has been allocated File 13h as has I, a variable in subroutine SQR_ROOT – see Program 8.3. This makes more e cient use of available Data memory. Variables that are only alive within the subrou-
216 The Quintessential PIC Microcontroller
tine that they are declared in are known in the C language as automatic, as their space is automatically reallocated as needed. The situation where variable space is preserved is known as static. Global variables, such as SQUARE are always static. In this case the variable SQUARE is created by reserving two bytes using the udata directive. It is also published using the global directive, as is the name of the subroutine.
Program 8.4 The relocatable source file root2.asm.
include |
"p16f84.inc" |
|||
extern |
SUM |
; The 2-byte number Hi:Lo |
||
; Local declarations |
||||
udata_ovr |
||||
I |
res 2 |
; Magic number hi:lo |
||
COUNT |
res 1 |
; Loop count |
||
TEXT |
code |
|||
SQR_ROOT |
clrf |
COUNT |
; Task 1: Zero loop count |
|
clrf |
I |
; Task 2: Set magic number I to one |
||
clrf |
I+1 |
|||
incf |
I+1,f |
|||
SQR_LOOP |
movf |
I+1,w |
; Task 3(a): Number - I |
|
subwf |
SUM+1,f |
; Subtract lo byte I from lo byte Num |
||
movf |
I,w |
; Get high byte magic number |
||
btfss |
STATUS,C |
; Skip if No Borrow out |
||
addlw |
1 |
; Return borrow |
||
subwf |
SUM,f |
; Subtract high bytes |
||
btfss |
STATUS,C |
; IF No Borrow THEN continue |
||
goto |
SQR_END |
; ELSE the process is complete |
||
incf |
COUNT,f |
; Task 3(c): ELSE inc loop count |
||
movf |
I+1,w |
; Task 3(d): Add 2 to the magic number |
||
addlw |
2 |
|||
btfsc |
STATUS,C |
; IF no carry THEN done |
||
incf |
I,f |
; ELSE add carry to upper byte I |
||
movwf |
I+1 |
|||
goto |
SQR_LOOP |
|||
SQR_END |
movf |
COUNT,w |
; Task 4: Return loop count as the root |
|
return |
||||
global |
SQR_ROOT |
|||
end |
||||
8. Assembly language 217
The final source file of the trio is the subroutine coded in Program 8.4. This is virtually identical to the absolute equivalent described in Program 8.1. Comparing the two, the org directive has been replaced by TEXT code and cblock by udata_ovr for the automatic local data. The data is passed to the subroutine SQR_ROOT via the external 2-byte global variable SUM, space for which has been allocated in main.asm. The subroutine name SQR_ROOT is published as global to make it visible to main.asm.
Like all source files, root2.asm makes use of SPRs such as STATUS. For this reason the file p16f84.inc of Table 8.4 has been included at the head of the file. As this file comprises a set of equ directives, the names thus published are absolute and are not allocated or changed in any way by the linker. Thus the linker map of Table 8.6 does not list such fixed symbols. They are, however, enumerated in the listing file produced by the linker.
In order to link the three source files together, the linker program must be given a command line listing the names of the input object files output by the relocatable assembler, the linker command file and the names of the output map and machine-code file. In the case of our example this was:
mplink p16f84.lkr main.o sqr.o root2.o /m rms.map /o rms.hex
which names the output map file rms.map and the absolute machine-code file rms.hex.
For documentation purposes the linker generates a composite listing file, similar (but more comprehensive) to that of Table 8.1 and an optional map file. The map file of Table 8.6 shows two lists. The first displays information for each section. This includes its name, type, start address, whether the section resides in Program or Data memory and its size in bytes. The Program Memory Usage table shows that 62 bytes of Program memory is used, including the two bytes of the Reset vector goto instruction, or around 6% of the possible total.
The second table shows information about the symbols in the composite program. Each symbol’s location in either the Program or Data store is given together with the source file where it is defined. Global symbols are noted as extern. Local variables are all labelled static, including automatic reusable variables such as COUNT and X_COPY_H both
at File 15h.
The final outcome, shown in Table 8.7, is a normal executable machine code file. The format of this file is exactly as described for Table 8.2 and can be loaded into absolute Program memory and run in the normal way.
218 The Quintessential PIC Microcontroller
Table 8.6: The output linker map file rms.asm.
MPLINK v1.20.00, Linker |
||||
Linker Map File - Created Sat Jun |
5 16:13:48 1999 |
|||
Section |
Info |
|||
Section |
Type |
Address |
Location Size(Bytes) |
|
--------- --------- --------- --------- --------- |
||||
VECTORS |
code |
0x0000 |
program |
0x0002 |
.cinit |
romdata |
0x0001 |
program |
0x0004 |
TEXT |
code |
0x0005 |
program |
0x0076 |
.udata |
udata |
0x000c |
data |
0x0007 |
.udata_ovr |
udata |
0x0013 |
data |
0x0003 |
Program Memory Usage |
|
Start |
End |
--------- |
--------- |
0x0000 |
0x0002 |
0x0005 |
0x003f |
62 out of 1024 program words used, memory utilization is 6
Symbols - Sorted by Name |
||||
Name |
Address |
Location |
Storage |
File |
--------- |
--------- |
--------- |
--------- |
--------- |
FINI |
0x002a |
program |
static |
SQR.ASM |
MAIN |
0x0005 |
program |
static |
MAIN.ASM |
SQR |
0x0015 |
program |
extern |
SQR.ASM |
SQR_CONT |
0x0024 |
program |
static |
SQR.ASM |
SQR_END |
0x003e |
program |
static |
ROOT2.ASM |
SQR_LOOP |
0x001a |
program |
static |
SQR.ASM |
SQR_LOOP |
0x002f |
program |
static |
ROOT2.ASM |
SQR_ROOT |
0x002b |
program |
extern |
ROOT2.ASM |
COUNT |
0x0015 |
data |
static |
ROOT2.ASM |
I |
0x0013 |
data |
static |
ROOT2.ASM |
NUM_1 |
0x000c |
data |
static |
MAIN.ASM |
NUM_2 |
0x000d |
data |
static |
MAIN.ASM |
RMS |
0x0010 |
data |
static |
MAIN.ASM |
SQUARE |
0x0011 |
data |
extern |
SQR.ASM |
SUM |
0x000e |
data |
extern |
MAIN.ASM |
X |
0x0013 |
data |
static |
SQR.ASM |
X_COPY_H |
0x0015 |
data |
static |
SQR.ASM |
X_COPY_L |
0x0014 |
data |
static |
SQR.ASM |
Developing, testing and debugging software requires a large number of software tools, many of which we have discussed earlier, such as an editor, assembler and linker. In practice there are many other tools such as high-level language compilers (see Chapter 9), simulators and EPROM programmers; shown diagrammatically in Fig. 8.5. Setting up these tools and interacting on an individual basis can be quite complex, especially where products from various manufacturers are involved. In this latter
8. Assembly language 221
Fig. 8.6 MPLAB window showing files selected to assemble, link and simulate Program 8.4.
allows the user to reset the (simulated) PIC, set break points, single step or run continuously. During this process user-selected file registers or the whole of Data memory can be monitored, as can execution time. Of course simulated execution time by the PC will be several orders of magnitude slower than a real PIC.
Figure 8.7 shows the end result of a simulation of our example. In the Watch_1 window are shown the initial values for NUM_1 and NUM_2 of 05h and 08h. Values of variables in this window can be set up by the programmer by double-clicking on the variable address. The outcome √52 + 82 = 9 (to the nearest integer) is seen in the Watch window as the value of RMS. The Watch window is set from the Window menu. Just under this window is the Stop-watch window, which shows that the program took 292 cycles to execute with the given data, which for a 4 MHz crystal is 292 µs in real time. After resetting under the Debug menu, a breakpoint is set up at the last instruction in main.asm. This movwf RMS instruction is shown in the screen snapshot greyed out. The program can be ‘run’
by clicking on the Green Tra c Light icon in the Simulation tool bar (second icon from the left) or from the Debug menu. The Red equivalent
222 The Quintessential PIC Microcontroller
Fig. 8.7 MPLAB screen shot showing the programs selected in Fig. 8.6 being simulated.
icon next left can be used to pause a run at any time. The icon is used to single step one instruction at a time.
Simulation will not catch all problems, especially those involving complex hardware/software interaction. However, over 95% of problems are caused by purely software design faults and simulation is good technique for testing and debugging such code.
For example, our code will fail if the total NUM_12 + NUM_22 > 65, 535, as SUM is only double-byte – see SAQ 8.5. Debugging should always at a first iteration try largest and smallest values of variables. However, correct operation is by no means guaranteed by this test for all possible combinations and sequences of input.
Finally, we review some general information specific to Microchip-compat- ible assemblers as an aid to reading programs in the rest of the book:
•Number representation.
–Hexadecimal: Denoted by a following h, eg. 41h, or a leading h with the number delineated by quotes, eg. h’41’ or a 0x prefix, eg. 0x41.
8. Assembly language 223
The latter is the prefix used in the C language to denote this number base.
The assembler normally defaults to this base so some programs show no hexadecimal indicators. However, it is better not to rely on the default behavior.
– Binary: Denoted by a leading b with a quote delimited number; eg. b’01000001’.
– Decimal: Denoted by a leading d with a quote delineated number; eg. d’65’ or a leading period prefix; eg. .65.
– ASCII: Denoted by a quote delimited character; eg. ’A’.
• Label arithmetic.
– Current position: $; eg. goto $+2.
– Addition: +; eg. goto LOOP+6.
– Subtraction: -; eg. goto LOOP-8.
– Multiplication: *; eg. subwf LAST*2.
– Division: /; eg. subwf LAST/2.
– Current position: $; eg. goto $+2.
• Directives.
– org: Places the following code in Program memory starting from the specified address; eg. org 0100h. Defaults to 000h. Can only be used for absolute assembly.
– code: Counterpart to org for relocatable assembly. The actual address of the code stream is defined in the linker’s command file. More than one code stream may be defined in the command file and in this case its name appears in the label field; eg. SUBROUTINES code.
– equ: Associates a value with a symbol; eg. PORTB equ 06. The
#define directive may be used instead; #define PORTB 06. |
||||
– |
cblock - endc: Used in absolute assembly to allocate program vari- |
|||
ables in Data memory; eg. |
||||
cblock 20h |
||||
FRED |
; One byte at 020h for FRED |
|||
JIM:2 |
; Two bytes at 021:2h for JIM |
|||
ARRAY:10 |
; Ten bytes for ARRAY at 023h - 02Ch |
|||
endc |
||||
The address is optional after the first cblock use. |
||||
– |
udata: Counterpart to cblock for relocatable assembler. The start |
|||
address for this Data memory stream is in the linker’s script file. |
||||
There may be more than one Data stream defined in this script file |
||||
in which case its name is published in the label field; eg. |
||||
SCRATCHPAD udata |
; Uninitialized data stream |
|||
FRED |
res 1 ; Reserve one byte for FRED |
|||
JIM |
res 2 |
; Reserve two bytes for JIM |
||
ARRAY |
res 10 |
; Reserve ten bytes for ARRAY |
||
–udata _ovr: OVeRlay Uninitialized DATA is similar to udata but the linker tries to reuse File registers for the specified named variables.
–res: Used with udata to REServe one or more bytes for a variable in the Data stream.