初めての記事がコレというのもちょっと引っ掛かりますが,まとまっている記事に出会えなかったのでまとめておこうかと思います。
Microchip が製造するPICのIDEである MPLAB X IDE, 何年か前に ver.5.40 になった際に長らく使われていた MPASM が付属しなくなり,代わりに XC8 に付属する pic-as を使用する事になりました。
この際多くの人がハマったようで,先人たちが移行のまとめ記事を各所で書いています。
しかし,一つだけ解決策らしい内容が見つからなかった物が。
というのがタイトルの通り,BSF等でビット位置の表記がエラーになり Assemble が通らないと言う物。
この原因を調べたのでまとめておきます。
PICってなんぞや?
興味本位?アセンブラ好きすぎ?で見てしまった人に少し解説を。PICって何ぞや?という話。
ググれば出てくる話ではありますが,物としてはワンチップマイコンです。
で,コイツがちょっと変態アーキテクチャでRISCのハーバードアーキテクチャーライク(!?)なマイクロコントローラーです。
初期は8bitのマイコンとして始まりましたが,その後16bitの物も製品化され,更にはMIPSコアを使用した PIC32MX 等も製造されています。今はARMコアの物もあるようです。
このPIC,古くから電子工作で人気があり,人気の理由の一つに8bitの製品の一つであるPIC16はアセンブラの命令が35個しかなく,すぐに覚えられるという点があります。
現在は改良され,C言語と親和性が良くなるよう,いくつか命令が追加された改良型のPIC16Fxxxx(型式が4桁の物)やPIC18等もあります。
そんなわけで長らくアセンブラによる開発が続いてきたのですが・・・今回の記事の通り。
アセンブラが変わり色々とみんなでハマったという話です。
有志により移行の記事がまとめられたのですが,その中で解決策や原因が明確に出ていなかった点についての記事になります。
【現象】あれ?BSF,アセンブル通らねーんだけど?
さて,今回の記事の現象です。私も久しぶりにいじって「あれ?コレ pic-as では通らなかったっけ?」と古い記憶がよみがえった話です。
PICにはビット操作命令と言う物があり,そのアセンブルでエラーが出てしまうと言う物です。
例えば・・・
LABEL: BSF INTCON, GIE
こんなのを書くとエラーになると言う物。
PICの事を知っている人が見ると「あぁ,割り込み許可したのね」というコードです。
Z-80なら「EI」ですね。
BSFとは「Bit Set File register」という意味で,ファイルレジスタの指定したビットを1にする(セットする)という意味です。
補足ですが,PICはRAMもレジスタの一種として扱います。PICではRAMの事を「ファイルレジスタ」と呼んでいます。
さて,BSFですが,オペランドは1つ目がファイルレジスタのアドレス,2つ目がファイルレジスタ内のビットの位置になります。
ここで「INTCON」や「GIE」というラベルはヘッダーに定義されており先頭でinclude,アセンブラは解釈できます。
例を人間の言葉にすれば「INTCON(RAM空間にマップされた割り込み制御レジスタ)のGIE(割り込み許可ビット)というビットをセットしなさい」となり「割り込みを許可しなさい」という意味になります。
さて,例の意味が分かると・・・何も不思議ではないコードです。
しかし,これが MPASM ではエラーにならないのに pic-as ではエラーになってしまうと言う物です。具体的には「Syntax Error」が出てしまいます。
何か不思議ですね?命令の記法の通りに書いてるのに・・・Syntax Error?
・・・実は,この「Syntax Error が出る」という点が後々ミソになります。
巷での解決策
さて,巷で見かける解決策はと言えば以下のように修正すると言う物。
LABEL: BSF INTCON, 7
ビットの位置をラベルではなく直接数値で記述すると言う物。
あ,GIEビットってbit7なんです。一番上位のビットですね。
そもそもラベルなので数値に文字で名前を付けているだけです。直接数値を書いてしまえと言う物。これでアセンブルするとちゃんとアセンブルが通ります。
通るんですが・・・
ぱっと見分かりにくい。
PIC,物により数十~数百個のレジスタがあり,すべてのビット位置なんて覚えられません。
なので何かラベルは使いたい・・・
と言う訳でもうちょっと粘ってみます。
原因はラベルである事ではない
さて,もうちょっと何とかならんか?と踏み込んでみるわけなのですが,これ・・・
IntEn equ 7
LABEL: BSF INTCON, IntEn
・・・はアセンブルが通ります。
あ,因みに「equ」は「equal」という意味です。「IntEnは7ですよ」という意味です。
ここで「あれ?」と思いませんか?
これ,ラベルなのにアセンブルが通ってます。
つまり,ラベルである事はエラーの原因ではありません。
じゃぁ,ラベルがなかったんじゃ?とこんなのも行ってみましょう。
GIE equ 7
LABEL: BSF INTCON, GIE
きっと「GIE」が定義されてないんだ,と定義してみました。
するとこれまたエラーです。何故か Syntax Error。
(あ,オチが分かると「何かもうちょっとわかりやすいエラー出せよ」なんですが)
これらの事を整理すると・・・・
①定義されているから,とラベルを使うとエラーする。
②数値で指定すると通る。よって命令からの翻訳,文法の解釈は合ってる。
③ラベルを適当に定義してみて,そのラベルを使うと通る。よってラベルを使う事が原因ではない。
④定義されているだろうと思っていたラベルを自前で定義するとエラーになる。
・・・という結果。
すると怪しいのは・・・ヘッダーファイルですね?
ところでヘッダーどれ読んでんだべなぁ?
さて,ヘッダーがなんかマズいんでねーか?と分かった所で,ヘッダーを読んでみましょう。
とは言え,そのヘッダー何処にあるんだろう?という話ですよね?
現行のMPLAB,プロジェクト配下の\build\default\productionに「(プロジェクト名).i」というファイルを作成しており,これがビルドのログになるようです。
(iなのでアセンブラに入力した内容のようです,oというファイルもあり,こちらはアセンブラの出力のようです)
ちょっと覗いてみましょう。
# 1 "<built-in>" 1
# 1 "Test.asm" 2
PROCESSOR 16F84A
; PIC16F84A Configuration Bit Settings
; Assembly source line config statements
; CONFIG
CONFIG FOSC = HS ; Oscillator Selection bits (HS oscillator)
CONFIG WDTE = OFF ; Watchdog Timer (WDT disabled)
CONFIG PWRTE = ON ; Power-up Timer Enable bit (Power-up Timer is enabled)
CONFIG CP = OFF ; Code Protection bit (Code protection disabled)
# 1 "C:\\Program Files\\Microchip\\xc8\\v2.46\\pic\\include\\xc.inc" 1 3
# 1 "C:/Program Files/Microchip/MPLABX/v6.20/packs/Microchip/PIC16Fxxx_DFP/1.6.156/xc8\\pic\\include\\pic.inc" 1 3
# 1 "C:/Program Files/Microchip/MPLABX/v6.20/packs/Microchip/PIC16Fxxx_DFP/1.6.156/xc8\\pic\\include\\pic_as_chip_select.inc" 1 3
# 543 "C:/Program Files/Microchip/MPLABX/v6.20/packs/Microchip/PIC16Fxxx_DFP/1.6.156/xc8\\pic\\include\\pic_as_chip_select.inc" 3
# 1 "C:/Program Files/Microchip/MPLABX/v6.20/packs/Microchip/PIC16Fxxx_DFP/1.6.156/xc8\\pic\\include\\proc\\pic16f84a.inc" 1 3
# 47 "C:/Program Files/Microchip/MPLABX/v6.20/packs/Microchip/PIC16Fxxx_DFP/1.6.156/xc8\\pic\\include\\proc\\pic16f84a.inc" 3
INDF equ 0000h
・
・
・
覗いてみると,こんな感じで始まっていました。
xc.inc(MPLABではヘッダーファイルにあたるファイルの拡張子は ”inc”)のIncludeを解釈して,結果的にMPLABのインストールフォルダー配下(XC8配下ではない)の「pic16f84a.inc」というファイルを読んでいるようです。
途中出てくる「pic_as_chip_select.inc」というファイルは,中身を見る限り使用しているデバイス(チップ)に合うヘッダーを選択してくれる処理のようです。
選択の結果,この例では PIC16F84A(デバイス,ICの型式です)のプロジェクトなので,「pic16f84a.inc」を読み込んだようです。
さて,型式がファイル名に入っているほどですから,中身はチップに合わせたビットやアドレスの定義でしょう。
因みに ver5.35 まで付属したMPAMSもそっくりな名前のヘッダーがあり,中身はアドレスなどの定義が書かれていました。
中を覗いてみると・・・
// Generated 12/10/2023 GMT
/*
* Copyright ツゥ 2023, Microchip Technology Inc. and its subsidiaries ("Microchip")
* All rights reserved.
*
* This software is developed by Microchip Technology Inc. and its subsidiaries ("Microchip").
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. Publication is not required when
* this file is used in an embedded application.
*
* 3. Microchip's name may not be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MICROCHIP "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MICROCHIP BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT LIMITED TO
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWSOEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PIC16F84A_INC_
#define _PIC16F84A_INC_
/*
* Assembly Header file for the Microchip PIC Microcontroller
* PIC16F84A
*/
/*
* Device Registers
*/
// Register: INDF
#define INDF INDF
INDF equ 0000h
// Register: TMR0
#define TMR0 TMR0
TMR0 equ 0001h
// Register: PCL
#define PCL PCL
PCL equ 0002h
・
・
・
・・・何やら長~い英語の説明に続き,見慣れた定義が。
そうですね,INDFのアドレスは0x000ですね。TMR0も0x001です。お?当たりのようです。
この方法で読み込んでいるヘッダーを特定できるようです。
さて,ではビットの定義は・・・と読んで,なるほどな,ってなりました(苦笑
GIE,彼は・・・文字列なんだねぇ・・・
さて,今回の例で出てきた「GIE」はどのように定義されていたかというと・・・
いや,びっくりしました(苦笑
#define GIE BANKMASK(INTCON), 7
おぉ,なるほど,そりゃ Syntax Error だわ。
ビット位置の「数字であれ文字であれの ”7”」が入っていると思っていた「GIE」・・・いやMPAMSはそうなってるんですが・・・
pic-as は「”BANKMASK(INTCON), 7” という文字列」になっていました。
これ,どのように解釈されるのか考えて見ましょう。
MPASMの様に「GIE」が「7」であった場合,GIEは・・・
LABEL: BSF INTCON, GIE
↓
LABEL: BSF INTCON, 7
・・・と解釈されます。
もちろん「INTCON」も同時にアドレスの数字になりますけどね。ここではGIEに着目してGIEのみ解釈させています。
しかし,今回の場合「GIE」は「BANKMASK(INTCON), 7」ですから・・・
LABEL: BSF INTCON, GIE
↓
LABEL: BSF INTCON, BANKMASK(INTCON), 7
・・・と解釈されます。
これ,なんだかわかりにくいのでMPASM風に整理すると・・・
LABEL: BSF INTCON, GIE
↓
LABEL: BSF INTCON, INTCON, 7
・・・となります。
はい!Syntax Error!
なんと・・・いや,途中の予想通り?ヘッダーの定義の問題でした。
これ,pic-as から名称が変わったようです。
ヘッダーを見ているとこんな定義がありました。
INTCON_GIE_POSN equ 0007h
INTCON_GIE_POSITION equ 0007h
はい,INTCONのbit7は「GIE」ですから,合ってますね。
名前が変わっていたようです。
でも,一ついたずら心が騒ぎませんか?
「GIE」ってレジスタ名も入ってるんですよね?ならば・・・
LABEL: BSF GIE
すっげーキメェけど,これで通るんじゃないか?と。
やってみました。
通りました(マジです
当然ですよね?「GIE」の中身は「INTCON, 7 相当」なんですから。
「えぇ~,MPASMと同じで通るようにしてよ!!」という気持ちはありますが,とりあえず少しは見やすい形にはなりました。
と言う訳で,まだ気になりはしますが,とりあえず「原因」は判明です。
とりあえず原因は判明したけど,コレどうしましょ?
さて,原因は突き止め,かつ少しは見やすい形に書けそうな雰囲気は出てきた物の,やっぱりなんか変!!
定義を見る限り,ビット位置のみを定義した名称はある物の,先に記載の通りずいぶん長い名前になったようです。
xc.incやpic_as_chip_select.incを見ていると,ヘッダーを読み込みに行く仕組み的にはそんなに難しくないようです。
スッキリやるのには,これらのファイルを書き換えるか自前で用意すれば解決しそうです。
ただ,まだ試してはいないのと,大規模な統合開発環境なのでどのような影響が出るかはやってみないとわかりません。
さて,コレだという解決策は考え付きませんでしたが,とりあえず原因だけは突き止めることは出来ました。
尻切れトンボではありますが,この記事が誰かの参考になれば幸いです。
また,今回は初めての記事故,「Qiitaの記事ってこんな感じかな?」と書きましたが,大外れしていなければ幸いです。