Dạng lệnh: GOTO nhãn
Miêu tả: nhảy đến đoạn chương trình bắt đầu bởi nhãn
Để hiểu rõ đoạn chương trình trên ta có ví dụ sau: START:
BSF PORTB,1 CALL DELAY
BCF PORB,1 CALL DELAY
GOTO START
Khi gặp lệnh GOTO START, vi điều khiển lập tức nhảy đến đoạn chương trình bắt đầu bởi START tức là sẽ nhảy đến lệnh BSF PORTB,1
Thực ra, đằng sau lệnh GOTO START, vi điều khiển tính ra địa chỉ của lệnh bắt đầu sau START giả sử đó là k, và câu lệnh thực sự là GOTO k
Chúng ta xem dạng dissampling của đoạn lệnh trên sẽ rõ:
29: ; BAT DAU XU LY 30: START: 30: START:
000A 1486 BSF 0x6, 0x1 31: BSF PORTB,1 000B 200F CALL 0xf 32: CALL DELAY 000C 1086 BCF 0x6, 0x1 33: BCF PORTB,1 000D 200F CALL 0xf 34: CALL DELAY 000E 280A GOTO 0xa 35: GOTO START
Cột thứ nhất chứa địa chỉ của lệnh. Cột thứ 3 là lệnh thực sự đã được phân giải. Ta thấy lệnh nằm ngay sau nhãn là BSF PORTB,1 có địa chỉ là 0x0a trong bộ nhớ chương trình
Vì vậy trong cột 3, ta có lệnh GOTO 0xa Như vậy dạng lệnh thực sự là GOTO k
Khi gặp lệnh này: PC<10:0>=k; PC<12:11>=PCLATCH<4:3> Tóm lại có thể giải thích lại như sau:
Khi gặp lệnh: goto nhãn
Trong trường hợp trên là goto start
MPLAB tính ra địa chỉ của lệnh nằm ngay sau nhãn start, giả sử đó là k Trong trường hợp trên là lệnh BSF PORTB,1 có địa chỉ k=0x0a
Do đó chương trình vi điều khiển sẽ chạy lệnh BSF PORTB,1 Mã hóa lệnh: 10 1kkk kkkk kkkk
Nhìn vào mã hóa lệnh ta thấy địa chỉ k gồm 11 bit kkk kkkk kkkk Như vậy thực ra chỉ 11 bit đầu của thanh ghi PC là chứa giá trị k: PC<10:0>=kkk kkkk kkkk
2 bit cao của thanh ghi PC lấy từ thanh ghi PCLATCH PC<12:11>=PCLATCH<4:3>
Điều này sẽ dẫn đến một vấn đề!!! Giả sử ta có đoạn chương trình sau: org 0x005 main banksel trisb clrf trisb banksel PORTB START: BSF PORTB,1 CALL DELAY BCF PORTB,1 CALL DELAY GOTO UPDATE ORG 0x800 UPDATE: MOVLW 0xFF MOVWF PORTB
Như vậy lệnh GOTO UPDATE nằm ở địa chỉ 0x0E
Như vậy khi gặp lệnh này, 2 bit của thanh ghi PCLATCH<4:3>=00
Lệnh nằm sau nhãn UPDATE là MOVLW 0xFF nằm ở địa chỉ 0x800 (do có chỉ dẫn biên dịch ORG 0x800)
Như vậy khi gặp lệnh GOTO UPDATE, thanh ghi PC được nạp giá trị: PC<10:0> = 000 0000 0000
PCLATCH vẫn không đổi: PCLATCH<4:3>=00 Suy ra, PC<12:11>=PC<4:3>=00
Suy ra: PC=0 0000 0000 0000 =0x00
Vậy chương trình nhảy đến địa chỉ 0x00!!!!!
Chắc chắn là chương trình sẽ khơng chạy được đoạn lệnh nằm sau UPDATE Để chạy đúng, đơn giản là ta phải dùng lệnh cho PCLATCH<4:3>=01 Đoạn chương trình đúng sẽ như sau:
org 0x005 main banksel trisb clrf trisb banksel PORTB START: BSF PORTB,1 CALL DELAY BCF PORTB,1 CALL DELAY PAGESEL UPDATE GOTO UPDATE ORG 0x800 UPDATE: MOVLW 0xFF MOVWF PORTB