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