1
\$\begingroup\$

I just started learning assembly coding in MPLabX IDE 5.4. Without connecting any hardware, simulator or debugger, I simply want to build an object code file and generate a listing file from an assembly file - just to check if the IDE works. But I kept getting obscure error messages even from building the simplest possible assembly lines.

As shown in figure [1 - 6], I should have the MPLabX IDE installed properly along with integration of XC8 (which seems to package with it the pic-as assembly compiler or another name for the MPASM assembler - after I struggled for hours asking and searching why a I need a C compiler for MPASM code until I realized they were bundled). I then tested building an assembly file with one single line of comment and one end instruction. The assembly was built successfully, but I can't find anywhere for the listing file (not one *.lst file was found searching through all directories).

As soon as I add any instruction before end, the building process failed as shown in Figure [7].

  1. Why is my assembly code not building?
  2. Why didn't my building process (failed or successful) generate the list file like everyone else

MPLabX-1 MPLabX-2

[EDIT]
Here is the assembly code file. The project was generated from step [1-6]. I just created a new assembly file (FooFile.asm) with three lines of instruction - org, clrw and end. enter image description here

\$\endgroup\$
8
  • \$\begingroup\$ What confuses me also is the term build should be associated with a compiler action of a high level language. Assembly code should be assembled into machine or object code. \$\endgroup\$
    – KMC
    Aug 19 '20 at 3:46
  • \$\begingroup\$ Please edit your question instead of posting additional information in the comments. -- To build is fine with assembly, too, as this is just another programming language. The executable is built, and if it were only because of the linking step. -- Did you look up the error message "no psect defined ..."? \$\endgroup\$ Aug 19 '20 at 7:31
  • \$\begingroup\$ @thebusybee, I tried looking in to Microchip - PSECT but I just can't understand anything there. I am not familiar with C nor am I programming in C either. It's confusing that I'm assembling assembly code and there are some C-like error messages popped up. \$\endgroup\$
    – KMC
    Aug 19 '20 at 8:13
  • \$\begingroup\$ The URL you link does not force you to program in C, and the error message has nothing to do with C. Actually it shows you an example how to program in assembler. If you want to solve your issue, you need to learn what this psect pseudo instruction means, and all its options. As it says: "But while coding in assembly, the user has to take care of variable allocation, using psects, etc. in RAM space." You don't need to bother if you were programming in C. \$\endgroup\$ Aug 19 '20 at 10:34
  • \$\begingroup\$ @thebusybee, thanks for the hint. I will go on and read XC8 Assembly User Guide and see if I can figure something out. \$\endgroup\$
    – KMC
    Aug 19 '20 at 11:00
8
\$\begingroup\$

Microchip has made it very to hard to develop 8-bit assembly language applications using the latest release of MPLABX v5.40.

To help I have crafted a PIC16F84A example project you can find here.

