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

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

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

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

Добавлен: 15.06.2025

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

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

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

8. Assembly language 201

org

Specifies the start address for following code otherwise the assembler defaults to 000h in the Program store. In this program the subroutine SQR_ROOT is originated at 200h.

Of course symbolic translators demand more computing power than simple hexadecimal loaders, especially in the area of memory and backup store. Prior to the introduction of personal computers in the late 1970s, either mainframe, minicomputers or special-purpose MPU/MCU development systems were required to implement the assembly process. Such implementations were inevitably expensive and inhibited the use of such computer aids, and hand-assembled coding was relatively common.

Translation software thus implements two tasks:

Conversion of the various instruction mnemonics and labels to their machine-code equivalents.

The location of the instructions and data in the appropriate memory location.

It is the second of these that is perhaps more di cult to understand. Program 8.2 is designed to be processed by an absolute assembler.

Here the programmer uses the directive org to tell the assembler to place the code in the specified Program store address. This means that the programmer needs to know where everything is to be placed. This absolute assembly process is shown in Fig. 8.2. Absolute assembly is adequate where a program is contained in a single self-contained file; which is the case for the majority of code in this text. However, real projects often consist of several thousand lines of code and require teamwork. With many modules being written by di erent people, perhaps also coming in from outside sources and libraries, some means must be found to link the appropriate modules together to give the one executable machine-code file. For example, you may have to call up a division subroutine that Fred has written some time ago. You will not know exactly where in memory this subroutine will reside until the project has been completed. What can you do? Well, a subroutine should have its entry point labelled; say, DIV in this case. You should be able to direct the assembler to give this label the attribute that its absolute value is to be found later by a linker program. We will look at this relocatable way of working later on in the chapter.

Most programs running on the lowand mid-range PICs are adequately handled by an absolute assembler. To clarify the process we will take the subroutine of Fig. 8.2 through from the creation of the source file to the final absolute machine-code file.

Editing

Initially the source file must be created using a text editor. A text editor di ers from a wordprocessor in that no embedded control codes, giving

202 The Quintessential PIC Microcontroller

y

Binary data/addresses

Absolute Machine-code file

(Absolute Object code)

Errorfile

Symbolfile

Listingfile

Source file

memor Program

EPROM

PIC

Fig. 8.2 Absolute assembly-level code translation.

formatting and other information, are inserted. For instance, there is no line wrapping; if you want a new line then you hit the [ENT] key. Most operating systems come with a simple text editor; for example, notepad for Microsoft’s Windows. Third-party products are also available and most wordprocessors have a text mode which can double as a program editor.3 Microchip-compatible assembly-level source files names have an extension .src.

3For example, some programs for this book were created using Wordstar 2000 in its non-document format.


8. Assembly language 203

The format of a typical line of source code looks like:

Label (optional) Destination operand

SQREND movf COUNT,w ; Copy into W

Instruction mnemonic Source operand Comment (optional)

With the exception of comment-only lines, all lines must contain an instruction (either executable by the MCU or a directive) and any relevant operand or operands. Any label must begin in column 1, otherwise the first character must be a space or a tab to indicate no label. A label can be up to 32 alphanumeric, underline or question mark characters with the proviso that the first character be an underline or letter. Labels are usually case sensitive. A line label names the Program store address of the first following executable instruction.

An optional comment is delineated by a semicolon, and whole-line comments are permitted – see lines 11–18 of Program 8.1. Comments are ignored by the assembler and are there solely for human-readable documentation. Notes should be copious and should explain what the program is doing, and not simply repeat the instruction. For example:

movf I,w

; Move I into W

is a waste of energy:

movf I,w

; Get high byte of magic number

is rather more worthwhile. Not, or minimally, commenting source code is a frequent failing, not confined to students. A poorly documented program is di cult to debug and subsequently to alter or extend. The latter is sometimes known as program maintenance.

Space should separate the instruction from any operand. Where there are two operands the source and destination fields are delineated by a comma. In instructions where the destination can be the Working register or the addressed file register, the predefined names w or f should appear in the destination fields or numbers 0 or 1 respectively. The assembler will default to destination file if omitted.

Assembling

The assembler program will scan the source file checking for syntax errors. If there no such errors the process goes on to translate to absolute object code; which is basically machine code with information concerning the location it is to be placed in Program memory. Syntax errors include such things as referring to labels that don’t exist or instructions that are not recognized. The output will include an error file giving any such errors. If there are no syntax errors, a listing file and machine-code file are generated.

In the case of our example the translation was invoked by entering:

204 The Quintessential PIC Microcontroller

mpasmwin /aINHX8M /e+ /l+ /c+ /rhex /p16f84 root.asm

where mpasmwin.exe is the name of the assembler program and root.asm is the specified source file. The flags are of the form /<option> and may be followed by + or - to enable or disable the option. Thus /e+ orders the production of an error file, /l+ likewise for a listing file, /c+ makes labels case sensitive, /rhex specifies the default base radix to be hexadecimal. The flag /p16f84 tells the assembler to treat the source file as pertaining to the PIC16F84 device. mpasmwin can translate code for all PIC devices; whether for 12-, 14or 16-bit cores.

