Search code examples
assemblymicrocontrollerpicxc8lstlisting

Vector address starts in the middle of program memory


I'm using MPLabX IDE 5.4 with XC8 compiler (a C/MPASM hybrid compiler that has a driver named pic-as v.2.2 as its assembler) to compile/assemble a simple piece of assembly code and to output a listing file.

My entire assembly code:

PROCESSOR 16F84A
#include <xc.inc>
PSECT code
; a comment
            org     00
            addlw   01
            addlw   02
            addlw   03
            clrw
loop:       addlw   04
            goto    loop
            end     loop

Listing file:
Same result generated either from MPLab X IDE's Disassembly Listing File or through a CLI command: $pic-as -mcpu=16F84A -Wa,-a MyAssemblyFile.S -o MyFolder/MyOutputFileName):

 1                              processor   16F84A
 2                              pagewidth 132
 3                              psect   udata,global,class=RAM,space=1,delta=1,noexec
 4                              psect   udata_bank0,global,class=BANK0,space=1,delta=1,noexec
 5                              psect   code,global,class=CODE,delta=2
 6                              psect   data,global,class=STRCODE,delta=2,noexec
 7                              psect   edata,global,class=EEDATA,space=3,delta=2,noexec
 8  0089                     
 9                              psect   code
10  01FA                        org 0
11  01FA  3E01                  addlw   1
12  01FB  3E02                  addlw   2
13  01FC  3E03                  addlw   3
14  01FD  0103                  clrw
15  01FE                     loop:
16  01FE  3E04                  addlw   4
17  01FF  29FE                  goto    loop

The first column contains the line number (i.e. 1,2,3...19). The second and third column list out respectively the memory (vector) addresses (0x01FA-0x01FE) and the opcode (3E08, 29FE etc.) per instruction.

Questions:

  1. Shouldn't the instructions be stored sequentially from 0x0000-0x03FF (PIC16F84A's Program Memory addresses). 0x0000 should always be the starting line or origin of a program, and I've also explicitly stated org 0 as the program origin. But the listing file shows instructions occupying 0x01FA-0x01FF instead - as if the assembler counted upward from the middle of the program memory (0x03FF / 2 = 0x01FF) and started off from 0x01FA.
  2. What is 0x0089 address and why is it there?

[EDIT] Mapping File (if it matters)
                Name                               Link     Load   Length Selector   Space Scale
Output/temp.o   code                                1FA      1FA        6      3F4       0

TOTAL           Name                               Link     Load   Length     Space
        CLASS   CODE           
                code                                1FA      1FA        6         0

Solution

  • 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 get frustrated and fail because of trivial issues with lame tools.