Assembly Language Programming

 

In line assembly
Assembler statements are recognized by the compiler.
The only exception is SWAP because this is a valid BASIC statement.
You must precede this ASM-statement with the !-sign so the compiler knows that you mean the ASM SWAP statement.

Note that for the ACC register, A is used in mnemonics.( Except for bit operations )

Example:
Mov a, #10 'ok
Mov acc,#10 'also ok but generates 1 more byte
Setb acc.0 'ok
Setb a.0 'NOT OK

You can also include an assembler file with the $INCLUDE FILE.ASM statement.

The assembler is based on the standard Intel mnemonics.
The following codes are used to describe the mnemonics:


Rn working register R0-R7
Direct 128 internal RAM locations, any IO port, control or status register.
For example : P1, P3, ACC
@Ri indirect internal RAM location addressed by register R0 or R1
#data 8-bit constant included in instruction
#data16 16-bit constant included in instruction
Bit 128 software flags, any IO pin, control or status bit
For example : ACC.0, P1.0, P1.1

Boolean variable manipulation :

CLR C clear carry flag
CLR bit clear direct bit
SETB C set carry flag
SETB bit set direct bit
CPL C complement carry flag
CPL bit complement direct bit
ANL C, bit AND direct bit to carry flag
ORL C,bit OR direct bit to carry flag
MOV C,bit Move direct bit to carry flag

Program and machine control :

LCALL addr16 long subroutine call
RET return from subroutine
RETI return from interrupt
LJMP addr16 long jump
SJMP rel short jump (relative address)
JMP @A+DPTR jump indirect relative to the DPTR
JZ rel jump if accu is zero
JNZ rel jump if accu is not zero
JC rel jump if carry flag is set
JNC rel jump if carry flag is not set
JB bit,rel jump if direct bit is set
JNB bit,rel jump if direct bit is not set
JBC bit,rel jump if direct bit is set & clear bit
CJNE A,direct,rel compare direct to A & jump of not equal
CJNE A,#data,rel comp. I'mmed. to A & jump if not equal
CJNE Rn,#data,rel comp. I'mmed. to reg. & jump if not equal
CJNE @Ri,#data,rel comp. I'mmed. to ind. & jump if not equal
DJNZ Rn,rel decrement register & jump if not zero
DJNZ direct,rel decrement direct & jump if not zero
NOP No operation

Arithmetic operations :

ADD A,Rn add register to accu
ADD A,direct add register byte to accu
ADD A,@Ri add indirect RAM to accu
ADD A,#data add immediate data to accu
ADDC A,Rn add register to accu with carry
ADDC A,direct add direct byte to accu with carry flag
ADDC A,@Ri add indirect RAM to accu with carry flag
ADDC A,#data add immediate data to accu with carry flag
SUBB A,Rn subtract register from A with borrow
SUBB A,direct subtract direct byte from A with borrow
SUBB A,@Ri subtract indirect RAM from A with borrow
SUBB A,#data subtract immediate data from A with borrow
INC A increment accumulator
INC Rn increment register
INC direct increment direct byte
INC@Ri increment indirect RAM
DEC A decrement accumulator
DEC Rn decrement register
DEC direct decrement direct byte
DEC@Ri decrement indirect RAM
INC DPTR increment datapointer
MUL AB multiply A & B
DIV AB divide A by B
DA A decimal adjust accu

Logical operations :

ANL A,Rn AND register to accu
ANL A,direct AND direct byte to accu
ANL A,@Ri AND indirect RAM to accu
ANL A,#data AND immediate data to accu
ANL direct,A AND accu to direct byte
ANL direct,#data AND immediate data to direct byte
ORL A,Rn OR register to accu
ORL A,direct OR direct byte to accu
ORL A,@Ri OR indirect RAM to accu
ORL A,#data OR immediate data to accu
ORL direct,A ORL accu to direct byte
ORL direct,#data ORL immediate data to direct byte
XRL A,Rn exclusive OR register to accu
XRL A,direct exclusive OR direct byte to accu
XRL A,@Ri exclusive OR indirect RAM to accu
XRL A,#data exclusive OR immediate data to accu
XRL direct,A exclusive OR accu to direct byte
XRL direct,#data exclusive OR immediate data to direct byte
CLR A clear accu
CPL A complement accu
RL A rotate accu left
RLC A rotate A left through the carry flag
RR A rotate accu right
RRC A rotate accu right through the carry flag
SWAP A swap nibbles within the accu

Data transfer :

MOV A,Rn move register to accu
MOV A,direct move direct byte to accu
MOV A,@Ri move indirect RAM to accu
MOV A,#data move immediate data to accu
MOV Rn,A move accu to register
MOV Rn,direct move direct byte to register
MOV Rn,#data move immediate data to register
MOV direct,A move accu to direct byte
MOV direct,Rn move register to direct byte
MOV direct,direct move direct byte to direct
MOV direct,@Ri move indirect RAM to direct byte
MOV direct,#data move immediate data to direct byte
MOV@Ri,A move accu to indirect RAM
MOV@Ri,direct move direct byte to indirect RAM
MOV@Ri,#data move immediate to indirect RAM
MOV DPTR,#data16 load datapointer with a 16-bit constant
MOVC A,@A+DPTR move code byte relative to DPTR to A
MOVC A,@A+PC move code byte relative to PC to A
MOVX A,@Ri move external RAM (8-bit) to A
MOVX A,@DPTR move external; RAM (16 bit) to A
MOVX@Ri,A move A to external RAM (8-bit)
MOVX@DPTR,A move A to external RAM (16-bit)
PUSH direct push direct byte onto stack
POP direct pop direct byte from stack
XCH A,Rn exchange register with accu
XCH A,direct exchange direct byte with accu
XCH A,@Ri exchange indirect RAM with A
XCHD A,@Ri exchange low-order digit ind. RAM w. A

