向量地址从程序存储器的中间开始
Vector address starts in the middle of program memory
我正在使用 MPLabX IDE 5.4 和 XC8 编译器(一个 C/MPASM 混合编译器,有一个名为 pic-as v.2.2 的驱动程序作为它的汇编器)到 compile/assemble a一段简单的汇编代码并输出一个列表文件。
我的整个汇编代码:
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
列表文件:
从 MPLab X IDE 的反汇编列表文件或通过 CLI 命令生成相同的结果:$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
第一列包含行号(即 1,2,3...19)。第二列和第三列分别列出了每条指令的内存(向量)地址(0x01FA-0x01FE)和操作码(3E08、29FE 等)。
问题:
- 指令不应该从0x0000-0x03FF(PIC16F84A的程序存储器地址)顺序存储。 0x0000 应该始终是程序的起始行或起点,我还明确指出
org 0
是程序起点。但是清单文件显示的指令占用了 0x01FA-0x01FF——就好像汇编程序从程序存储器的中间向上计数 (0x03FF / 2 = 0x01FF) 并从 0x01FA 开始。
- 什么是
0x0089
地址,为什么它在那里?
[编辑] 映射文件(如果重要的话)
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
Microchip 使使用最新版本的 MPLABX v5.40 开发 8 位汇编语言应用程序变得非常困难。
为了提供帮助,我制作了一个 PIC16F84A 示例项目,您可以找到 here。
这是 pic-as(v2.20) 源代码:
;
; 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
如果可以,请从我的 git 存储库中获取整个 MPLABX 项目的副本。关于在 MPLABX 中设置汇编语言项目,您需要了解一些内容,Microchip 尚未提供足够详细的文档。
我不是 Microchip 的员工,他们付不起足够的钱让我为他们做这件事。
我预计随着学校在秋季课程中开始教授 PIC 汇编语言,MPLABX 工具的问题会变得更加严重。我这个答案的目标是在更多学生因为蹩脚的工具的琐碎问题而感到沮丧和失败之前尝试提供帮助。
MPLabX IDE 无法为中端设备正确构建 pic-as 项目,因为缺少在位置 0x000 处设置重置向量的选项“-Wl,-presetVec=0h ”。
您可以从命令行构建项目:
pic-as -mcpu=16f1937 -Wl,-presetVec=0h -Wa,-a -Wl,-Map=test.map test.S
如XC8-PIC Assembler Guide for EE所述。
或者您可以尝试在项目选项中添加选项 -Wl,-presetVec=0h 到 pic-as compiler/linker,从 IDE 构建. MPLABX v5.40 compiler settings
顺便说一句,用于将中断向量放置在正确位置的选项也丢失了。
我正在使用 MPLabX IDE 5.4 和 XC8 编译器(一个 C/MPASM 混合编译器,有一个名为 pic-as v.2.2 的驱动程序作为它的汇编器)到 compile/assemble a一段简单的汇编代码并输出一个列表文件。
我的整个汇编代码:
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
列表文件:
从 MPLab X IDE 的反汇编列表文件或通过 CLI 命令生成相同的结果:$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
第一列包含行号(即 1,2,3...19)。第二列和第三列分别列出了每条指令的内存(向量)地址(0x01FA-0x01FE)和操作码(3E08、29FE 等)。
问题:
- 指令不应该从0x0000-0x03FF(PIC16F84A的程序存储器地址)顺序存储。 0x0000 应该始终是程序的起始行或起点,我还明确指出
org 0
是程序起点。但是清单文件显示的指令占用了 0x01FA-0x01FF——就好像汇编程序从程序存储器的中间向上计数 (0x03FF / 2 = 0x01FF) 并从 0x01FA 开始。 - 什么是
0x0089
地址,为什么它在那里?
[编辑] 映射文件(如果重要的话)
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
Microchip 使使用最新版本的 MPLABX v5.40 开发 8 位汇编语言应用程序变得非常困难。
为了提供帮助,我制作了一个 PIC16F84A 示例项目,您可以找到 here。
这是 pic-as(v2.20) 源代码:
;
; 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
如果可以,请从我的 git 存储库中获取整个 MPLABX 项目的副本。关于在 MPLABX 中设置汇编语言项目,您需要了解一些内容,Microchip 尚未提供足够详细的文档。
我不是 Microchip 的员工,他们付不起足够的钱让我为他们做这件事。
我预计随着学校在秋季课程中开始教授 PIC 汇编语言,MPLABX 工具的问题会变得更加严重。我这个答案的目标是在更多学生因为蹩脚的工具的琐碎问题而感到沮丧和失败之前尝试提供帮助。
MPLabX IDE 无法为中端设备正确构建 pic-as 项目,因为缺少在位置 0x000 处设置重置向量的选项“-Wl,-presetVec=0h ”。 您可以从命令行构建项目:
pic-as -mcpu=16f1937 -Wl,-presetVec=0h -Wa,-a -Wl,-Map=test.map test.S
如XC8-PIC Assembler Guide for EE所述。
或者您可以尝试在项目选项中添加选项 -Wl,-presetVec=0h 到 pic-as compiler/linker,从 IDE 构建. MPLABX v5.40 compiler settings
顺便说一句,用于将中断向量放置在正确位置的选项也丢失了。