Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 15.06.2025

Просмотров: 5292

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

8. Assembly language 209

tions actually used by the program. Any macros defined in the included file but not used will have no e ect on the final machine code.

One of the major advantages of using an assembler over machine code programming is the use of names for the various file registers and bits therein; for example, INTCON instead of File 0Bh and GIE in place of 7. In code, such as Program 7.1 on page 181, these equivalences are listed at the head of the source code using equ directives. Although the GPRs will have name labels unique to the particular program, the SPRs and their constituent bits are the same for all programs targeted to a particular type of PIC. Microchip provide files for each PIC, listing all SPRs and bits which can be included in the program’s heading; for example

Table 8.4: Part of Microchip’s file p16f84.inc.

;This header file defines configurations, registers, and other

;useful bits of information for the PIC16F84 microcontroller.

;These names match the data sheets as closely as possible.

;-----

Register Files

------------------------------------------

INDF

EQU

H’0000’

TMR0

EQU

H’0001’

PCL

EQU

H’0002’

STATUS

EQU

H’0003’

FSR

EQU

H’0004’

PORTA

EQU

H’0005’

PORTB

EQU

H’0006’

EEDATA

EQU

H’0008’

EEADR

EQU

H’0009’

PCLATH

EQU

H’000A’

INTCON

EQU

H’000B’

OPTION_REG

EQU

H’0081’

TRISA

EQU

H’0085’

TRISB

EQU

H’0086’

EECON1

EQU

H’0088’

EECON2

EQU

H’0089’

;-----

STATUS Bits --------------------------------------------

IRP

EQU

H’0007’

RP1

EQU

H’0006’

RP0

EQU

H’0005’

NOT_TO

EQU

H’0004’

NOT_PD

EQU

H’0003’

Z

EQU

H’0002’

DC

EQU

H’0001’

C

EQU

H’0000’

;-----

INTCON Bits --------------------------------------------

GIE

EQU

H’0007’

EEIE

EQU

H’0006’

T0IE

EQU

H’0005’

INTE

EQU

H’0004’

RBIE

EQU

H’0003’

T0IF

EQU

H’0002’

INTF

EQU

H’0001’

RBIF

EQU

H’0000’


210 The Quintessential PIC Microcontroller

as used in Program 8.2. For instance, Table 8.4 shows the first part of Microchip’s file p16f84.inc which we will use for the rest of this text.

The process outlined up to here is known as absolute assembly. Here the source code is in a single file (plus maybe some included files) and the assembler places the resulting machine code in known (i.e. absolute) locations in the Program store. We stated earlier on page 201 that where many modules are involved, often written by di erent people or/and coming from outside sources and commercial libraries, some means must be found to link the appropriate modules together to give the final single absolute executable machine-code file. For example, you may have to call up one of the modules that Fred has written some time ago. You will not know exactly where in memory this module will reside until the project has been completed. What can you do? Well a module should have its entry point labelled; say, FRED in this case. Then you should be able to call FRED without knowing exactly what address this label represents.

The process used to facilitate this is shown in Fig. 8.3. Central to this modular tie-up is the linker program, which satisfies such external cross-references between the modules. Each module’s source-code file needs to have been translated into relocatable object code prior to the linkage. “Relocatable” means that its final location and various addresses of external labels have yet to be determined. This translation is done by a relocatable assembler. Unlike absolute assembly, it is the linker that determines where the machine code is to be located in memory, not the programmer.

Treating the linker as a type of task builder, its main functions are:

To concatenate code and data from the various input module streams.

To allocate values to symbolic labels which have not been explicitly given constant values by the programmer – eg. using equ directives.

To generate the absolute machine-code executable file together with any symbol, listing and link-time error files.

In order to allow the linker to do its job, it must have knowledge of the memory architecture of the target processor; basically where the array of general-purpose file registers start and end, where the vectors reside in Program memory and where the code begins and ends. In the case of Microchip’s mplink.exe linker this information is supplied in the form of a linker command file.

A simple example of such a command file for a PIC16F84 is given in Table 8.5. Three directives are used in the file.8

codepage

The codepage directive is used for program code. These directives are here used to define two regions, one for the Reset and Interrupt vectors

8Microchip’s MPASM Users Guide with MPLINK and MPLIB manual gives a full list of linker directives.

.translation code level-assembly Relocatable 3.8 .Fig

Relocatable Listing file

Assembler Error file

Absolute Listing file

Absolute Symbol file

Linker Error file

Source file

Relocatable

Absolute Machine-code file

Binary data/addresses

Relocating assembler

Linker

Loader

Object code

(Absolute Object code)

Relocatable Object-code files from other modules, and libraries

Program

PIC

memory

EPROM

language Assembly .8

211


212 The Quintessential PIC Microcontroller

Table 8.5: The pic16f84.lkr linker command file.

//File: pic16f84.lkr

//Simple linker command file for 16F84

//Created by S.J. Katzen

//16/05/1999

CODEPAGE

NAME=vec

START=0x0

END=0x4

CODEPAGE

NAME=program

START=0x5

END=0x3FF

DATABANK

NAME=gprs

START=0x0C

END=0x4F

SECTION

NAME=VECTORS

ROM=vec

//

Reset & int vectors

SECTION

NAME=TEXT

ROM=program

//

ROM code space