How to access labels from ASM.
Each label in BASCOM is changed into a period followed by the label name.

Example :
GOTO Test
Test:

generated ASM code:
LJMP .Test
.Test:

When you are using ASM-labels you can also precede them with the !-Sign so the label won't be converted.
Jb P1.0, Test ; no period
!test : ;indicate ASM label

Or you can include the period in the labelname.
Another good alternative is to use the $ASM $END ASM directives.

Example:
$Asm
mov a
,#1
test:
sjmp test
$End Asm

How variables are stored.
BIT variables are stored in bytes.
These bytes are stored from 20hex -2Fhex thus allowing 16 * 8 = 128 bit variables.
You can access a bit variable as follows:

Dim var As Bit 'dim variable
SETB {var} ; set bit
CLR {var} ; clear bit
Print var ; print value
End

Or you can use the BASIC statement SET and RESET which do the same thing.


BYTE variables are stored after the BIT variables.

Starting at address 20 hex + (used bytes for bit vars).

INTEGER/WORD variables are stored with the LSB at the lowest memory position.
LONG variables are stored with the LSB at the lowest memory position too.

You can access variables by surrounding the variable with {.
To refer to the MSB of an Integer/Word use var+1.
To refer to the MSB of a Long use var+3.

The following example shows how to access the variables from ASM

Dim t as Byte, c as Integer
CLR a ; clear register a
MOV {t} , a ; clear variable t
INC {t} ; t=t + 1
MOV {c} , {t} ; c = t
MOV {c+0}, {t} ; LSB of C = t (you don't have to enter the +0)
MOV {lain+1}, {t} ; MSB of C = t
MOV {c},#10 ; assign value

You can also change SFRs from BASIC.
P1 = 12 'this is obvious
ACC = 5 'this is ok too
f0 B = 3 'B is a SFR too
MUL AB
'acc = acc * b

Printcf0 acc

EXTERNAL variables are stored similar.
Strings are stored with a terminating zero.

Example :

$RAMSTART = 0
Dim s As String * 10 'reserve 10 bytes + 1 for string terminator

s = "abcde" 'assign string constant to string

ram location 0 = a 'first memory location
ram location 1 = b
ram location 2 = c
ram location 3 = d
ram location 4 = e
ram location 5 = #0


External variables must be accessed somewhat different.

Dim T as XRAM Byte

mov dptr,#{T} ; address of T to datapointer
mov a,#65 ; place A into acc
movx @dptr,a ; move to external memory
Print T ; print it from basic

Dim T1 as XRAM Integer
mov dptr,#{T1} ; set datapointer
mov a,#65 ; place A into acc (LSB)
movx @dptr,a ; move to external memory
inc dptr ; move datapointer
mov a,#1 ; 1 to MSB
movx @dptr,a ; move to external memory

Print T1 ; print it from basic


Helper routines
There are two new ASM helper routines that can make it a bit easier:

PLACEVALUE var , SFR
PLACEADRES var, SFR

PLACEVALUE assigns the variable, var, to the specified register, SFR.
Placevalue 1, A will generate :
Mov a,#1

Dim x as Byte
Placevalue x ,R0 will generate:
Mov a, h'3A ; in this example only of course

Where it is becoming handy is with arrays :
Placevalue a(x), RO will generate :

Mov r0,#h'3A
Mov a,@r0
Rl a
Add a,#h'1F
Mov R0,a
Mov a
,@r0

These are all examples, the generated code will differ with the type of variables used.

You can only assign 1 SFR with the PLACEVALUE statement.
This is where PLACEADRES comes around the corner.
Placeadres , places a variables address into a register.

Placeadres ar(x),A
Placeadres z , R0

When external variables are used, you don't need to specify a register because DPTR is always assigned.

Dim X as xram Integer
PLACEADRES x , dptr or PLACEADRES x
Will generate :
Mov dptr,#2

Or with arrays :
PLACEADRES ar(x)

Mov dptr,#2
Mov r0,#h'37

Mov a,@r0
Mov r2,a
Inc r0
Mov a,@r0
Mov r3,a
Mov r1,#1
Acall _AddIndex

Of course these are also examples, the generated code depends on the types and if they are internal or external variables.

Hexdecimal notation
You can also use hexadecimal notation.
Example : Mov a,#h'AA
Or use the BASIC notation :
Mov a,#&HAA

Binary notation
You can also use binary notation.
Example : Mov a,#&B10001000


Jumping with offset

You can specify an offset instead of a labelname when jumping.
Jb P1.0 , *+12 ;jump forward
Jb P1.0 , *-12 ;jump back
Jnb P1.0 , *+0 ;loop until P1.0 becomes high

This also applies to the other instructions where can be jumped to a label like SJMP, LJMP DJNZ etc.

Internal buffer for string conversion
The string conversion routines used for PRINT num , STR() and VAL(), use an internal buffer of 16 bytes. This has the advantage that no stack handling is needed but the disadvantage that a fixed space is used.

Of course you can use this buffer. It can be referenced with ___TMP_S1
So when you need a temp string, you can use this buffer.
Note that this buffer is only available with the mentioned statements!

Example :
Dim s as single
s = 1.1
Print s 'now the buffer is needed
___TMP_S1 = "Use this space"
Print ___TMP_S1

Comment
The ; sign can be used or the BASIC comment sign '
Mov a,#1 ; comment
Mov a,#2 'comment