石原 博の覚書

電子工作に関する日々の覚書を記載します

PL/M

2021-10-31 16:12:27 | 日記

CUGにも幾つかPL/Mでかかれたプログラムがある。PL/MコンパイラをコンパイルするにはFortranコンパイラが必要なので、Linux上でgfortranを使用し動かしてみた。

(1)The Unofficial CP/M Web Siteから「PLM compiler source 」をダウンロードし展開
(2)本体はPLM81.FORとPLM82.FOR
  gfortran PLM81.FOR -o plm81
    gfortran PLM82.FOR -o plm82
   ソースの最後にCP/MのEOFである01AHがあるのでエラーになるが、それを除いてコンパイル。いろいろWarningが出るが無視。
(3)使い方が良くわからなったが、同サイト上の「PL/M-80 compiler for DOS Box: 500K」を展開してみたところ、以下のDOSのバッチファイルがあった。つまり入力ファイルも出力ファイルもファイル名は固定ということ。(fort.1は良くわからないけど)

===PLM80.BAT===
Rem This setup created by mr.collis@physics.org 31/03/2008
copy %1.plm fort.2
echo rubbish  > fort.1
plm81

rename fort.16 fort.4
rename fort.17 fort.7
plm82
copy fort.17 %1.hex
===============

linuxでは以下のスクリプトを作成。(改行をCR/LFにするのもsedで組み込んだ)
===plm80===
#!/bin/sh
cp $1.PLM fort.2
echo rubbish > fort.1
./plm81

mv fort.16 fort.4
mv fort.17 fort.7
./plm82
sed 's/$/\r/g' fort.17 > $1.HEX
===========

./plm80 PLMSAMP としてコンパイルすればPLMSAMP.HEXが生成される。(付属していたPLMSAMP.HEXと一致することを確認)

これをCP/MでLOADすれば動くはず。ところがエラー「ERROR: INVERTED LOAD ADDRESS, LOAD ADDRESS 0010」
HEXファイルを調べてみると、ロード場所が0010スタート。良く見るとPLMSAMP.PLM内で、「10H:  /*  IS THE ORIGIN OF THIS PROGRAM */」となっている。ソースを修正 (10H->100H)しコンパイルし、CP/Mでロード
  
>load PLMSAMP.HEX

FIRST ADDRESS 0100
LAST  ADDRESS 0381
BYTES READ    0282
RECORDS WRITTEN 06

ところが、実行するとエラー。もう一度ソースを良く読むと、なんと出力ルーチンがアドレスで指定されている。

    /* PRINT USING INTELLEC MONITOR */                                          
PRINT$CHAR: PROCEDURE (CHAR);                                                   
    DECLARE CHAR BYTE;                                                          
    DECLARE IOCO LITERALLY '3809H';                                             
    GO TO IOCO;                                                                 
    END PRINT$CHAR;                      

fort.12がリストファイルなので、該当するPRINT$CHARルーチンを探すと、0197Hとなっている。DDTでHEXファイルを確認すると、
  0197  LXI  H,03E1
  019A  MOV  M,C
  019B  JMP  3809
  019E  RET  

0x3809に出力ルーチンを作れば良いのだが、Cregを出力すれば良いのか? どのレジスタを保存すべきか? よくわからない。出来るだけ安全サイドでBDOSコールルーチンを作る。

===COUT.ASM===
;--CP/M interface---------------
BDOS EQU 5

ORIGIN EQU 3809H
;
 ORG ORIGIN
COUT: PUSH H
 PUSH D
 PUSH B
 PUSH PSW
 MOV E,C
 MVI C,2
 CALL BDOS
 POP PSW
 POP B
 POP D
 POP H
 RET
;

これを使用して
>asm COUT
CP/M ASSEMBLER - VER 2.0
3818
000H USE FACTOR
END OF ASSEMBLY

RunCPM Version 5.3 (CP/M 2.2 60K)

>ddt COUT.HEX
DDT VERS 1.4
NEXT  PC
3818 0000
-I PLMSAMP.HEX
-R
NEXT  PC
3818 0000
-G100

SAVE 38 PLMSAMP.COM とすればCOMファイルが出来る。 動作確認が出来た。


FlashForthの注意点

2021-10-17 09:17:54 | 日記

FlashForthのソースコードをつらつら眺めていると、思わぬ間違いを発見。

FlashForthでは、tosはhigher addressに保存されている。コメントなので動作上は問題ないけれど間違っている。

---ff-xc8.asm---

1529c1529
< ;   the lower address will appear on top of stack
---
> ;   the higher address will appear on top of stack
1543,1544c1543,1544
< ;   SWAP OVER ! CELL+ ! ;
< ;   the top of stack is stored at the lower adrs
---
> ;   SWAP OVER CELL+ ! ! ;
> ;   the top of stack is stored at the higher adrs

 

---ff-pic18.asm---

