Useage:- A84 filename.ext
Outputs:- filename.HEX (Intel Hex Format INHX8M)
filename.LST
filename.OLD and filename.ext (If errors)
MINIMUM requirements:- .COM files are not supported in 64 bit versions of Windows.)Local labels are the closest labels having that name in either forward or reverse directions.
Eg: A1:, H2:, X0:, O0: and Z9:are all local labels.
To jump BACK to the closest local label just specify the label. Eg:-
a2: ;local label A2
btfss portb,6 ;wait for b6 to go high
goto a2 ;jump backwards the the nearest A2
To jump FORWARDS to the closest local label place a '>' before the
label. Eg:-
btfss status,c
goto >a3 ;forward local jump to the first A3
bsf portA,2 ;set bit 2 portA
a3: ;local label A3
Consider this simple code example for interfacing with a PC parallel
port which demonstrates free-form structure and local labels:-
SEND_BYTE: ;byte to be sent is in W
movwf txreg ;put W into transmit register
movlw 8 ;eight bits
movwf bit ;a counter for bits
a1:
btfsc portb,6 ;wait for ack to go low
goto a1
rrf txreg,f ;roll right bit 0 into carry
btfss status,c ;if carry 0, we want to clear bit (a low)
goto >a2 ;else we set bit, (a high)
bsf portA,2
goto >a4
a2:
bcf portA,2
a4:
bsf portA,4 ;raise clk
a2:
btfss portb,6 ;wait for ack to go high
goto a2
bcf portA,4 ;lower clk
decfsz bit,f ;dec bit, skip loop when zero
goto a1
return
Rather than giving labels their own column, they head a block of
code. Use capitals only for labels. They don't have to be capitals but
they stand out better. Making the whole code upper-case lowers the
readability.
The same code in conventional format:-
SEND_BYTE MOVWF TXREG ;put W into transmit counter
MOVLW 8 ;eight bits
MOVWF BIT ;a counter for bits
ANOTHER_BIT BTFSC PORTB,6 ;wait for ack to go low
GOTO ANOTHER_BIT
RRF TXREG,F ;roll right bit 0 into carry
BTFSS STATUS,C ;if carry 0, we want to clear bit (a low)
GOTO CLEARBIT ;else we set bit, (a high)
BSF PORTA,2
GOTO RAISE_CLK
CLEARBIT BCF PORTA,2
RAISE_CLK BSF PORTA,4 ;raise clk
WAIT_FOR_ACK BTFSS PORTB,6 ;wait for ack to go high
GOTO WAIT_FOR_ACK
BCF PORTA,4 ;lower clk
DECFSZ BIT,F ;dec bit, skip loop when zero
GOTO ANOTHER_BIT
RETURN
This is slightly more compact but it's structure is harder to see.
A84 will assemble this code however, if the labels have a colon added
on.
;register definitions
flags equ 24
string equ 26 ;reg 26 is start of 10 byte text string
counter equ 36
;initial variables
seconds equ 34567
delay1 equ 100
delay2 equ 150
word_val equ 0F09A
length equ 32
direction equ 5 ;flags bit 5
ok_message equ 'OK' ;16 bit definition $4B4F
word_2 equ -1 ;word_2 equals h'FFFF'
;do calculations
minutes equ seconds / 60 ;convert to mins = 576
hours equ minutes / 60 ;convert to hours = 9
mean_delay equ (delay1+delay2)/2 ;calculate mean delay = 125
lowbits equ mean_delay & 111xb ;clear high bits from MEAN_DELAY
high_byte equ word_val/0100 ;separate WORD_VAL into high
low_byte equ word_val-high_byte*0100 ; and low bytes:- F0:9A
volume equ length^3
;coding examples
decfsz counter+1,f ;decfsz register 26
goto $+3 ;skip the next 2 instructions
movlw (mean_delay/2)+1 ;reset loop counter
movwf counter+1 ;move w to register 26
call table+10 ;directly address a RETLW table entry
movwf string+1 ;move w to 2nd byte of string
movlw 2^direction ;toggle direction flag (bit 5)
xorwf flags,f
Calculations are performed from right to left, eg:-
MOVLW 340 / 20 + 6 * 4 - 2This will put 10 into w, ie, 4-2=2, 6*2=12, 20+12=32, then 340/32=10.
Use brackets if you are unsure:-
MOVLW (340/20)+(6*4)-2 ;this will put 39 into w
ch1 equ 'C' ch2 equ 'K' string db (ch2-'A') dup (((ch2-ch1)/2)+ch1)
The results of all calculations are shown in the LST file.
radix hex
FFFB B998 equ -1+4 ;calculating right to left = -5
03 B996 equ (-1)+4
radix dec
64 A110 equ 4*014+3-111xb
4 A97 equ 2^(5-3)
4 3020 32 movlw 2^direction
NB:Because some text editors when searching confuse a tilde ~ with a
circumplex ^, a tick ` can be used instead of a circumplex for
exponent. Other assemblers may not support this.
4 A97 equ 2`(5-3)
4 3020 32 movlw 2`direction
To specify the current adress use $, eg:-
GOTO $ ;endless loop
GOTO $+10 ;skip the next 9 instructions
LF EQU 0A
CR EQU 0D
EEORG 5 ;For compatibility you can also use ORG h'2105'
DB 2 ;This will define a 2 at EEPROM location 5.
EEORG 15
db 10 ;define 10 at EEPROM location 15 (No label)
FRED db 10 ;This example gives the byte a label. FRED equals 16
TESTDB db 2 dup ('Xyz',LF,CR) ;Data definition using DUP
dw 1 ;Word definition in INTEL format
This will define (in decimal):- 88,121,122,10,13,88,121,122,10,13,1,0
at EEPROM location 17. The label TESTDB will be equal to 17.
STRING1 db 'The quick brown fox ......',0 ;a 27 byte ASCIIZ string
__CONFIG _rc_osc, _wdt_off & _pwrte_on ;config terms
__CONFIG 11110011xb ;alternative method
ADDWF ANDWF COMF DECF DECFSZ INC INCFSZ
IORWF MOVF RLF RRF SUBWF SWAPF XORWF
No other default destinations are employed.
h'20', $ABC, 23h and 0x10 are all HEX. 020, 020d, 0ABC and 010 are also all HEX. 20, 20d, d'20' and 10 are DECIMAL. ABC is a label.
Binary numbers can simply end with "XB". Eg:- 10001010xb is the same as b'10001010'
Eg:
DW DEFB ;is it 57,083 or a label "DEFB" ?
DW 0DEFA ;no mistake - it is 57,082
Use RADIX DEC or RADIX d'10' to change back to decimal.
Byte-Oriented File Register Operations
Mnemonic Ops Description Cycles MSB (opcode) LSB Status Notes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ADDWF f, d Add W and f 1 00 0111 dfff ffff C,DC,Z 1,2
ANDWF f, d AND W with f 1 00 0101 dfff ffff Z 1,2
CLRF f Clear f 1 00 0001 lfff ffff Z 2
CLRW Clear W 1 00 0001 0xxx xxxx Z
COMF f,d Complement f 1 00 1001 dfff ffff Z 1,2
DECF f, d Decrement f 1 00 0011 dfff ffff Z 1,2
DECFSZ f, d Decrement f,Skip if 0 1(2) 00 1011 dfff ffff 1,2,3
INCF f, d Increment f 1 00 1010 dfff ffff Z 1,2
INCFSZ f, d Increment f,Skip if 0 1(2) 00 1111 dfff ffff 1,2,3
IORWF f, d Inclusive OR W with f 1 00 0100 dfff ffff Z 1,2
MOVF f, d Move f to d (w or f) 1 00 1000 dfff ffff Z 1,2
MOVWF f Move W to f 1 00 0000 lfff ffff
NOP No Operation 1 00 0000 0xx0 0000
RLF f, d Rotate Left f through C 1 00 1101 dfff ffff C 1,2
RRF f, d Rotate Rght f through C 1 00 1100 dfff ffff C 1,2
SUBWF f, d Subtract W from f 1 00 0010 dfff ffff C,DC,Z 1,2
SWAPF f, d Swap nibbles in f 1 00 1110 dfff ffff 1,2
XORWF f, d Exclusive OR W with f 1 00 0110 dfff ffff Z 1,2
Bit-Oriented File Register Operations
BCF f, b Bit Clear f 1 01 00bb bfff ffff 1,2
BSF f, b Bit Set f 1 01 01bb bfff ffff 1,2
BTFSC f, b Bit Test f Skip if 0 1(2) 01 10bb bfff ffff 3
BTFSS f, b Bit Test f Skip if 1 1(2) 01 11bb bfff ffff 3
Literal and Control Operations
ADDLW k Add literal and W 1 11 111x kkkk kkkk C,DC,Z
ANDLW k AND literal with W 1 11 1001 kkkk kkkk Z
CALL k Call subroutine 2 10 0kkk kkkk kkkk __ __
CLRWDT Clear Watchdog Timer 1 00 0000 0110 0100 TO,PD
GOTO k Go to address 2 10 1kkk kkkk kkkk
IORLW k Incl OR literal with W 1 11 1000 kkkk kkkk Z
MOVLW k Move literal to W 1 11 00xx kkkk kkkk
RETFIE Ret from interrupt 2 00 0000 0000 1001
RETLW k Ret with literal in W 2 11 01xx kkkk kkkk
RETURN Return from Subroutine 2 00 0000 0000 1000 __ __
SLEEP Go into standby mode 1 00 0000 0110 0011 TO,PD
SUBLW k Subtract W from literal 1 11 110x kkkk kkkk C,DC,Z
XORLW k Excl OR literal with W 1 11 1010 kkkk kkkk Z
Note 1:- When an I/O register is modified as a function of itself ( e.g.,
MOVF PORTB, 1), the value used will be that value present on the
pins themselves. For example, if the data latch is '1' for a pin
configured as input and is driven low by an external device, the
data will be written back with a '0'.
Note 2:- If this instruction is executed on the TMR0 register (and, where
applicable, d = 1), the prescaler will be cleared if assigned to
the Timer0 Module.
Note 3:- If Program Counter (PC) is modified or a conditional test is true,
the instruction requires two cycles. The second cycle is executed
as a NOP.
Mnemonic Substituted Mnemonic Substituted
~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~ ~~~~~~~~~~~
NEGF f,d Comf f,f BNDC k Btfss 3,1
Incf f,d Goto k
ADDDCF f,d Btfsc 3,1 BNZ k Btfss 3,2
Incf f,d Goto k
ADDCF f,d Btfsc 3,0 BZ k Btfsc 3,2
Incf f,d Goto k
SUBCF f,d Btfsc 3,0 B k Goto k
Decf f,d CLRC Bcf 3,0
CLRDC Bcf 3,1
SUBDCF f,d Btfsc 3,1 CLRZ Bcf 3,2
Decf f,d SETC Bsf 3,0
SETDC Bsf 3,1
BC k Btfsc 3,0 SETZ Bsf 3,2
Goto k SKPC Btfss 3,0
SKPDC Btfss 3,1
BDC k Btfsc 3,1 SKPNC Btfsc 3,0
Goto k SKPNDC Btfsc 3,1
SKPNZ Btfsc 3,2
BNC k Btfss 3,0 MOVFW f Movf f,w
Goto k TSTF f Movf f,f
RET same as RETURN
IRET same as RETFIE
JMP same as GOTO
CLI same as BCF INTCON,GIE
STI same as BSF INTCON,GIE
Because some text editors when searching confuse a tilde ~ with a
circumplex ^, a tick ` can be used instead of a circumplex for exponent.
COMMENT ..... /COMMENT
The COMMENT mnemonic can be used to "REM-OUT" a block of text. Finnish the block with /COMMENT
COMMENT
This is a comment
/COMMENT
Alternatively the A86 style of comment can be used.
COMMENT c ....... cWhere "c" is any character. Example:-
COMMENT @
This is a comment
@
The /COMMENT mnemonic can also be used on it's own as a "REM" eg:-
/COMMENT This is a comment.This means that to un-comment a block of code simply insert a semi-colon before the COMMENT mnemonic. A quick way of isolating chunks of code. Eg:-
;COMMENT
This is NOT a comment and will produce an error message.
/COMMENT This IS a comment and can stay in.
@echo off
:again
ed %1.asm
a84 %1.asm
if errorlevel=1 then goto again
pause
topic %1.hex
(Assuming you use David Tait's TOPIC programmer, and an editor
called ED).
TITLE
ERRORLEVEL
END
The first line of the LST file indicates the name of the source file and its date.
CONFIG data is listed in both HEX and BINARY (LSB). Defined data is listed in HEX.
21 bit equ 21
8 char equ eedata
9 pointer equ eeadr
2007 3FF3 11110011xb __config _RC_OSC, _WDT_OFF & _PWRTE_ON
5 eeorg 5
2105 41 38 34 20 69 73 20 sample_text db 'A84 is a free-form assembler that '
210C 61 20 66 72 65 65 2D
2113 66 6F 72 6D 20 61 73
211A 73 65 6D 62 6C 65 72
2121 20 74 68 61 74 20
If the HEX_LIST directive is used the LST file is in HEX regardless of the RADIX in force.
If the RADIX is set to HEX then Term1 & Term2 are listed in HEX, otherwise in DECIMAL.
Inst# Opcd Term1 Term2
----- ---- ----- -----
24 org 24
24 1683 3 5 bsf status,rp0
25 1408 8 0 bsf eecon1,rd
26 1283 3 5 bcf status,rp0
27 0008 return
The same code with RADIX set to HEX:-
radix hex
18 org d'24'
0018 1683 03 05 bsf status,rp0
0019 1408 08 00 bsf eecon1,rd
001A 1283 03 05 bcf status,rp0
001B 0008 return
BIT 21 0015 CHAR 8 0008
POINTER 9 0009 SAMPLE_TEXT 5 0005
A list of internal definitions will only be included in the
list file if you include the FULL_LIST directive.
The file PICOUT.A84 is a simple A84 program that sends a string via the parallel port to a PC.
To assemble it enter:-
This will transfer data using a single bit at a faster rate than can be obtained via RS232 using a 4Mhz crystal. As well, the PIC will wait indefinatly for the PC, and the PC for up to 10 seconds if either computer is interupted.
Connections to the PC parallel port:-
PIC A3 (pin 2) --> PRN S4 + (pin 13)
PIC A2 (pin 1) --> PRN S5 + (pin 12)
PIC B6 (pin 12) <-- PRN C0 - (pin 1)
PIC ground <--> PRN ground (pin 25)
Use 1K resistors in series with each data line.
Also wire a Button switch or jumper from PIC B2 (pin 8) to ground.
To use it, run PICIN.COM on the PC. Be sure to check your port address.
As it is, PICIN.COM is set to use port 0378. If you have A86
you can change this in the source code supplied (PICIN.A86) and
re-assemble. If you don't have A86 you can download the shareware version
from www.eji.com. A84 was written using A86.
Run PICIN and press button to send the string.
PICIN.COM times out after 10 seconds and returns to DOS when waiting for button press or char from PIC.
David Dorling
* A86 is an assembler for the Intel 8086++ processors by Eric Isaacson,
416 E. University Ave., Bloomington, IN 47401-4739 www.eji.com