The listing file shown in Table 8.1 reproduces the original source code, with the addition of the hexadecimal location of each instruction and its code. The values of any symbols (such as NUM which is listed as File 20h) is also itemized.

The listing file also provides a symbol table enumerating all symbols/labels defined in the program. The memory usage map gives a graphical representation of Program memory usage. Any warning messages are embedded in the file where they are applicable. For example, if the destination operand w or f is omitted the assembler will default to the latter and embed a warning message at that instruction in the listing file.

This file has only documentation value and is not executable by the processor.

Executable code

The concluding outcome of any translation process is the object file, sometimes known as the machine-code file. Once the specified code is in situ in the Program store, it may be run as the executable program.

As can be seen in Table 8.2, such files consist essentially of lines of hexadecimal digits representing the binary machine code, each preceded by the address of the first byte location of the line. This file can be used by the PIC programmer to put the code into Program ROM memory at the correct place. As the location of each code byte is explicitly specified, this type of file is known as absolute object code. The software component of the PIC programmer reading, deciphering and placing this code is sometimes called an absolute loader.

In the MPU/MCU world there are many di erent formats in common use. Although most of these de facto standards are manufacturerspecific, in the main they can be used for any brand of MPU/MCU. The format of the machine-code file shown here is known as 8-bit Intel hex and was specified with the flag /a INHEX8M.

Let us look at one of the lines in root.hex in more detail.


8. Assembly language 205

Start of data record marker

Byte

address of

first

datum

Machine

code

:

10

0400

00

3C

A401 A201

A301

A30A

2308 A102

2208

031C

Record type = code record

Checksum

Number

of bytes following marker

Table 8.1 The listing file root.lst. (continued next page).

Listing

MPASM 02.20 Released

ROOT.ASM

5-9-1999 14:18:12

PAGE 1

LOC OBJECT CODE LINE SOURCE TEXT

VALUE

01

; Global declarations

00000003

02

STATUS

equ

3

; Status register is File 3

00000000

03

C

equ

0

; Carry/Not Borrow flag is bit0

04

05

cblock 20h

00000020

06

NUM:2

; Number: high byte, low byte

07

endc

0000

2A00

08

MAIN

goto

SQR_ROOT

09

10

; ***********************************************************

11

12

; * FUNCTION: Calculates the square root of a 16-bit integer*

13

; * EXAMPLE : Number = FFFFh (65,535d), Root = FFh (255d)

*

14

; * ENTRY

: Number in File NUM:NUM+1

*

15

; * EXIT

: Root in W. NUM:NUM+1; I:I+1 and COUNT altered *

16

; ***********************************************************

17

; Local declarations

18

19

cblock

00000022

20

I:2, COUNT

; Magic number hi:lo byte & loop count

21

endc

0200

22

org

200h

23

0200

01A4

24

SQR_ROOT clrf

COUNT

; Task 1: Zero loop count

25

0201

01A2

26

clrf

I

; Task 2: Set magic number I to one

0202

01A3

27

clrf

I+1

0203

0AA3 28

incf

I+1,f

29

30

; Task 3: DO

0204

0823

31

SQR_LOOP movf

I+1,w

; Task 3(a): Number - I

0205

02A1

32

subwf

NUM+1,f ; Subtract lo byte I from lo byte Num

0206

0822

33

movf

I,w

; Get high byte magic number

0207

1C03

34

btfss

STATUS,C; Skip if No Borrow out

0208

3E01

35

addlw

1

; Return borrow

0209

02A0

36

subwf

NUM,f

; Subtract high bytes

37

38

; Task 3(b): IF

underflow THEN exit

020A

1C03

39

btfss

STATUS,C; IF No Borrow THEN continue

020B

2A13

40

goto

SQR_END ; ELSE the process is complete

41

020C

0AA4 42

incf

COUNT,f ; Task 3(c): ELSE inc loop count

43

020D

0823

44

movf

I+1,w

; Task 3(d): Add 2 to the magic number

020E

3E02

45

addlw

2

020F

1803

46

btfsc

STATUS,C; IF no carry THEN done

0210

0AA2 47

incf

I,f

; ELSE add carry to upper byte I

0211

00A3

48

movwf

I+1

0212

2A04

49

goto

SQR_LOOP

50

0213

0824

51

SQR_END

movf

COUNT,w ; Task 4: Return loop count as root

0214

0008

52

return

53

end


206 The Quintessential PIC Microcontroller

Table 8.1: (continued). The listing file root.lst.

MPASM 02.20 Released

ROOT.ASM

5-9-1999 14:18:12 PAGE 2

SYMBOL TABLE

LABEL

VALUE

C

00000000

COUNT

00000024

I

00000022

MAIN

00000000

NUM

00000020

SQR_END

00000213

SQR_LOOP

00000204

SQR_ROOT

00000200

STATUS

00000003

__16F84

00000001