in between 000h and 004h called vec and the other called program to be used for executable code from 005h through 3FFh. Notice the use of the prefix 0x to denote the hexadecimal base. This is the notation used in the C language.

databank

This is similar to codepage but is used for variable data in RAM. Here the file register array between File 0Ch and File 4Fh is called gprs.

section

This linker directive names two code streams. The first called VECTORS will be used by the programmer to store the two vector goto instructions while TEXT is used for the core program code. The source code assembler directive code with the appropriate label tells the linker which stream any following code is to be placed; for example, see Program 8.2. As many code sections from any codepage can be created as desired. For instance, all subroutines may be placed together in Program memory by modifying the linker file thus:

SECTION

NAME=TEXT

ROM=program

//

ROM

code space

SECTION

NAME=SUBROUTINES ROM=program

//

ROM

subroutine

stream

Sections can be made from DATABANK memory with RAM replacing the ROM attribute. In our case we have not defined a data section and the unlabelled assembler directive udata (Uninitialiized DATA) allows space to be reserved for labels in the general-purpose register array; see Program 8.4.

To illustrate the principle of linking we will implement the mathemat-

ical function NUM_12 + NUM_22, known as root mean square. There are three teams working on this problem.9 Tasks have been allocated by the project manager (a fourth person?) as follows:

1. The main function which sequences the steps:

9Obviously this is a ridiculously simple problem for team work but it illustrates the principle in a manageable space.


8. Assembly language 213

Relocatable

assembler

rms.lst

main.asm

main.o

Linker

sqr.asm

sqr.o

+

rms.hex

rms.map

root2.asm

root2.o

Linker

script

pic16f84.lkr

Fig. 8.4 Linking three source files to implement a root mean square program.

(a)Square NUM_1.

(b)Square NUM_2.

(c)Add NUM_12 + NUM_22

(d)Square root item (c).

2.Design of a subroutine to square a byte number in the Working register to give a double-byte outcome in two GPRs.

3.Design of a subroutine to evaluate the square root of a double-byte sum and return it in W.

The process based on this decomposition of the task is shown diagrammatically in Fig. 8.4.

The main function is shown in Program 8.2. The program commences with the Reset goto instruction and is located in the VECTORS code stream. From the MAIN label onwards, code is located in the TEXT code stream using the directive TEXT code. We see from the map file output by the linker in Table 8.6 that MAIN is located at 005h.

The main routine uses four variables located in general-purpose file. These are placed in uninitialized RAM with the directives udata and res. A single file register is reserved for each of the two input variables NUM_1 and NUM_2 respectively. Two bytes are reserved for SUM which is used to hold the sum NUM_1 + NUM_2. As this is to be the input for the subroutine SQR_ROOT, it is declared global at the end of the file. This means that the location is public, that is additional files that are linked together can use the label SUM by declaring it extern – i.e. external to the file. Variables not declared thus are ‘hidden’ from the outside world, i.e. are private (or local) variables. In this manner the directive extern at the head of Program 8.2 allows the main routine to call the subroutines SQR_ROOT and SQR without knowing in advance where they are. In the same way the variable SQUARE is used by subroutine SQR to return the square of the byte sent to it in W. Space for this is reserved in a GPR in subroutine SQR and its exact whereabouts is not known by main.asm but will be allocated later by the linker. From the map file of Table 8.6 it is finally located in File 11h.


214 The Quintessential PIC Microcontroller

Program 8.2 The main relocatable source file main.asm.

include

"p16f84.inc"

extern

SQR_ROOT, SQR, SQUARE

udata

;

Reserve static data

NUM_1

res

1

;

The first number

NUM_2

res

1

;

The second number

SUM

res

2

;

Two bytes HI:LO for the sum

RMS

res

1

;

One byte for the outcome

VECTORS

code

goto

MAIN

;

The Reset vector

TEXT

code

MAIN

movf

NUM_1,w

;

Get Number 1

call

SQR

;

Square it

movf

SQUARE+1,w

;

Get lower byte

movwf

SUM+1

;

Is the low byte of sum

movf

SQUARE,w

;

Get upper byte

movwf

SUM

;

Is the high byte of sum

movf

NUM_2,w

;

Now get Number 2

call

SQR

;

Square it

movf

SQUARE+1,w

;

Get lower byte

addwf

SUM+1,f

;

Add to the low byte of sum

btfsc

STATUS,C

;

Check if produces carry

incf

SUM,f

;

Add the carry

movf

SQUARE,w

;

Get upper byte

addwf

SUM,f

;

Add to the high byte of sum

call

SQR_ROOT

;

Work out the square root

movwf

RMS

;

which is the root mean square

global

SUM

end

The main body of the code follows the task list enumerated above. The value NUM_12 is placed in file registers SUM:SUM+1 to which the computed NUM_22 is added. The outcome is then used as input to subroutine SQR_ROOT to return the root-mean square byte in W. Finally this is copied to the file register named RMS, for which a single byte has been reserved in the Data stream.

The subroutine sqr.asm of Program 8.3 is based on the subroutine of Program 6.5 on page 152, which multiplies two byte numbers. In this case on entry the contents of the Working register are copied to a file register labelled X and a 16-bit version constructed in X_COPY_H:X_COPY_L. The shift and add algorithm then evaluates X × X = X2. These three file registers are allocated with the directive udata_ovr (OVeRlay Uninitialized