3458c3458
< ;   the lower address will appear on top of stack
---
> ;   the higher address will appear on top of stack
3470,3471c3470,3471
< ;   SWAP OVER ! CELL+ ! ;
< ;   the top of stack is stored at the lower adrs
---
> ;   SWAP OVER CE+++ ! ! ;
> ;   the top of stack is stored at the higher adrs

 

F83やGForthを含め多くのForthではstack topは lower addressに保存される。
Forth Standard(https://forth-standard.org/standard/core/TwoStore)も以下のように記載されている。

------
2!
( x1 x2 a-addr -- )

Store the cell pair x1 x2 at a-addr, with x2 at a-addr and x1 at the next consecutive cell. It is equivalent to the sequence SWAP OVER ! CELL+ !. 
--------------------

なぜFlashForthは逆なのだろうか。

 


FlashForthのアセンブル(3)

2021-10-13 15:39:55 | 日記

Arduino pro mini上でFlashForthを使ってマルチタスクの実験をしたが、hexファイルの書き込みでインストールしている。

しかしやはりソースからアセンブルしたい。 (FlashForthのアセンブル(2)よりの続き)

 

 なぜかビルドした結果のHexファイルと付属のHexが一致しない。

 なにが起きているのか確認するため、MAPLABの逆アセンブラを使ってみる。

  File > Import > Hex/ELFで該当のHexファイルを読み込み、Windows > Target memory views  > Program Memory

出来た結果はファイルに出せる

 

 

 ビルドしたHexファイルと、付属しているHexファイルを逆アセンブルしてdiffした。

   しかし逆アセンブルした結果が1行目から変。本来JMPは4バイト命令のはずだが。 MAPLABのバグか? 

 

 JMPは4バイトなので、後ろのADD R21, R5などはおかしい。


 無いよりましだけど、あまりあてにならない。(FlashForthを調べるどころではないなあ)


[5]それでもあれやこれや調べると、ff-xc8.asmの以下の「call FETCH」を「rcall FETCH」としてビルドすれば、付属のHexファイルと一致することがわかった。

===ff-xc8.asm 3014行より ここの call FETCHを rcall FETCHに変更========
F_LFA_FETCH:
        call    FETCH      ; c-addr nfa
        cbr     FLAGS2, (1<<fFIND)
findi2:
        sbiw    tosl, 0     ; c-addr nfa
        brne    findi1
        rjmp    findi3
============

これで安心して遊べる。

 


FlashForthのアセンブル(2)

2021-10-13 15:39:55 | 日記

Arduino pro mini上でFlashForthを使ってマルチタスクの実験をしたが、hexファイルの書き込みでインストールしている。

しかしやはりソースからアセンブルしたい。 (FlashForthのアセンブル(1)よりの続き)


[3]ビルドするとエラー
  /home/ishi/.mchp_packs/Microchip/ATmega_DFP/2.4.131/xc8/avr/lib/avr5/memx-const/crtatmega328p.o:../../../../../crt1/gcrt1.S:352: undefined reference to `main'
collect2: error: ld returned 1 exit status

  -->macro-xc8.incにコメントがあった。これをMPLABXに設定
   ;;; - Add linker option "-nostartfiles"

[4]やっとビルド成功。Hexファイルはここに出来る
  ~/MPLABXProjects/FlashForth.X/dist/default/production/FlashForth.X.production.hex

 ところが付属していた328-16MHz-38400.hexとdiffを取ってみるとちょっと違う。
 Cだと最適化で差が出るかもしれないが、アセンブラで差が出るのはおかしい。
 微妙にアドレスがずれているような感じ。

 

FlashForthのアセンブル(3)に続く

 


FlashForthのアセンブル(1)

2021-10-13 15:39:55 | 日記

Arduino pro mini上でFlashForthを使ってマルチタスクの実験をしたが、hexファイルの書き込みでインストールしている。

しかしやはりソースからアセンブルしたい。ソースは付属しているがff-xc8.asm ff-atmega.asm の2種類がある。(GPL3)

以下のような記載があるが、MPLABXは良くわからない。
---https://flashforth.com/atmega.html---
    Install MPLABX and XC8
    Add avr/src/ff-xc8.asm as only source file in a project.
    Select a chip
    Add linker option "-nostartfiles"
    Configure options according to your hardware and preferences in avr/src/config.inc
    Compile
    Get the hex file from dist/default/production/
    Program the chip with avrdude or some other tool using fuses: extended(0xff) high(0xdf) low(0xff) 

そこで手探りでアセンブルを試みた。

環境
 Debian10, MPLAB X IDE v5.45
  (最新と思われる MPLABX IDE v5.50は、なにかおかしい(注1)。インストールを試みたが途中でOSが落ちた)

[1]プロジェクトの作成

ダウンロードしたソースを読み込ませる

字が半分消えているが見えないことはない

[2]ビルドするとエラー。
  #include <config-xc8.inc>で見つからない。
  -->config-xc8.incを登録するところが悪いのか? しかたないので、#include "config-xc8.inc" とソースを変更。

 

FlashForthのアセンブル(2)に続く