MEMORY USAGE MAP (’X’ = Used,

’-’ = Unused)

0000

:

X---------------

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

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

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

0200

:

XXXXXXXXXXXXXXXX

XXXXX-----------

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

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

All other memory blocks unused.

Program Memory Words Used: 22

Program Memory Words Free: 1002

Errors

:

0

Warnings :

0

reported,

0

suppressed

Messages :

0

reported,

0

suppressed

Table 8.2: The absolute 8-bit Intel format object-code file root.hex.

:02000000002AD4

:10040000A401A201A301A30A2308A1022208031C3C

:10041000013EA002031C132AA40A2308023E03186B

:0A042000A20AA300042A2408080021

:00000001FF

The loader recognizes that a record follows when the character : is received. The colon is followed by a 2-digit hexadecimal number representing the number of machine-code bytes in the record; 10h = 16d in this case. The next four hexadecimal digits represent the starting byte address 0400h. This is twice the PIC’s Program store address of 200h, as each instruction takes up two bytes. The following 2-digit number is 00h for a normal record and 01h for the end-of-file record – see the last line of Table 8.2. The core of the record is the machine code with each instruction taking two 2-digit hexadecimal bytes ordered low:high byte. The loader reads this lower byte first (eg. A4) and then ‘tacks on’ the upper byte (eg. 01h) giving a 12-, 14or 16-bit program word as appro-


8. Assembly language 207

priate to the target PIC core – eg. 01A4 for a 14-bit core clrf 24h.4 The final byte is known as a checksum. The checksum is calculated as the 2’s complement of the sum of all preceding bytes in the record; that is −sum. As a check-up on transmission accuracy, the loader adds up all received bytes including this checksum for each record. This received count should give zero if no download error has occurred.

Assemblers are very particular that the syntax is correct. If there are syntax errors5 then an error file will be generated. For example, if line 49 was mistakenly entered as:

got SQRLOOP

then the error file of Table 8.3 below is generated.

Table 8.3: The error file

Warning[207]

ROOT.ASM

49

: Found label after column 1. (got)

Error[122]

ROOT.ASM

49

: Illegal opcode (SQRLOOP)

The assembler does not recognize got as an instruction or directive mnemonic and erroneously assumes that it is a label mistakenly not beginning in column 1. On this basis it assumes that SQRLOOP is an instruction/directive mnemonic and again does not recognize it.

Most assemblers allow the programmer to define a sequence of processor instructions as a macro instruction. Such macro instructions can subsequently be used in a similar manner to native instructions. For example, the following code defines a macro instruction called Delay_1ms6 that implements a 1 ms delay when executed on a PIC running with a 4 MHz crystal. The directive pair macro - endm is used to enclose the sequence of native instructions which will be substituted when the mnemonic Delay_1ms is used anywhere in the subsequent program. The mnemonic will be replaced by the assembler with the defined code. Note that this will be in-line code unlike calling up a subroutine.

4Locating the multi-byte code in memory in the Intel way, formatted low:high byte, is known as big-endian (high byte is in the higher memory location) whereas the low-endian arrangement is favored by amongst others, Motorola.

5If the assembler announces that there are no errors then there is a tendency to think that the program will work. Unfortunately a lack of syntax errors in no way guarantees that the program will do anything of the sort!

6I have capitalized the first letter of all macro instructions to distinguish them from native instructions.

208 The Quintessential PIC Microcontroller

Delay_1ms

macro

LOOP

local

movlw

d’250’

; Count from 250d

LOOP

addlw

-1

; Decrement

btfss

STATUS,Z

; to zero

goto

LOOP

endm

Where labels are used within the body of the macro, they should be declared using the local directive. This means that any conflict with labels where a macro instruction is evoked more than once is avoided.

This example is unusual in that the ‘instruction’ did not have any operands. Like native instructions, macros can have one or more operands. To see how this is done, consider a macro instruction called Bnz for Branch if Not Zero.7 Thus the instruction Bnz NEXT causes execution to transfer to the specified label if the Z flag is zero, otherwise continue on as normal. The definition of Bnz is:

Bnz

macro

destination

btfss

STATUS,Z

goto

destination

endm

Macros can be of any arbitrary complexity and can have any number of comma separated operands. For example, Microchip have available a large number of macros implementing arithmetic operations such as 16 × 16 and 32 × 32 multiplication. However, extensive use of macros can make programs di cult to debug, especially when an apparently simple macro instruction hides a number of side e ects which alter register contents and flags. A frequent source of error is to precede a macro instruction with a skip instruction, intending to branch around it on some condition. As the macro instruction is in fact a structure of several native instructions, this skip will actually be into the middle of the macro – with dire consequences.

Macro definitions, whether commercial or/and in-house may be collected together as a single file and included in the user program using the include directive. Thus if your file is called mymacros.mac then the line at the beginning of your program

include "mymacros.mac"

will allow access by the programmer to all macro definitions in the file. The assembler will only generate machine code for any macro instruc-

7This is a native instruction for the PIC18CXXX family.