asm Declaration
The mikroC PRO for dsPIC30/33 and PIC24 allows embedding assembly in the source code by means of the asm
declaration. The declarations _asm
and __asm
are also allowed in the mikroC PRO for dsPIC30/33 and PIC24 and have the same meaning. Note that numerals cannnot be used as absolute addresses for SFR or GPR variables in assembly instructions. Symbolic names may be used instead (listing will display these names as well as addresses).
Assembly instructions can be grouped by the asm
keyword (or _asm
, or __asm
):
asm { block of assembly instructions }
The mikroC PRO for dsPIC30/33 and PIC24 comments (both single-line and multi-line) are allowed in embedded assembly code.
The only types whose name remains the same in asm as it is in the mikroC PRO for dsPIC30/33 and PIC24 are registers, e.g. INTCON, PORTB, WREG, GIE, etc.
Accessing variables
Depending on the place of declaration, accessing a variable can be done in several ways :
- Accessing global variable :
1. If declared as static (visible only in the file where it was declared) :<source_file_name>_<variable_name>
.
2. If declared as a non-static global (visible throughout the whole project) :_<variable_name>
.
3. If accessing registers (declared throughregister
,rx
orsfr
specifiers, visible throughout the whole project) :<variable_name>
. - Accessing local variable :
<routine_name>_<variable_name>
. - Accessing routine parameter :
FARG_<routine_name>_<variable_name>
.
Here is an example of using asm instructions :
unsigned myvar absolute 0x2678; unsigned long myvar1; const char msg[] = "Test" absolute 0x3652; void main() org 0x11234 { myvar = 5; myvar1 = 0xABCDEFAB; asm { MOV _myvar, w0 ; move myvar to W0 nop MOV #6, W0 ; move literal 6 to W0 MOV W0, _myvar ; move contents of W0 to myvar MOV #lo_addr(_myvar), W1 ; retrieve low address word of _myvar and move it to W1 (0x2678 -> W1) MOV #hi_addr(_myvar), W1 ; retrieve high address word of _myvar and move it to W1 (0x0000 -> W1) MOV #lo_addr(___main_Label1), W0 ; retrieve lo address word of Label1 and move it W0 ( PC(Label1) ) -> W0 MOV #hi_addr(_main), W0 ; retrieve hi address byte of main routine and move it to W0 (0x0001 -> W1) MOV #lo_addr(_msg2), W0 ; retrieve low address word of constant msg and move it to W0 (0x3652 -> W1) MOV _myvar1+2, W1 ; accessing hi word of myvar1 variable and move it to W1 (0xABCD -> W1) } Label1: asm MOV #hi_addr(___main_Label1), W0 // retrieve hi address word of Label1 and move it W0 (PC(Label1)) -> W0 goto Label1; }
When using asm instructions that expect parameters like lit1
, lit4
, slit6
, slit6
, bit4
, etc. be sure to preceed them with the '#' (hash symbol) to ensure proper functioning.
Example :
BSET f, #5 ; set bit #5 in f register MOV #16000, Wnd ; move number #16000 to destination working register ADD Ws, #-5, Acc ; add number #-5 to accumulator
Asm code and SSA optimization
If asm code is mixed with the C code, keep in mind that the generated code can substantially differ when SSA optimization option is enabled or disabled.
This is due to the fact that SSA optimization uses certain working registers to store routine parameters (W10-W13), rather than storing them onto the function frame.
Because of this, user must be very careful when writing asm code as existing values in the working registers used by SSA optimization can be overwritten.
To avoid this, it is recommended that user includes desired asm code in a separate routine.
What do you think about this topic ? Send us feedback!