MPLAB X IDE PIC 汇编程序在包含标签的行上抛出语法错误
MPLAB X IDE PIC assembly program throwing syntax error on lines containing labels
我在包含“3 COMF PORTB,F”“D1 MOVLW 0xaf”(包含标签的行)的行中收到语法错误错误。
此外,任何人都知道如何设置配置位并正确编写 pic 微控制器的汇编代码,请纠正并指出正确的资源。
请在回答之前阅读此内容,因为我使用的是最新的 MPLABX IDE 没有像旧版本那样名为 MPASM 的程序或工具链。
于是在网上搜索了一下,发现我们也可以用XC8来编译汇编代码。
但是当我添加使用 MPLABX 生成的配置位代码时 IDE 构建过程再次抛出错误,我只创建了一个 main。
ASM 文件并在其中添加了生成的配置代码。
所以现在我删除了整个配置代码,只写了裸汇编代码来模拟,现在出现语法错误。
一头雾水,一头雾水,真的很烦恼。
我已经了解嵌入式 C 编程,但喜欢学习汇编以了解 PIC 的底层细节。
需要帮助。
#include <pic18f45k80.inc>
R1 EQU 0X07
R2 EQU 0X08
R3 EQU 0X09
ORG 0
CLRF TRISB
MOVLW 0X55
MOVWF PORTB
L3 COMF PORTB,F
CALL QDELAY
BRA L3
QDELAY
MOVLW 0x05
MOVWF R1
D1 MOVLW 0xaf
MOVWF R2
D2 MOVLW 0xaf
MOVWF R3
D3 NOP
NOP
DECF R3, F
BNZ D3
DECF R2, F
BNZ D2
DECF R1, F
BNZ D1
RETURN
END
这是构建完成时遇到的错误。
main.asm:6:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:8:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:9:: error: (876) syntax error
main.asm:13:: error: (876) syntax error
main.asm:15:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:16:: error: (876) syntax error
main.asm:17:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:18:: error: (876) syntax error
main.asm:19:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:20:: error: (876) syntax error
main.asm:22:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:24:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:26:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:10:: error: (800) undefined symbol "QDELAY"
main.asm:11:: error: (1223) relative branch/call offset out of range
(908) exit status = 1
最新的 MPLABX 5.4 不再支持 MPASM。所以你必须使用 xc8 提供的汇编器。有几个不同之处,所以看看 here.
例如
- 配置位应使用
config
指令 定义
标签必须用 :
定义
PSECT
定义数据内存
- 等等...
您可能会受益于从 MPASM 到 pic-as(v2.20) 的端口的实际示例
这是我开始时使用的 MPASM 文件:
; File: main.asm
; Target: PIC18F2550
; Author: dan1138
; Date: 2020-06-17
; Compiler: MPASM v5.84
; IDE: MPLABX v5.25
;
; Description:
;
; Find integer square root of a 32-bit value
;
;
;
;
; PIC18F2550
; +------------:_:------------+
; VPP -> 1 : RE3/MCLRn/VPP PGD/RB7 : 28 <> PGD
; -> 2 : RA0/AN0 PGC/RB6 : 27 <> PGC
; <> 3 : RA1/AN1 PGM/RB5 : 26 <>
; <> 4 : RA2/AN2 AN11/RB4 : 25 <>
; <> 5 : RA3/AN3 AN9/RB3 : 24 <>
; <> 6 : RA4/C1OUT AN8/RB2 : 23 <>
; <> 7 : RA5/AN4 AN10/RB1 : 22 <>
; GND <> 8 : VSS AN12/RB0 : 21 <>
; 20MHz <> 9 : RA7/OSC1 VDD : 20 <- 5v0
; 20MHz <> 10 : RA6/OSC2 VSS : 19 <- GND
; 32.768KHz <> 11 : RC0/SOSCO RX/DT/RC7 : 18 <>
; 32.768KHz <> 12 : RC1/SOSCI TX/CK/RC6 : 17 <>
; <> 13 : RC2/CCP1 D+/RC5 : 16 <-
; <> 14 : VUSB D-/RC4 : 15 <-
; +---------------------------:
; DIP-28
; Note:
; RC4,RC5 can only be used as digital inputs when the USB transceiver is not used.
;
list p=18F2550
list c=132
list r=dec
;
config PLLDIV = 5 ; PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input))
config CPUDIV = OSC1_PLL2 ; System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
config USBDIV = 2 ; USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes from the 96 MHz PLL divided by 2)
config FOSC = HSPLL_HS ; Oscillator Selection bits (HS oscillator, PLL enabled (HSPLL))
config FCMEN = OFF ; Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
config IESO = OFF ; Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
config PWRT = OFF ; Power-up Timer Enable bit (PWRT disabled)
config BOR = OFF ; Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
config BORV = 3 ; Brown-out Reset Voltage bits (Minimum setting 2.05V)
config VREGEN = OFF ; USB Voltage Regulator Enable bit (USB voltage regulator disabled)
config WDT = OFF ; Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
config WDTPS = 32768 ; Watchdog Timer Postscale Select bits (1:32768)
config CCP2MX = ON ; CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
config PBADEN = OFF ; PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
config LPT1OSC = OFF ; Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
config MCLRE = ON ; MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
config STVREN = ON ; Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
config LVP = OFF ; Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
config XINST = OFF ; Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
config CP0 = OFF ; Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
config CP1 = OFF ; Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
config CP2 = OFF ; Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
config CP3 = OFF ; Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)
config CPB = OFF ; Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
config CPD = OFF ; Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
config WRT0 = OFF ; Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
config WRT1 = OFF ; Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
config WRT2 = OFF ; Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
config WRT3 = OFF ; Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)
config WRTC = OFF ; Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
config WRTB = OFF ; Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
config WRTD = OFF ; Data EEPROM Write Protection bit (Data EEPROM is not write-protected)
config EBTR0 = OFF ; Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
config EBTR1 = OFF ; Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
config EBTR2 = OFF ; Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
config EBTR3 = OFF ; Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
config EBTRB = OFF ; Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)
;
; Specify the System clock frequency in Hz
;
#define FOSC 48000000
;
; Specify the Peripheral clock frequency in Hz
;
#define FCYC (FOSC/4)
;
; Include device specific definitions for Special Function Registers
;
#include <p18F2550.inc>
;
;
;
;
;
resetVec code 0x0000 ; processor reset vector
;
resetVec:
clrf TBLPTRU, ACCESS
goto Start
;
hi_int_vec code 0x0008
;
goto HighIsrHandler
;
LowIsr_data udata_acs
;
global WREG_save,STATUS_save,BSR_save
;
WREG_save: res 1
STATUS_save: res 1
BSR_save: res 1
;
lo_int_vec code 0x0018
;
LowIsrVec:
movff WREG,WREG_save
movff STATUS,STATUS_save
movff BSR,BSR_save
;
LowIsrHandler:
;
movff BSR_save,BSR
movff STATUS_save,STATUS
movff WREG_save,WREG
retfie
;
HighIsr_code code
;
HighIsrHandler:
return FAST
;
start_code code
;
Start:
bcf INTCON,GIEH ; Disable all interrupts
bcf INTCON,GIEL
bsf RCON,IPEN ; Enable interrupt priority
;
movlw 0x00 ; Set primary oscillator as system clock source
movwf OSCCON,ACCESS ;
;
movlw 0x0F ; Configure A/D
movwf ADCON1 ; for digital inputs
;
goto main
;
; Implement integer square root
;
; unsigned long in;
; unsigned long out;
; unsigned long bit;
; unsigned long temp;
;
; unsigned long isqrt(void)
; {
; out = 0;
; bit = 1L << 30;
;
; // "bit" starts at the highest power of four <= the argument.
; while (bit > in)
; bit >>= 2;
;
; while (bit != 0)
; {
; temp = out + bit;
; out >>= 1;
; if (in >= temp)
; {
; in -= temp;
; out += bit;
; }
; bit >>= 2;
; }
; return out;
; }
;
;
isqrt_data udata
global isqrt_in,isqrt_out,isqrt_bit,isqrt_temp
;
isqrt_in: res 4
isqrt_out: res 4
isqrt_bit: res 4
isqrt_temp: res 4
;
isqrt_code code
;
;
; logical shift right one bit [fsr1]
;
isqrt_lsr:
bcf STATUS,C
rrcf POSTDEC1,F
rrcf POSTDEC1,F
rrcf POSTDEC1,F
rrcf INDF1,f
return
;
; Compare [FSR2] - [FSR1]
; Carry set when [FSR2] >= [FSR1]
; Carry clear when [FSR2] < [FSR1]
;
isqrt_cmp:
movf POSTINC1,w
subwf POSTINC2,w
movf POSTINC1,w
subwfb POSTINC2,w
movf POSTINC1,w
subwfb POSTINC2,w
movf INDF1,w
subwfb INDF2,w
return
;
isqrt:
clrf isqrt_out
clrf isqrt_out+1
clrf isqrt_out+2
clrf isqrt_out+3
;
clrf isqrt_bit
clrf isqrt_bit+1
clrf isqrt_bit+2
movlw B'01000000'
movwf isqrt_bit+3
;
FindMSB:
lfsr FSR1,isqrt_bit
lfsr FSR2,isqrt_in
rcall isqrt_cmp ; STATUS set to (isqrt_in - isqrt_bit)
bc FindNextDigit ; branch when isqrt_in >= isqrt_bit
;
; Shift the digits right two bits
;
lfsr FSR1,isqrt_bit+3
rcall isqrt_lsr
lfsr FSR1,isqrt_bit+3
rcall isqrt_lsr
bra FindMSB
;
FindNextDigit:
movf isqrt_bit,W
iorwf isqrt_bit+1,W
iorwf isqrt_bit+2,W
iorwf isqrt_bit+3,W
bz isqrt_done
;
movf isqrt_bit,W
addwf isqrt_out,W
movwf isqrt_temp
movf isqrt_bit+1,W
addwfc isqrt_out+1,W
movwf isqrt_temp+1
movf isqrt_bit+2,W
addwfc isqrt_out+2,W
movwf isqrt_temp+2
movf isqrt_bit+3,W
addwfc isqrt_out+3,W
movwf isqrt_temp+3
;
lfsr FSR1,isqrt_out+3
rcall isqrt_lsr
;
lfsr FSR1,isqrt_temp
lfsr FSR2,isqrt_in
rcall isqrt_cmp ; STATUS set to (isqrt_in - isqrt_temp)
bnc NoDigitUpdate ; Branch when isqrt_in >= isqrt_temp
;
movf isqrt_temp,W
subwf isqrt_in
movf isqrt_temp+1,W
subwfb isqrt_in+1
movf isqrt_temp+2,W
subwfb isqrt_in+2
movf isqrt_temp+3,W
subwfb isqrt_in+3
;
movf isqrt_bit,W
addwf isqrt_out
movf isqrt_bit+1,W
addwfc isqrt_out+1
movf isqrt_bit+2,W
addwfc isqrt_out+2
movf isqrt_bit+3,W
addwfc isqrt_out+3
;
NoDigitUpdate:
;
lfsr FSR1,isqrt_bit+3
rcall isqrt_lsr
lfsr FSR1,isqrt_bit+3
rcall isqrt_lsr
bra FindNextDigit
;
isqrt_done:
return
;
main_code code
;
;
; Constants
#define TEST_VALUE1 2*2
#define TEST_VALUE2 3*3
#define TEST_VALUE3 4*4
#define TEST_VALUE4 5*5
#define TEST_VALUE5 6*6
#define TEST_VALUE6 10*10
#define TEST_VALUE7 9999*9999
#define TEST_VALUE8 12345*12345
#define TEST_VALUE9 65535*65535
;
; Macro to load a 32-bit constant
;
load32 macro DWORD, CONST
;
banksel DWORD
movlw 0xFF & (CONST)
movwf DWORD
movlw 0xFF & (CONST >> 8)
movwf DWORD+1
movlw 0xFF & (CONST >> 16)
movwf DWORD+2
movlw 0xFF & (CONST >> 24)
movwf DWORD+3
;
endm
;
main:
;
AppLoop:
load32 isqrt_in,TEST_VALUE1
call isqrt
load32 isqrt_in,TEST_VALUE2
call isqrt
load32 isqrt_in,TEST_VALUE3
call isqrt
load32 isqrt_in,TEST_VALUE4
call isqrt
load32 isqrt_in,TEST_VALUE5
call isqrt
load32 isqrt_in,TEST_VALUE6
call isqrt
load32 isqrt_in,TEST_VALUE7
call isqrt
load32 isqrt_in,TEST_VALUE8
call isqrt
load32 isqrt_in,TEST_VALUE9
call isqrt
goto AppLoop
;
END
这是移植到使用 pic-as(v2.20) 工具链构建的代码:
; File: main.S
; Target: PIC18F2550
; Author: dan1138
; Date: 2020-06-17
; Compiler: pic-as(v2.20)
; IDE: MPLABX v5.40
;
; Description:
;
; Find integer square root of a 32-bit value
;
; Add to the MPLABX project Additional options:
; -Wa,-a -Wl,-presetVec=0h,-phi_int_vec=08h,-plo_int_vec=18h
;
; PIC18F2550
; +------------:_:------------+
; VPP -> 1 : RE3/MCLRn/VPP PGD/RB7 : 28 <> PGD
; -> 2 : RA0/AN0 PGC/RB6 : 27 <> PGC
; <> 3 : RA1/AN1 PGM/RB5 : 26 <>
; <> 4 : RA2/AN2 AN11/RB4 : 25 <>
; <> 5 : RA3/AN3 AN9/RB3 : 24 <>
; <> 6 : RA4/C1OUT AN8/RB2 : 23 <>
; <> 7 : RA5/AN4 AN10/RB1 : 22 <>
; GND <> 8 : VSS AN12/RB0 : 21 <>
; 20MHz <> 9 : RA7/OSC1 VDD : 20 <- 5v0
; 20MHz <> 10 : RA6/OSC2 VSS : 19 <- GND
; 32.768KHz <> 11 : RC0/SOSCO RX/DT/RC7 : 18 <>
; 32.768KHz <> 12 : RC1/SOSCI TX/CK/RC6 : 17 <>
; <> 13 : RC2/CCP1 D+/RC5 : 16 <-
; <> 14 : VUSB D-/RC4 : 15 <-
; +---------------------------:
; DIP-28
; Note:
; RC4,RC5 can only be used as digital inputs when the USB transceiver is not used.
;
processor 18F2550
pagewidth 132
radix dec
;
config PLLDIV = 5 ; PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input))
config CPUDIV = OSC1_PLL2 ; System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
config USBDIV = 2 ; USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes from the 96 MHz PLL divided by 2)
config FOSC = HSPLL_HS ; Oscillator Selection bits (HS oscillator, PLL enabled (HSPLL))
config FCMEN = OFF ; Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
config IESO = OFF ; Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
config PWRT = OFF ; Power-up Timer Enable bit (PWRT disabled)
config BOR = OFF ; Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
config BORV = 3 ; Brown-out Reset Voltage bits (Minimum setting 2.05V)
config VREGEN = OFF ; USB Voltage Regulator Enable bit (USB voltage regulator disabled)
config WDT = OFF ; Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
config WDTPS = 32768 ; Watchdog Timer Postscale Select bits (1:32768)
config CCP2MX = ON ; CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
config PBADEN = OFF ; PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
config LPT1OSC = OFF ; Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
config MCLRE = ON ; MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
config STVREN = ON ; Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
config LVP = OFF ; Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
config XINST = OFF ; Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
config CP0 = OFF ; Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
config CP1 = OFF ; Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
config CP2 = OFF ; Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
config CP3 = OFF ; Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)
config CPB = OFF ; Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
config CPD = OFF ; Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
config WRT0 = OFF ; Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
config WRT1 = OFF ; Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
config WRT2 = OFF ; Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
config WRT3 = OFF ; Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)
config WRTC = OFF ; Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
config WRTB = OFF ; Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
config WRTD = OFF ; Data EEPROM Write Protection bit (Data EEPROM is not write-protected)
config EBTR0 = OFF ; Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
config EBTR1 = OFF ; Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
config EBTR2 = OFF ; Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
config EBTR3 = OFF ; Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
config EBTRB = OFF ; Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)
;
; Specify the System clock frequency in Hz
;
#define FOSC 48000000
;
; Specify the Peripheral clock frequency in Hz
;
#define FCYC (FOSC/4)
;
; Include device specific definitions for Special Function Registers
;
#include <xc.inc>
;
; Preprocessor macro to help with LFSR opcode
;
#define FSR(x) (x)
;
psect resetVec,global,reloc=2,class=CODE,delta=1
;
resetVec:
clrf TBLPTRU,c
goto Start
;
psect hi_int_vec,global,reloc=2,class=CODE,delta=1
;
goto HighIsrHandler
;
psect LowIsr_data,global,class=COMRAM,space=1,delta=1,lowdata,noexec
;
global WREG_save,STATUS_save,BSR_save
;
WREG_save: ds 1
STATUS_save: ds 1
BSR_save: ds 1
;
psect lo_int_vec,global,reloc=2,class=CODE,delta=1
;
LowIsrVec:
movff WREG,WREG_save
movff STATUS,STATUS_save
movff BSR,BSR_save
;
LowIsrHandler:
;
movff BSR_save,BSR
movff STATUS_save,STATUS
movff WREG_save,WREG
retfie 0
;
psect HighIsr_code,global,reloc=2,class=CODE,delta=1
;
HighIsrHandler:
return 1
;
psect start_code,global,reloc=2,class=CODE,delta=1
;
Start:
bcf INTCON,INTCON_GIEH_POSITION,0 ; Disable all interrupts
bcf INTCON,INTCON_GIEL_POSITION,0
bsf RCON,RCON_IPEN_POSITION,0 ; Enable interrupt priority
;
movlw 0x00 ; Set primary oscillator as system clock source
movwf OSCCON,c ;
;
movlw 0x0F ; Configure A/D
movwf ADCON1,c ; for digital inputs
;
goto main
;
; Implement integer square root
;
; unsigned long in;
; unsigned long out;
; unsigned long bit;
; unsigned long temp;
;
; unsigned long isqrt(void)
; {
; out = 0;
; bit = 1L << 30;
;
; // "bit" starts at the highest power of four <= the argument.
; while (bit > in)
; bit >>= 2;
;
; while (bit != 0)
; {
; temp = out + bit;
; out >>= 1;
; if (in >= temp)
; {
; in -= temp;
; out += bit;
; }
; bit >>= 2;
; }
; return out;
; }
;
;
psect isqrt_data,global,class=RAM,space=1,delta=1,noexec
global isqrt_in,isqrt_out,isqrt_bit,isqrt_temp
;
isqrt_in: ds 4
isqrt_out: ds 4
isqrt_bit: ds 4
isqrt_temp: ds 4
;
psect isqrt_code,global,reloc=2,class=CODE,delta=1
;
;
; 32-bit logical shift right one bit [fsr1]
;
isqrt_lsr:
bcf STATUS,STATUS_C_POSITION,0
rrcf POSTDEC1,1,0
rrcf POSTDEC1,1,0
rrcf POSTDEC1,1,0
rrcf INDF1,1,0
return
;
; Compare [FSR2] - [FSR1]
; Carry set when [FSR2] >= [FSR1]
; Carry clear when [FSR2] < [FSR1]
;
isqrt_cmp:
movf POSTINC1,w,c
subwf POSTINC2,w,c
movf POSTINC1,w,c
subwfb POSTINC2,w,c
movf POSTINC1,w,c
subwfb POSTINC2,w,c
movf INDF1,w,c
subwfb INDF2,w,c
return
;
isqrt:
clrf BANKMASK(isqrt_out),b
clrf BANKMASK(isqrt_out)+1,b
clrf BANKMASK(isqrt_out)+2,b
clrf BANKMASK(isqrt_out)+3,b
;
clrf BANKMASK(isqrt_bit),b
clrf BANKMASK(isqrt_bit)+1,b
clrf BANKMASK(isqrt_bit)+2,b
movlw 0b01000000
movwf BANKMASK(isqrt_bit)+3,b
;
FindMSB:
lfsr FSR(1),isqrt_bit
lfsr FSR(2),isqrt_in
rcall isqrt_cmp ; STATUS set to (isqrt_in - isqrt_bit)
bc FindNextDigit ; branch when isqrt_in >= isqrt_bit
;
; Shift the digits right two bits
;
lfsr FSR(1),isqrt_bit+3
rcall isqrt_lsr
lfsr FSR(1),isqrt_bit+3
rcall isqrt_lsr
bra FindMSB
;
FindNextDigit:
movf BANKMASK(isqrt_bit),W,b
iorwf BANKMASK(isqrt_bit)+1,W,b
iorwf BANKMASK(isqrt_bit)+2,W,b
iorwf BANKMASK(isqrt_bit)+3,W,b
bz isqrt_done
;
movf BANKMASK(isqrt_bit),W,b
addwf BANKMASK(isqrt_out),W,b
movwf BANKMASK(isqrt_temp),b
movf BANKMASK(isqrt_bit)+1,W,b
addwfc BANKMASK(isqrt_out)+1,W,b
movwf BANKMASK(isqrt_temp)+1,b
movf BANKMASK(isqrt_bit)+2,W,b
addwfc BANKMASK(isqrt_out)+2,W,b
movwf BANKMASK(isqrt_temp)+2,b
movf BANKMASK(isqrt_bit)+3,W,b
addwfc BANKMASK(isqrt_out)+3,W,b
movwf BANKMASK(isqrt_temp)+3,b
;
lfsr FSR(1),isqrt_out+3
rcall isqrt_lsr
;
lfsr FSR(1),isqrt_temp
lfsr FSR(2),isqrt_in
rcall isqrt_cmp ; STATUS set to (isqrt_in - isqrt_temp)
bnc NoDigitUpdate ; Branch when isqrt_in >= isqrt_temp
;
movf BANKMASK(isqrt_temp),W,b
subwf BANKMASK(isqrt_in),b
movf BANKMASK(isqrt_temp)+1,W,b
subwfb BANKMASK(isqrt_in)+1,b
movf BANKMASK(isqrt_temp)+2,W,b
subwfb BANKMASK(isqrt_in)+2,b
movf BANKMASK(isqrt_temp)+3,W,b
subwfb BANKMASK(isqrt_in)+3,b
;
movf BANKMASK(isqrt_bit),W,b
addwf BANKMASK(isqrt_out),b
movf BANKMASK(isqrt_bit)+1,W,b
addwfc BANKMASK(isqrt_out)+1,b
movf BANKMASK(isqrt_bit)+2,W,b
addwfc BANKMASK(isqrt_out)+2,b
movf BANKMASK(isqrt_bit)+3,W,b
addwfc BANKMASK(isqrt_out)+3,b
;
NoDigitUpdate:
;
lfsr FSR(1),isqrt_bit+3
rcall isqrt_lsr
lfsr FSR(1),isqrt_bit+3
rcall isqrt_lsr
bra FindNextDigit
;
isqrt_done:
return
;
psect main_code,global,reloc=2,class=CODE,delta=1
;
;
; Constants
#define TEST_VALUE1 2*2
#define TEST_VALUE2 3*3
#define TEST_VALUE3 4*4
#define TEST_VALUE4 5*5
#define TEST_VALUE5 6*6
#define TEST_VALUE6 10*10
#define TEST_VALUE7 9999*9999
#define TEST_VALUE8 12345*12345
#define TEST_VALUE9 65535*65535
;
; Macro to load a 32-bit constant
;
load32 macro DWORD,CONST
;
banksel DWORD
movlw 255 and (CONST)
movwf BANKMASK(DWORD),b
movlw 255 and (CONST >> 8)
movwf BANKMASK(DWORD)+1,b
movlw 255 and (CONST >> 16)
movwf BANKMASK(DWORD)+2,b
movlw 255 and (CONST >> 24)
movwf BANKMASK(DWORD)+3,b
;
endm
;
main:
;
AppLoop:
load32 isqrt_in,TEST_VALUE1
call isqrt
load32 isqrt_in,TEST_VALUE2
call isqrt
load32 isqrt_in,TEST_VALUE3
call isqrt
load32 isqrt_in,TEST_VALUE4
call isqrt
load32 isqrt_in,TEST_VALUE5
call isqrt
load32 isqrt_in,TEST_VALUE6
call isqrt
load32 isqrt_in,TEST_VALUE7
call isqrt
load32 isqrt_in,TEST_VALUE8
call isqrt
load32 isqrt_in,TEST_VALUE9
call isqrt
goto AppLoop
;
END resetVec
使用 kdiff 等源文件差异工具查看需要更改的内容。
我非常努力地进行最小的更改,以便从两个汇编程序中获得相同的 HEX 文件输出。
有关完整的 MPLABX v5.40 项目,请参阅此 git repository。
我在包含“3 COMF PORTB,F”“D1 MOVLW 0xaf”(包含标签的行)的行中收到语法错误错误。
此外,任何人都知道如何设置配置位并正确编写 pic 微控制器的汇编代码,请纠正并指出正确的资源。
请在回答之前阅读此内容,因为我使用的是最新的 MPLABX IDE 没有像旧版本那样名为 MPASM 的程序或工具链。
于是在网上搜索了一下,发现我们也可以用XC8来编译汇编代码。
但是当我添加使用 MPLABX 生成的配置位代码时 IDE 构建过程再次抛出错误,我只创建了一个 main。
ASM 文件并在其中添加了生成的配置代码。
所以现在我删除了整个配置代码,只写了裸汇编代码来模拟,现在出现语法错误。
一头雾水,一头雾水,真的很烦恼。
我已经了解嵌入式 C 编程,但喜欢学习汇编以了解 PIC 的底层细节。
需要帮助。
#include <pic18f45k80.inc>
R1 EQU 0X07
R2 EQU 0X08
R3 EQU 0X09
ORG 0
CLRF TRISB
MOVLW 0X55
MOVWF PORTB
L3 COMF PORTB,F
CALL QDELAY
BRA L3
QDELAY
MOVLW 0x05
MOVWF R1
D1 MOVLW 0xaf
MOVWF R2
D2 MOVLW 0xaf
MOVWF R3
D3 NOP
NOP
DECF R3, F
BNZ D3
DECF R2, F
BNZ D2
DECF R1, F
BNZ D1
RETURN
END
这是构建完成时遇到的错误。
main.asm:6:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:8:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:9:: error: (876) syntax error
main.asm:13:: error: (876) syntax error
main.asm:15:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:16:: error: (876) syntax error
main.asm:17:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:18:: error: (876) syntax error
main.asm:19:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:20:: error: (876) syntax error
main.asm:22:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:24:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:26:: warning: (1522) RAM access bit operand not specified, assuming access-bank
main.asm:10:: error: (800) undefined symbol "QDELAY"
main.asm:11:: error: (1223) relative branch/call offset out of range
(908) exit status = 1
最新的 MPLABX 5.4 不再支持 MPASM。所以你必须使用 xc8 提供的汇编器。有几个不同之处,所以看看 here.
例如
- 配置位应使用
config
指令 定义
标签必须用
:
定义
PSECT
定义数据内存- 等等...
您可能会受益于从 MPASM 到 pic-as(v2.20) 的端口的实际示例
这是我开始时使用的 MPASM 文件:
; File: main.asm
; Target: PIC18F2550
; Author: dan1138
; Date: 2020-06-17
; Compiler: MPASM v5.84
; IDE: MPLABX v5.25
;
; Description:
;
; Find integer square root of a 32-bit value
;
;
;
;
; PIC18F2550
; +------------:_:------------+
; VPP -> 1 : RE3/MCLRn/VPP PGD/RB7 : 28 <> PGD
; -> 2 : RA0/AN0 PGC/RB6 : 27 <> PGC
; <> 3 : RA1/AN1 PGM/RB5 : 26 <>
; <> 4 : RA2/AN2 AN11/RB4 : 25 <>
; <> 5 : RA3/AN3 AN9/RB3 : 24 <>
; <> 6 : RA4/C1OUT AN8/RB2 : 23 <>
; <> 7 : RA5/AN4 AN10/RB1 : 22 <>
; GND <> 8 : VSS AN12/RB0 : 21 <>
; 20MHz <> 9 : RA7/OSC1 VDD : 20 <- 5v0
; 20MHz <> 10 : RA6/OSC2 VSS : 19 <- GND
; 32.768KHz <> 11 : RC0/SOSCO RX/DT/RC7 : 18 <>
; 32.768KHz <> 12 : RC1/SOSCI TX/CK/RC6 : 17 <>
; <> 13 : RC2/CCP1 D+/RC5 : 16 <-
; <> 14 : VUSB D-/RC4 : 15 <-
; +---------------------------:
; DIP-28
; Note:
; RC4,RC5 can only be used as digital inputs when the USB transceiver is not used.
;
list p=18F2550
list c=132
list r=dec
;
config PLLDIV = 5 ; PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input))
config CPUDIV = OSC1_PLL2 ; System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
config USBDIV = 2 ; USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes from the 96 MHz PLL divided by 2)
config FOSC = HSPLL_HS ; Oscillator Selection bits (HS oscillator, PLL enabled (HSPLL))
config FCMEN = OFF ; Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
config IESO = OFF ; Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
config PWRT = OFF ; Power-up Timer Enable bit (PWRT disabled)
config BOR = OFF ; Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
config BORV = 3 ; Brown-out Reset Voltage bits (Minimum setting 2.05V)
config VREGEN = OFF ; USB Voltage Regulator Enable bit (USB voltage regulator disabled)
config WDT = OFF ; Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
config WDTPS = 32768 ; Watchdog Timer Postscale Select bits (1:32768)
config CCP2MX = ON ; CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
config PBADEN = OFF ; PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
config LPT1OSC = OFF ; Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
config MCLRE = ON ; MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
config STVREN = ON ; Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
config LVP = OFF ; Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
config XINST = OFF ; Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
config CP0 = OFF ; Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
config CP1 = OFF ; Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
config CP2 = OFF ; Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
config CP3 = OFF ; Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)
config CPB = OFF ; Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
config CPD = OFF ; Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
config WRT0 = OFF ; Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
config WRT1 = OFF ; Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
config WRT2 = OFF ; Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
config WRT3 = OFF ; Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)
config WRTC = OFF ; Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
config WRTB = OFF ; Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
config WRTD = OFF ; Data EEPROM Write Protection bit (Data EEPROM is not write-protected)
config EBTR0 = OFF ; Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
config EBTR1 = OFF ; Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
config EBTR2 = OFF ; Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
config EBTR3 = OFF ; Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
config EBTRB = OFF ; Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)
;
; Specify the System clock frequency in Hz
;
#define FOSC 48000000
;
; Specify the Peripheral clock frequency in Hz
;
#define FCYC (FOSC/4)
;
; Include device specific definitions for Special Function Registers
;
#include <p18F2550.inc>
;
;
;
;
;
resetVec code 0x0000 ; processor reset vector
;
resetVec:
clrf TBLPTRU, ACCESS
goto Start
;
hi_int_vec code 0x0008
;
goto HighIsrHandler
;
LowIsr_data udata_acs
;
global WREG_save,STATUS_save,BSR_save
;
WREG_save: res 1
STATUS_save: res 1
BSR_save: res 1
;
lo_int_vec code 0x0018
;
LowIsrVec:
movff WREG,WREG_save
movff STATUS,STATUS_save
movff BSR,BSR_save
;
LowIsrHandler:
;
movff BSR_save,BSR
movff STATUS_save,STATUS
movff WREG_save,WREG
retfie
;
HighIsr_code code
;
HighIsrHandler:
return FAST
;
start_code code
;
Start:
bcf INTCON,GIEH ; Disable all interrupts
bcf INTCON,GIEL
bsf RCON,IPEN ; Enable interrupt priority
;
movlw 0x00 ; Set primary oscillator as system clock source
movwf OSCCON,ACCESS ;
;
movlw 0x0F ; Configure A/D
movwf ADCON1 ; for digital inputs
;
goto main
;
; Implement integer square root
;
; unsigned long in;
; unsigned long out;
; unsigned long bit;
; unsigned long temp;
;
; unsigned long isqrt(void)
; {
; out = 0;
; bit = 1L << 30;
;
; // "bit" starts at the highest power of four <= the argument.
; while (bit > in)
; bit >>= 2;
;
; while (bit != 0)
; {
; temp = out + bit;
; out >>= 1;
; if (in >= temp)
; {
; in -= temp;
; out += bit;
; }
; bit >>= 2;
; }
; return out;
; }
;
;
isqrt_data udata
global isqrt_in,isqrt_out,isqrt_bit,isqrt_temp
;
isqrt_in: res 4
isqrt_out: res 4
isqrt_bit: res 4
isqrt_temp: res 4
;
isqrt_code code
;
;
; logical shift right one bit [fsr1]
;
isqrt_lsr:
bcf STATUS,C
rrcf POSTDEC1,F
rrcf POSTDEC1,F
rrcf POSTDEC1,F
rrcf INDF1,f
return
;
; Compare [FSR2] - [FSR1]
; Carry set when [FSR2] >= [FSR1]
; Carry clear when [FSR2] < [FSR1]
;
isqrt_cmp:
movf POSTINC1,w
subwf POSTINC2,w
movf POSTINC1,w
subwfb POSTINC2,w
movf POSTINC1,w
subwfb POSTINC2,w
movf INDF1,w
subwfb INDF2,w
return
;
isqrt:
clrf isqrt_out
clrf isqrt_out+1
clrf isqrt_out+2
clrf isqrt_out+3
;
clrf isqrt_bit
clrf isqrt_bit+1
clrf isqrt_bit+2
movlw B'01000000'
movwf isqrt_bit+3
;
FindMSB:
lfsr FSR1,isqrt_bit
lfsr FSR2,isqrt_in
rcall isqrt_cmp ; STATUS set to (isqrt_in - isqrt_bit)
bc FindNextDigit ; branch when isqrt_in >= isqrt_bit
;
; Shift the digits right two bits
;
lfsr FSR1,isqrt_bit+3
rcall isqrt_lsr
lfsr FSR1,isqrt_bit+3
rcall isqrt_lsr
bra FindMSB
;
FindNextDigit:
movf isqrt_bit,W
iorwf isqrt_bit+1,W
iorwf isqrt_bit+2,W
iorwf isqrt_bit+3,W
bz isqrt_done
;
movf isqrt_bit,W
addwf isqrt_out,W
movwf isqrt_temp
movf isqrt_bit+1,W
addwfc isqrt_out+1,W
movwf isqrt_temp+1
movf isqrt_bit+2,W
addwfc isqrt_out+2,W
movwf isqrt_temp+2
movf isqrt_bit+3,W
addwfc isqrt_out+3,W
movwf isqrt_temp+3
;
lfsr FSR1,isqrt_out+3
rcall isqrt_lsr
;
lfsr FSR1,isqrt_temp
lfsr FSR2,isqrt_in
rcall isqrt_cmp ; STATUS set to (isqrt_in - isqrt_temp)
bnc NoDigitUpdate ; Branch when isqrt_in >= isqrt_temp
;
movf isqrt_temp,W
subwf isqrt_in
movf isqrt_temp+1,W
subwfb isqrt_in+1
movf isqrt_temp+2,W
subwfb isqrt_in+2
movf isqrt_temp+3,W
subwfb isqrt_in+3
;
movf isqrt_bit,W
addwf isqrt_out
movf isqrt_bit+1,W
addwfc isqrt_out+1
movf isqrt_bit+2,W
addwfc isqrt_out+2
movf isqrt_bit+3,W
addwfc isqrt_out+3
;
NoDigitUpdate:
;
lfsr FSR1,isqrt_bit+3
rcall isqrt_lsr
lfsr FSR1,isqrt_bit+3
rcall isqrt_lsr
bra FindNextDigit
;
isqrt_done:
return
;
main_code code
;
;
; Constants
#define TEST_VALUE1 2*2
#define TEST_VALUE2 3*3
#define TEST_VALUE3 4*4
#define TEST_VALUE4 5*5
#define TEST_VALUE5 6*6
#define TEST_VALUE6 10*10
#define TEST_VALUE7 9999*9999
#define TEST_VALUE8 12345*12345
#define TEST_VALUE9 65535*65535
;
; Macro to load a 32-bit constant
;
load32 macro DWORD, CONST
;
banksel DWORD
movlw 0xFF & (CONST)
movwf DWORD
movlw 0xFF & (CONST >> 8)
movwf DWORD+1
movlw 0xFF & (CONST >> 16)
movwf DWORD+2
movlw 0xFF & (CONST >> 24)
movwf DWORD+3
;
endm
;
main:
;
AppLoop:
load32 isqrt_in,TEST_VALUE1
call isqrt
load32 isqrt_in,TEST_VALUE2
call isqrt
load32 isqrt_in,TEST_VALUE3
call isqrt
load32 isqrt_in,TEST_VALUE4
call isqrt
load32 isqrt_in,TEST_VALUE5
call isqrt
load32 isqrt_in,TEST_VALUE6
call isqrt
load32 isqrt_in,TEST_VALUE7
call isqrt
load32 isqrt_in,TEST_VALUE8
call isqrt
load32 isqrt_in,TEST_VALUE9
call isqrt
goto AppLoop
;
END
这是移植到使用 pic-as(v2.20) 工具链构建的代码:
; File: main.S
; Target: PIC18F2550
; Author: dan1138
; Date: 2020-06-17
; Compiler: pic-as(v2.20)
; IDE: MPLABX v5.40
;
; Description:
;
; Find integer square root of a 32-bit value
;
; Add to the MPLABX project Additional options:
; -Wa,-a -Wl,-presetVec=0h,-phi_int_vec=08h,-plo_int_vec=18h
;
; PIC18F2550
; +------------:_:------------+
; VPP -> 1 : RE3/MCLRn/VPP PGD/RB7 : 28 <> PGD
; -> 2 : RA0/AN0 PGC/RB6 : 27 <> PGC
; <> 3 : RA1/AN1 PGM/RB5 : 26 <>
; <> 4 : RA2/AN2 AN11/RB4 : 25 <>
; <> 5 : RA3/AN3 AN9/RB3 : 24 <>
; <> 6 : RA4/C1OUT AN8/RB2 : 23 <>
; <> 7 : RA5/AN4 AN10/RB1 : 22 <>
; GND <> 8 : VSS AN12/RB0 : 21 <>
; 20MHz <> 9 : RA7/OSC1 VDD : 20 <- 5v0
; 20MHz <> 10 : RA6/OSC2 VSS : 19 <- GND
; 32.768KHz <> 11 : RC0/SOSCO RX/DT/RC7 : 18 <>
; 32.768KHz <> 12 : RC1/SOSCI TX/CK/RC6 : 17 <>
; <> 13 : RC2/CCP1 D+/RC5 : 16 <-
; <> 14 : VUSB D-/RC4 : 15 <-
; +---------------------------:
; DIP-28
; Note:
; RC4,RC5 can only be used as digital inputs when the USB transceiver is not used.
;
processor 18F2550
pagewidth 132
radix dec
;
config PLLDIV = 5 ; PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input))
config CPUDIV = OSC1_PLL2 ; System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
config USBDIV = 2 ; USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes from the 96 MHz PLL divided by 2)
config FOSC = HSPLL_HS ; Oscillator Selection bits (HS oscillator, PLL enabled (HSPLL))
config FCMEN = OFF ; Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
config IESO = OFF ; Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
config PWRT = OFF ; Power-up Timer Enable bit (PWRT disabled)
config BOR = OFF ; Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
config BORV = 3 ; Brown-out Reset Voltage bits (Minimum setting 2.05V)
config VREGEN = OFF ; USB Voltage Regulator Enable bit (USB voltage regulator disabled)
config WDT = OFF ; Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
config WDTPS = 32768 ; Watchdog Timer Postscale Select bits (1:32768)
config CCP2MX = ON ; CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
config PBADEN = OFF ; PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
config LPT1OSC = OFF ; Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)
config MCLRE = ON ; MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
config STVREN = ON ; Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
config LVP = OFF ; Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
config XINST = OFF ; Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
config CP0 = OFF ; Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)
config CP1 = OFF ; Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)
config CP2 = OFF ; Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)
config CP3 = OFF ; Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)
config CPB = OFF ; Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)
config CPD = OFF ; Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
config WRT0 = OFF ; Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)
config WRT1 = OFF ; Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)
config WRT2 = OFF ; Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)
config WRT3 = OFF ; Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)
config WRTC = OFF ; Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)
config WRTB = OFF ; Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)
config WRTD = OFF ; Data EEPROM Write Protection bit (Data EEPROM is not write-protected)
config EBTR0 = OFF ; Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)
config EBTR1 = OFF ; Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)
config EBTR2 = OFF ; Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)
config EBTR3 = OFF ; Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)
config EBTRB = OFF ; Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)
;
; Specify the System clock frequency in Hz
;
#define FOSC 48000000
;
; Specify the Peripheral clock frequency in Hz
;
#define FCYC (FOSC/4)
;
; Include device specific definitions for Special Function Registers
;
#include <xc.inc>
;
; Preprocessor macro to help with LFSR opcode
;
#define FSR(x) (x)
;
psect resetVec,global,reloc=2,class=CODE,delta=1
;
resetVec:
clrf TBLPTRU,c
goto Start
;
psect hi_int_vec,global,reloc=2,class=CODE,delta=1
;
goto HighIsrHandler
;
psect LowIsr_data,global,class=COMRAM,space=1,delta=1,lowdata,noexec
;
global WREG_save,STATUS_save,BSR_save
;
WREG_save: ds 1
STATUS_save: ds 1
BSR_save: ds 1
;
psect lo_int_vec,global,reloc=2,class=CODE,delta=1
;
LowIsrVec:
movff WREG,WREG_save
movff STATUS,STATUS_save
movff BSR,BSR_save
;
LowIsrHandler:
;
movff BSR_save,BSR
movff STATUS_save,STATUS
movff WREG_save,WREG
retfie 0
;
psect HighIsr_code,global,reloc=2,class=CODE,delta=1
;
HighIsrHandler:
return 1
;
psect start_code,global,reloc=2,class=CODE,delta=1
;
Start:
bcf INTCON,INTCON_GIEH_POSITION,0 ; Disable all interrupts
bcf INTCON,INTCON_GIEL_POSITION,0
bsf RCON,RCON_IPEN_POSITION,0 ; Enable interrupt priority
;
movlw 0x00 ; Set primary oscillator as system clock source
movwf OSCCON,c ;
;
movlw 0x0F ; Configure A/D
movwf ADCON1,c ; for digital inputs
;
goto main
;
; Implement integer square root
;
; unsigned long in;
; unsigned long out;
; unsigned long bit;
; unsigned long temp;
;
; unsigned long isqrt(void)
; {
; out = 0;
; bit = 1L << 30;
;
; // "bit" starts at the highest power of four <= the argument.
; while (bit > in)
; bit >>= 2;
;
; while (bit != 0)
; {
; temp = out + bit;
; out >>= 1;
; if (in >= temp)
; {
; in -= temp;
; out += bit;
; }
; bit >>= 2;
; }
; return out;
; }
;
;
psect isqrt_data,global,class=RAM,space=1,delta=1,noexec
global isqrt_in,isqrt_out,isqrt_bit,isqrt_temp
;
isqrt_in: ds 4
isqrt_out: ds 4
isqrt_bit: ds 4
isqrt_temp: ds 4
;
psect isqrt_code,global,reloc=2,class=CODE,delta=1
;
;
; 32-bit logical shift right one bit [fsr1]
;
isqrt_lsr:
bcf STATUS,STATUS_C_POSITION,0
rrcf POSTDEC1,1,0
rrcf POSTDEC1,1,0
rrcf POSTDEC1,1,0
rrcf INDF1,1,0
return
;
; Compare [FSR2] - [FSR1]
; Carry set when [FSR2] >= [FSR1]
; Carry clear when [FSR2] < [FSR1]
;
isqrt_cmp:
movf POSTINC1,w,c
subwf POSTINC2,w,c
movf POSTINC1,w,c
subwfb POSTINC2,w,c
movf POSTINC1,w,c
subwfb POSTINC2,w,c
movf INDF1,w,c
subwfb INDF2,w,c
return
;
isqrt:
clrf BANKMASK(isqrt_out),b
clrf BANKMASK(isqrt_out)+1,b
clrf BANKMASK(isqrt_out)+2,b
clrf BANKMASK(isqrt_out)+3,b
;
clrf BANKMASK(isqrt_bit),b
clrf BANKMASK(isqrt_bit)+1,b
clrf BANKMASK(isqrt_bit)+2,b
movlw 0b01000000
movwf BANKMASK(isqrt_bit)+3,b
;
FindMSB:
lfsr FSR(1),isqrt_bit
lfsr FSR(2),isqrt_in
rcall isqrt_cmp ; STATUS set to (isqrt_in - isqrt_bit)
bc FindNextDigit ; branch when isqrt_in >= isqrt_bit
;
; Shift the digits right two bits
;
lfsr FSR(1),isqrt_bit+3
rcall isqrt_lsr
lfsr FSR(1),isqrt_bit+3
rcall isqrt_lsr
bra FindMSB
;
FindNextDigit:
movf BANKMASK(isqrt_bit),W,b
iorwf BANKMASK(isqrt_bit)+1,W,b
iorwf BANKMASK(isqrt_bit)+2,W,b
iorwf BANKMASK(isqrt_bit)+3,W,b
bz isqrt_done
;
movf BANKMASK(isqrt_bit),W,b
addwf BANKMASK(isqrt_out),W,b
movwf BANKMASK(isqrt_temp),b
movf BANKMASK(isqrt_bit)+1,W,b
addwfc BANKMASK(isqrt_out)+1,W,b
movwf BANKMASK(isqrt_temp)+1,b
movf BANKMASK(isqrt_bit)+2,W,b
addwfc BANKMASK(isqrt_out)+2,W,b
movwf BANKMASK(isqrt_temp)+2,b
movf BANKMASK(isqrt_bit)+3,W,b
addwfc BANKMASK(isqrt_out)+3,W,b
movwf BANKMASK(isqrt_temp)+3,b
;
lfsr FSR(1),isqrt_out+3
rcall isqrt_lsr
;
lfsr FSR(1),isqrt_temp
lfsr FSR(2),isqrt_in
rcall isqrt_cmp ; STATUS set to (isqrt_in - isqrt_temp)
bnc NoDigitUpdate ; Branch when isqrt_in >= isqrt_temp
;
movf BANKMASK(isqrt_temp),W,b
subwf BANKMASK(isqrt_in),b
movf BANKMASK(isqrt_temp)+1,W,b
subwfb BANKMASK(isqrt_in)+1,b
movf BANKMASK(isqrt_temp)+2,W,b
subwfb BANKMASK(isqrt_in)+2,b
movf BANKMASK(isqrt_temp)+3,W,b
subwfb BANKMASK(isqrt_in)+3,b
;
movf BANKMASK(isqrt_bit),W,b
addwf BANKMASK(isqrt_out),b
movf BANKMASK(isqrt_bit)+1,W,b
addwfc BANKMASK(isqrt_out)+1,b
movf BANKMASK(isqrt_bit)+2,W,b
addwfc BANKMASK(isqrt_out)+2,b
movf BANKMASK(isqrt_bit)+3,W,b
addwfc BANKMASK(isqrt_out)+3,b
;
NoDigitUpdate:
;
lfsr FSR(1),isqrt_bit+3
rcall isqrt_lsr
lfsr FSR(1),isqrt_bit+3
rcall isqrt_lsr
bra FindNextDigit
;
isqrt_done:
return
;
psect main_code,global,reloc=2,class=CODE,delta=1
;
;
; Constants
#define TEST_VALUE1 2*2
#define TEST_VALUE2 3*3
#define TEST_VALUE3 4*4
#define TEST_VALUE4 5*5
#define TEST_VALUE5 6*6
#define TEST_VALUE6 10*10
#define TEST_VALUE7 9999*9999
#define TEST_VALUE8 12345*12345
#define TEST_VALUE9 65535*65535
;
; Macro to load a 32-bit constant
;
load32 macro DWORD,CONST
;
banksel DWORD
movlw 255 and (CONST)
movwf BANKMASK(DWORD),b
movlw 255 and (CONST >> 8)
movwf BANKMASK(DWORD)+1,b
movlw 255 and (CONST >> 16)
movwf BANKMASK(DWORD)+2,b
movlw 255 and (CONST >> 24)
movwf BANKMASK(DWORD)+3,b
;
endm
;
main:
;
AppLoop:
load32 isqrt_in,TEST_VALUE1
call isqrt
load32 isqrt_in,TEST_VALUE2
call isqrt
load32 isqrt_in,TEST_VALUE3
call isqrt
load32 isqrt_in,TEST_VALUE4
call isqrt
load32 isqrt_in,TEST_VALUE5
call isqrt
load32 isqrt_in,TEST_VALUE6
call isqrt
load32 isqrt_in,TEST_VALUE7
call isqrt
load32 isqrt_in,TEST_VALUE8
call isqrt
load32 isqrt_in,TEST_VALUE9
call isqrt
goto AppLoop
;
END resetVec
使用 kdiff 等源文件差异工具查看需要更改的内容。
我非常努力地进行最小的更改,以便从两个汇编程序中获得相同的 HEX 文件输出。
有关完整的 MPLABX v5.40 项目,请参阅此 git repository。