This is the pic-as(v2.20) source code:

    ;
    ; File:     main.S
    ; Target:   PIC16f84A
    ; Author:   dan1138
    ; Date:     2020-08-20
    ; Compiler: pic-as(v2.20)
    ; IDE:      MPLABX v5.40
    ;
    ; Description:
    ;
    ;   Example project for the PIC16F84A controller using the pic-as(v2.20) tool chain.
    ;
    ; Add this line in the project properties box, pic-as Global Options -> Additional options: 
    ;   -Wa,-a -Wl,-pPor_Vec=0h,-pIsr_Vec=4h
    ;
    ;                           PIC16F84A
    ;                   +----------:_:----------+
    ;             <>  1 : RA2               RA1 : 18 <> 
    ;             <>  2 : RA3               RA0 : 17 <> 
    ;             <>  3 : RA4/T0CKI        OSC1 : 16 <- 4MHz crystal
    ;    ICSP_VPP ->  4 : MCLR             OSC2 : 15 -> 4MHz crystal     
    ;         GND ->  5 : GND               VDD : 14 <- 5v0
    ;             <>  6 : RB0/INT       PGD/RB7 : 13 <> ICSP_PGD
    ;             <>  7 : RB1           PGC/RB6 : 12 <> ICSP_PGC
    ;             <>  8 : RB2               RB5 : 11 <> 
    ;             <>  9 : RB3               RB4 : 10 <> 
    ;                   +-----------------------:
    ;                            DIP-18

        PROCESSOR   16F84A
        PAGEWIDTH   132
        RADIX       DEC

    #include <xc.inc>

    ; PIC16F84A Configuration Bit Settings

     config FOSC = HS        ; Oscillator Selection bits (HS oscillator)
     config WDTE = OFF       ; Watchdog Timer (WDT disabled)
     config PWRTE = OFF      ; Power-up Timer Enable bit (Power-up Timer is disabled)
     config CP = OFF         ; Code Protection bit (Code protection disabled)

      skipnc  MACRO
        btfsc   STATUS,STATUS_C_POSITION
      ENDM

      skipnz  MACRO
        btfsc   STATUS,STATUS_Z_POSITION
      ENDM
    ;
    ; Power-On-Reset entry point
    ;
        PSECT   Por_Vec,global,class=CODE,delta=2
        global  resetVec
    resetVec:
        PAGESEL main                ;jump to the main routine
        goto    main

    ;
    ;   Data space use by interrupt handler to save context
        PSECT   Isr_Data,global,class=RAM,space=1,delta=1,noexec
    ;
        GLOBAL  WREG_save,STATUS_save
    ;
    WREG_save:      DS  1
    STATUS_save:    DS  1
    PCLATH_save:    DS  1
    ;
    ;   Interrupt vector and handler
        PSECT   Isr_Vec,global,class=CODE,delta=2
        GLOBAL  IsrVec
    ;
    IsrVec:
        movwf   WREG_save
        swapf   STATUS,W
        movwf   STATUS_save
        movf    PCLATH,W
        movwf   PCLATH_save
    ;
    IsrHandler:
    ;
    IsrExit:
        movf    PCLATH_save,W
        movwf   PCLATH
        swapf   STATUS_save,W
        movwf   STATUS
        swapf   WREG_save,F
        swapf   WREG_save,W
        retfie                      ; Return from interrupt
        

    ;objects in bank 0 memory
        PSECT   MainData,global,class=RAM,space=1,delta=1,noexec
    max:    DS      1               ;reserve 1 byte for max
    tmp:    DS      1               ;reserve 1 byte for tmp

    /* find the highest PORTB value read, storing this into the object max */
        PSECT   MainCode,global,class=CODE,delta=2
    main:
        BANKSEL TRISB               ;starting point
        movlw   0xFF
        movwf   BANKMASK(TRISB)     ;
        BANKSEL max
        clrf    BANKMASK(max)
    loop:
        BANKSEL PORTB               ;read and store port value
        movf    BANKMASK(PORTB),w
        BANKSEL tmp
        movwf   BANKMASK(tmp)
        subwf   max,w               ;is this value larger than max?
        skipnc
        goto    loop                ;no - read again
        movf    BANKMASK(tmp),w     ;yes - record this new high value
        movwf   BANKMASK(max)
        goto    loop                ;read again
        END     resetVec

If you can please get a copy of the entire MPLABX project from my git repository. There are some things you need to learn about setting up an assembly language project in MPLABX that Microchip has not document in enough detail yet.

I am not an employee if Microchip and they could not pay me enough to do this for them.

I expect issues with the MPLABX tools to become more of a problem as schools start teaching PIC assembly language in the fall sessions. My goal with this answer is to try to help before more students to not get frustrated and fail because of trivial issues with lame tools.

\$\endgroup\$
5
  • \$\begingroup\$ This is a crucial resource and I'm so happy that I found it. Thank you. There are some niceties that you can add to your assembly, but I'll raise those in Github. \$\endgroup\$
    – Reinderien
    Oct 20 '20 at 13:27
  • \$\begingroup\$ @Reinderien, I don't really know how to use Github very well. If you you would like to see some changes to my code you may need to add another comment to this thread. \$\endgroup\$
    – Dan1138
    Nov 2 '20 at 3:13
  • \$\begingroup\$ Re. PROCESSOR 16F84A - I'm surprised that it's necessary? This should be set on the project, and appropriate #defines applied by the build system. \$\endgroup\$
    – Reinderien
    Nov 2 '20 at 3:56
  • \$\begingroup\$ If you define a different linker class for near memory and apply it to MainData, then you will not need your PAGESEL directive. \$\endgroup\$
    – Reinderien
    Nov 2 '20 at 4:05
  • \$\begingroup\$ @Reinderien, My style when creating assembly language code is to make an implementation that works correctly for the largest address spaces supported by the "largest" controller available in that family. This allows up-scaling the controller when code or data space gets tight. Optimizing the code too soon in the development cycle is a trap that the new kids are always falling into. Best practice is to write clear simple code and use the target specific optimizations only when required. \$\endgroup\$
    – Dan1138
    Nov 5 '20 at 22:43
3
\$\begingroup\$

The documentations Microchip has for MPLab X and XC8 are probably some of the worst I've ever read. I had to mesh what I've read from multiple sources, and with some guessing just to get the assembler working in MPLab X IDE 5.4. So here is the assembly code that gets to assemble with no error or warning messages.

PROCESSOR 16F84A
#include <xc.inc>
PSECT   code
        org     00
loop:   clrw
        end     loop

