SDCCをZ80で使用する場合、Cのmainプログラムが開始する前及び、終了した後の
動作をプログラムしておく必要があります。通常はOSが何気なくやっていますが、組み
込み用ではお膳立てが必要になってきます。
このお膳立てプログラムが、 crt0.s(ソースの場合)ですが中身をみるといろいろ
やってる(スタックポインターの初期化など)ので、自分用の作るのがいいかもしれません。
通常のコンパイルでは、このcrt0.sが自動的にリンクされます。
ちなみに、デフォルトのcrt0.sは下記のところに置いてあります。
$ cd /usr/local/share/sdcc/lib/src/z80/
$ ls
README crt0.s divunsigned.s modsigned.s putchar.s
__sdcc_call_hl.s crtenter.s heap.s modunsigned.s setjmp.s
__sdcc_call_iy.s divmixed.s memmove.s mul.s strcpy.s
abs.s divsigned.s modmixed.s mulchar.s strlen.s
自分用のcrt0.sをmycrt.asmとして作成します。
作成条件として下記のとおりです。
1、開始アドレス 0x0000よりスタートし、0x0100へジャンプ(コンパイル時指定)
2、初期設定プログラムとして 0x0100から配置(コンパイル時指定)
3、スタックポインター 0x8000 に設定 (0x4000~0x7FFFまでがRAMとして仮定)
4、main()から戻ってきたら即、halt実行(Z80停止)
mycrt.asmは次のようになります。
.module mycrt
.globl _main
.area _HEADER (ABS)
.org 0
jp init
.area _CODE
init:
ld sp,#0x8000
call _main
halt
このmycrt.asmをアセンブルして、リンク用オブジェクトを作成します。
$ sdasz80 -o mycrt.o mycrt.asm
確認用のCプログラムを作成します。
単に戻り値を返すだけのmain()を作成します。
int main(void)
{
return 0;
}
test.cとして保存して、コンパイルします。
$ sdcc test.c -mz80 --code-loc 0x0100 --no-std-crt0 -Wlmycrt.o
コンパイルオプション --code-loc 0x0100 で コード領域を 0x0100から配置
コンパイルオプション --no-std-crt0 で デフォルトのcrt0.oをリンクしない
コンパイルオプション -Wlmycrt.o で 自分用のmycrt.oをリンク
アセンブルリストを確認
$ more test.asm
--------------------------------------------------------
; File Created by SDCC : free open source ANSI-C Compiler
; Version 3.5.0 #9253 (Dec 10 2015) (Linux)
; This file was generated Sun Dec 13 09:17:21 2015
;--------------------------------------------------------
.module test
.optsdcc -mz80
;--------------------------------------------------------
; Public variables in this module
;--------------------------------------------------------
.globl _main
;--------------------------------------------------------
; special function registers
;--------------------------------------------------------
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
.area _DATA
;--------------------------------------------------------
; ram data
;--------------------------------------------------------
.area _INITIALIZED
;--------------------------------------------------------
; absolute external ram data
;--------------------------------------------------------
.area _DABS (ABS)
;--------------------------------------------------------
; global & static initialisations
;--------------------------------------------------------
.area _HOME
.area _GSINIT
.area _GSFINAL
.area _GSINIT
;--------------------------------------------------------
; Home
;--------------------------------------------------------
.area _HOME
.area _HOME
;--------------------------------------------------------
; code
;--------------------------------------------------------
.area _CODE
;test.c:1: int main(void)
; ---------------------------------
; Function main
; ---------------------------------
_main::
;test.c:3: return 0;
ld hl,#0x0000
ret
.area _CODE
.area _INITIALIZER
.area _CABS (ABS)
コンパイルされたhexコードで確認してみます。
$ more test.ihx
:03000000C3000139
:0B010000310080CD070176210000C90E
:00000001FF
ちょっとわかりずらいのでコードを抜き出してみると
0000: C30001 ;JP 0x0100
0100: 310080 ;LD SP,0x8000
0103: CD0701 ;CALL 0x0107
0106: 76 ;HALT
0107: 210000 ;LD HL,0x0000
010A: C9 ;RET
とりあえず意図したコードになっていましたwww
main()のreturnの戻り値は HLレジスターに設定されるようです。