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
B = 3 'B is a SFR too
MUL AB 'acc = acc * b
Print 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 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