Tutorials and books I've read all uses MPASM assembler instead of it's current replacement, pic-as in XC8. With MPASM and older MPLab, pure assembly code would just get built. But with current XC8 and pic-as, you have to start off with including /Applications/microchip/xc8/v2.20/pic/include/xc.inc where it has a directive pointing to /Applications/microchip/xc8/v2.20/pic/include/pic.inc which in turns has a directive pointing to /Applications/microchip/xc8/v2.20/pic/include/ic_as_chip_select.inc that eventually points to /Applications/microchip/xc8/v2.20/pic/include/proc/pic16f84a.inc that defines the PSECT:

psect udata,class=RAM,space=SPACE_DATA,noexec
psect udata_bank0,class=BANK0,space=SPACE_DATA,noexec
psect code,class=CODE,space=SPACE_CODE,delta=2
psect data,class=STRCODE,space=SPACE_CODE,delta=2,noexec
psect edata,class=EEDATA,space=SPACE_EEPROM,delta=2,noexec

For whatever obscure reason, there has to be psect wrapping around the assembly code. The explanation is given as this (I've no idea what it's talking about or why I need to wrap an assembly code like I bracket-wrap a C function call):

Psects—short for program sections—are containers that group and hold related parts of the program, even though the source code for these parts might not be physically adjacent in the source file, or may even be spread over several modules. They are the smallest entities positioned by the linker into memory.

As for the listing file: instruction to read or output the listing file is somewhat mentioned in MPLAB® X IDE User’s Guide's (Section 5.16 on page 127): Window>Debugging>Output>DisassemblyListingFile. Alternatively, the listing file can be outputted to /MyProject/disassembly/listing.disasm (not in the *.lst format as Microchip forum or their guide suggests!) by inserting -code=0h -Wa,-a in ProjectProperties/pic-asLinker/CustomLinkerOptions (there is no mention or instruction in any of their user guide and I just happen to guess right where to insert what from reading MPLAB® XC8 PIC Assembler User's Guide for Embedded Engineers) where it provides examples compiling under the XC8 command line. Neither listing files generated under the IDE provides all details - it doesn't even show the vector addresses of instructions!

Disassembly Listing for FooProject
Generated From:
/Users/*******/Desktop/Foo/dist/default/production/Foo.production.elf


---  /Users/*******/Desktop/Foo/FooFile.asm  ------------------------------------------------------------
                                                  1:     PROCESSOR 16F84A
                                                  2:     #include <xc.inc>
                                                  3:     PSECT code
                                                  4:         ; a commend
                                                  5:        org     00
01FF  0103     CLRW                               6:     loop:  clrw
                                                  7:        end     loop
 

I won't accept my own answer. If someone can help address my finding or explain why psect is there and how to get the listing file to show vector addresses I'll accept his/her answer.

[EDIT] To output listing file on MPLabX 5.4 or with X8 (pis-as) CLI using -Wa,-a option.

// Source file must end with *.S extension for compiler to preprocess the C preprocessor $sudo pic-as -mcpu=16F84A -Wa,-a SourceFileName.S -o OutputFolderName/OutputFileName

enter image description here

\$\endgroup\$
3
  • 1
    \$\begingroup\$ If you ever leave the hobby level and enter professional development processes, you will need these sections. Your project will have multiple modules and libraries, built from multiple modules as well. All the modules can have instructions or read-only data or read-write data or variable space or any combination of them. The final software needs all these parts sorted in their respective sections. QED! An assembler without section capabilities is just a toy. \$\endgroup\$ Aug 21 '20 at 7:27
  • 3
    \$\begingroup\$ @thebusybee Microchip became popular by having 'hobbyist friendly' MCUs - then they shoved that Java turd on us and it's been downhill ever since. Today the market for 'toys' such as Arduino, Raspberry Pi and ESP is enormous, but hobbyists and semi-professionals are shying away from Microchip because their development tools suck. Most of the interesting PICs are low-end 8 bit devices that need assembly code to have competitive performance. By making asm code harder to get into, Microchip are effectively saying 'don't buy our product'. \$\endgroup\$ Aug 21 '20 at 19:54
  • 1
    \$\begingroup\$ I've always wished to know how things work at the low level after years of programming in HLL like .NET. With the time I have I wanted to dive straight down and learn some bare metal basic to get a feel of it. I started out with CircuitBread Tutorial just to blink some LEDs with assembly code - didn't work. Can't compile nothing. The initial attempt of playing out a hello world type of project ended up having to read books and documentations on the compiler. It's frustrating. \$\endgroup\$
    – KMC
    Aug 22 '20 at 0:25
1
\$\begingroup\$

KMC,

You could have downloaded a legacy version MPLAB IDE v8.92. Works like a charm. I only used this old IDE for programming my PIC's. I tried MPLAB X 5.50 as you did and ran into the same obstacles. The old IDE works better than the new stuff that entirely focused is on C.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.