as-5. サブルーチン呼び出しの
メカニズム
1
金子邦彦
68000 アセンブラプログラミング)
URL: https://www.kkaneko.jp/cc/as/index.html
種々のオペランド
move.w #200,%d2
/* #200 10進数. d2 の上位バイトは変化しない */
move.l #0x01,%d1
/* #0x01 16進数. d0 0x00000000 がセットされる */
.equ BUFFER_SIZE 100
move.w #BUFFER_SIZE,%d2
move.w #0x2700,%sr
/* 割り込み禁 */
move.l %d0,%d1
move.l %d0,(%a0)
/* アドレスレジス a0 がポイントするメモリに転送(a0は変化しない) */
move.b #0x00,(%a0)
/* アドレスレジスタ a0 がポイントするメモリに 0 をセット(.b なので1バイ) */
オペランド
「操作」すべきデータの
対象がかかれている部分
割り込み禁止の
決まり文句
データレジスタ直接
(data register direct)
例:
move.w %D0, %D3
記法 %Dn
12345678
ドレスバス
データバス
制御系
Control Unit
+命令長
レジスタ
Registers
R/W
データレジスタ D3
D0 の下位1ワードが
入る
move.w %D0, %D3 の命令実行
D0
????5678
D3
.w」とあるので,下
位1ワードを使う
アドレスレジスタ直接
(address register direct)
例:
move.l %A6, %A0
記法 %An
FF008800
ドレスバス
データバス
制御系
Control Unit
+命令長
レジスタ
Registers
R/W
アドレスレジスタ A0
A6 が入る
move.l %A6, %A0 の命令実行
A6
FF008800
A0
.l」とあるので,
全てを使う
アブソリュート
(absolute)
例:
.equ ADDR 0xffff00
move.w ADDR,%D0
move.w %D1,ADDR
メモリアドレスの値を指定
アドレスバス
データバス
制御系
Control Unit
+命令長
レジスタ
Registers
R/W
D0 の下位1ワード
に入る
move.w ADDR,%D0 の命令実行
????A000
D0
0xffff00
メモリからの
読み出し
アドレスバス
データバス
制御系
Control Unit
+命令長
レジスタ
Registers
R/W
D1 の下位1ワード
がメモリに書き込まれ
move.w %D1, ADDR の命令実行
????????
D1
0xffff00
メモリへの
書き込み
イミディエート (immediate)
例:
move.w #0x0040, %D0
記法 #data
????????
アドレスバス
データバス
制御系
Control Unit
+命令長
レジスタ
Registers
R/W
データレジスタ D0
0040 が入る
move.w #0x0040, %D0 命令実行では
D0
????0040
0040
イミディエート
.equ ADDR 0x00ffff00
move.w #0x1000,%d0
move.l #ADDR,%a0
値を扱う
アブソリュート
.equ ADDR 0xffff00
move.w ADDR,%d0
メモリの読み出し,書き込み
レジスタ間接
(register indirect)
例:
move.w (%A0), %D0
move.w %D3, (%A1)
記法 (%An)
(%A0) (%A7) は可. (%D0) などは許されない
アドレスバス
データバス
制御系
Control Unit
+命令長
レジスタ
Registers
R/W
D0 の下位1ワード
に入る
move.w (%A0),%D0 の命令実行
????????
D0
????????
A0
メモリからの
読み出し
アドレスバス
データバス
制御系
Control Unit
+命令長
レジスタ
Registers
R/W
D3 の下位1ワード
がメモリに書き込まれ
move.w %D3, (%A1) の命令実行
????????
D3
????????
A1
メモリへの
書き込み
レジスタ直接とレジスタ間接の違い
レジスタ直接
move.l #0,%D0
move.l %D2,%D0
d0 が書き換わる
レジスタ間接
.equ ADDR 0xffff00
move.l #ADDR,%A0
move.w %D0,(%A0)
A0 に入っているメモリアドレス
使って,データの書き込みが行われる
種々のオペランド(その2)
move.w %sr,-(%sp)
/* システムスタックエリアに sr の中身をプッシュ */
move.w (%sp)+,%sr
/* システムスタックエリアか sr 中身をポップ */
move.w #0x0010, 20(%A0)
/* A0 20 足したメモリアドレスに, 0x0010 を書き込む */
move.w ※※,-(%sp)
move.w (%sp)+,※※
システムスタックエリアへの
プッシュとポップの決まり文句
ポストインクリメント・レジスタ間接
例: move.w (%a0)+, %d0
a0 0x00002000 が入っているとしよう
move.w (%a0), %d0 と同様の処理が行われた後
に,自動的に a0 に2が足される. a0 の値は,
0x00002002 になる
.b なら1足される
.w」なら2足され
.l」なら4足される
プリデクリメント・レジスタ間接
例: move.w -(%a0), %d0
a0 0x00002000 が入っているとしよう
最初に,自動的に a0 から2が引かれる. a0 の値
は, 0x00001ffe になる.その後で,「move.w
(%a0), %d0 と同様の処理が行われる
.b なら1引かれる
.w」なら2引かれる
.l」なら4引かれる
ディスプレースメント付きレジスタ間接
例: move.l 0x20(%a0), %d0
a0 0x00002000 が入っているとしよう
0x00002000 0x20 が足されて,メモリアドレス
0x00002020 から,4バイト読み込まれて,d0
入る
数値(%レジスタ名)
例: lea 0x2000, %a0 /* a0 0x2000 をセット*/
move.b 4(%a0), %d0 /* 0x2004 から1バイト読みこみ */
move.w 4(%a0), %d0 /* 0x2004 から2バイト読みこみ */
move.l 4(%a0), %d0 /* 0x2004 から4バイト読みこみ */
構造体
例: 住所録
名前 20バイト
身長 2バイト move.w 20(%a0), %d0
年齢 1バイト move.b 22(%a0), %d0
性別 1バイト move.b 23(%a0), %d0
全体で 24バイトのデータ
20
22
23
68000 のアドレッシングモード
モード 記法
データレジスタ
データレジスタ
%Dn %D0, %D1, %D7
アドレスレジスタ
直接
アドレスレジスタ
%An %A0, %A1, %A7
アブソリュート
メモリアドレス
xx 0x00ffffff00, ADDR
レジスタ間接
括弧付き
(%An)
(%A0), (%A1), (%A7)
ポストインクリメン
ト・レジスタ間接
後ろに+付き
(%An)+
(%A0)+, (%A1)+, (%A7)+
プリデクリメント・
レジスタ間接
前に 付き
-(%An)
-(%A0), -(%A1), -(%A7)
ディスプレースメント
付きレジスタ間接
前に数値付き
d16(%An) 20(%A0),
BOTTOM(%A0)
イミディエート
数値
#data
#3, #0x2000, #ADDR
アドレッシングモード
命令の種類によって,書くことができるアドレッシ
ングモードに制限がある
例: cmp 命令では
cmp.w (%a2)+, %d2 は動く
cmp.w %d2, (%a2)+ 動かない
配布資料「37 CMP」のページを見よ
CMP.{.B/.W/.L} <ea>, Dn
とあるのは,2番目のオペランドにデータレジ
スタしか書けないという意味
C 言語での関数呼び出し
例題1
文字列の長さを数える関数
関数の
本体
関数名
関数の入力(パラメータ)
例題1.関数呼び出し(1)
1つの関数
1つの関数
関数呼び出し
プログラム実行は
メイン関数から始まる
戻り
変数
変数
変数名
データ(数値や文字)を入れるもの
英数字かアンダーバー(_)で作られる
最初の文字には数字は使えない
大文字と小文字を区別する
変数 i
変数 i をメモリエリア中に確保
変数len をメモリエリア中に確保
ここで使用
変数は2種類使っている
2バイトデータ(整数)
を扱う short int
メモリアドレスを扱う
char *
short int が2バイトになる
という決まりは無いが,
2バイトになっていることが
多い
変数は2種類使っている
2バイトデータ(整数)
を扱う short int
メモリアドレスを扱う
char *
short int が2バイトになる
という決まりは無いが,
2バイトになっていることが
多い
関数の入力(パラメータ)
この時点では
str 文字列の先頭
アドレス
char *
s 文字列の先頭
アドレス + 17
char *
len
17
int
実際のメモリの中身
str
s
str 文字列の先頭
アドレス
char *
s 文字列の先頭
アドレス + 17
char *
len
17
int
len
len s があるメモリエリアは,関数 stringlength 実行のために
ダイナミックに確保されたエリア
(参考)実際のメモリの中身
文字列データは,len, s などとは別の
メモリエリアに入っている
関数呼び出し
1. 制御の流れ
2. 関数のパラメータ
3. 関数内のローカル変数
4. 関数からの返り値
68000 アセンブラ言語での
関数呼び出し
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
C言語
68000アセンブラ言語
等価
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
C言語
68000アセンブラ言語
関数呼び出し
(文字列の先頭アドレスを関数に渡す)
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
C言語
68000アセンブラ言語
リターン
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
C言語
68000アセンブラ言語
関数での処理結果を,
呼び出し側に引き渡す
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
C言語
68000アセンブラ言語
関数実行のために,メモリ
エリアをダイナミックに確保
(関数実行の終わりで解放)
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
C言語
68000アセンブラ言語
「スタックエリア」の確保と,
そのメモリアドレスを A7 にセット
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
C言語
68000アセンブラ言語
(参考) BSVC での実行
最初に PC の値を手動でセット
メイン関数から開するように)
(1) システムスタックエリアの
確保と,A7 へのセット
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
0x4000 バイト (16進数)
のメモリエリア確保
例えば、0x0000005e 0x00000405e
この場合ラベル
SYS_STK_TOP
0x0000405e を指す
A7 0x0000405e
をセット
A7 は「スタックポイン」のこと
CPU内のレジスタ)である.
A7 0x0000405e
をセット
メモリ
システム
スタックエリア
プログラム実行の最初の時点で、
A7に「システムスタックエリア」の末尾+
のメモリアドレスをセットしておく
A7のポイント先
0x4000 バイトの
メモリエリア
0x0000005e
0x00000405e
(2) 関数のパラメータを,シス
テムスタックエリアにプッシュ
(push)
スタック
プッシュ (push)
ポップ (pop)
すでに
入っていた
データ
積み重なる
ように入る
すでに
入っていた
データ
一番最後に入った
データが先に出る
スタック
push 2
push 3
push 4
1
1
1
1
2
2
2
3
3
4
スタックとキュー
スタックは,データの後入れ・先出し(last in
first out)を行う
スタックの push 1, push 2, push 3, pop, pop
は,1番目のpop3が,2番目のpop2が出て,
1は残っている.
キューは,データの先入れ・先出しを行う.
メモリ
システム
スタックエリア
A7
ポイント先
(空なので「全体の末尾」
+1をポイントしている)
システムスタックエリアに
「4バイト」のデータを push
説明上、
最初は空
とする
push
push
A7
ポイント先
A0 の中身
4バイトデータ)
4減る
例) move.l %a0,-(%a7)
(3) 関数呼び出しとリターン
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
jsr stringlength
サブルーチン呼び出し
jsr = jump subroutine)
分岐が行われるとともに,
「戻り番地」が保存される
保存先
システムスタックエリア
メモリ
システム
スタックエリア
A7
ポイント先
(空なので「全体の末尾」
+1をポイントしている)
システムスタックエリアに
戻り番地 push
push
push
A7
ポイント先
A0 の中身
4バイトデータ)
4減る
例) jsr stringlength
戻り番地
命令フェッチでは
アドレスバス
データバス
R/W
命令レジスタ
Instruction Register
制御系
Control Unit
プログラムカウンタ
Program Counter
+命令長
プログラムカウンタ
を使用
命令が届く
jsr stringlength
0x4ebaffc0
命令フェッチでは
アドレスバス
データバス
R/W
命令レジスタ
Instruction Register
制御系
Control Unit
グラカウン
Program Counter
+命令長
ffc0 は,
分岐先のメモリアドレ
スを表している
0x4ebaffc0
命令デコードでは
アドレスバス
データバス
命令デコーダ
Instruction Decoder
制御系
Control Unit
プログラムカウンタ
Program Counter
+命令長
まず,プログラムカウンタが
jsr stringlengthの次をポイ
ントするように書き換わる
R/W
0x4ebaffc0
jsr stringlength
addq.l #4,%a7
アドレスバス
データバス
制御系
Control Unit
+命令長
R/W
命令実行では (1/2)
プログラムカウンタ
Program Counter
現在のプログラム
カウンタの値
(=戻り番地)をシ
ステムスタックエリ
アに push
A7 が4減る)
戻り番地
アドレスバス
データバス
制御系
Control Unit
+命令長
R/W
命令実行では (2/2)
プログラムカウンタ
Program Counter
メモリ
プログラムカウンタ
にサブルーチン
stringlength の先頭
アドレスが入る
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
rts
rts = return subroutine)
システムスタックエリア
から4バイト pop し,
プログラムカウンタに上書き
rts では,戻り先がプログラム中のどこにも
書かれていない.戻り先は,ダイナミックに
保存されるから.
命令フェッチでは
アドレスバス
データバス
R/W
命令レジスタ
Instruction Register
制御系
Control Unit
プログラムカウンタ
Program Counter
+命令長
プログラムカウンタ
を使用
命令が届く
rts
0x4e75
命令デコードでは
アドレスバス
データバス
命令デコーダ
Instruction Decoder
制御系
Control Unit
プログラムカウンタ
Program Counter
+命令長
プログラムカウンタが
rts」の次をポイントするよう
に書き換わる
R/W
0x4e75
アドレスバス
データバス
制御系
Control Unit
+命令長
R/W
rts の命令実行では
プログラムカウンタ
Program Counter
システムスタックエリアか
ら4バイト pop され,プロ
グラムカウンタに上書き.
(このとき A7 が4増える)
戻り番地
(4) 関数実行の始めに,メモリ
エリアをダイナミックに確保
(終わりで解放)
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
確保
解放
システムスタックエリア内に
8バイトを確保せよ
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
確保
解放
A6 をシステムスタックエリア
push (A6 の保存)
A6 A7
(A7 の現時点の値の記録)
A7 A7 8
(メモリエリアの確保)
A7 A6
システムスタックエリアから
pop して,A6 に入れる
(A6, A7 が元に戻る)
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
確保
A6 をシステムスタックエリア
push (A6 の保存)
A6 A7
(A7 の現時点の値の記録)
A7 A7 8
(メモリエリアの確保)
link
A6: 0x00000000
A7: 0x00004056
戻り番地
パラメータ
システムスタックエリアの中身(一部)
link
A6: 0x00004052
A7: 0x0000404a
-4
-4-8
A6
メモリエリア
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
確保
link
A6: 0x00004052
メモリエリア
メモリエリア内の2つのデータ
1.2バイトデータ
(長さを数える)
-2(%a6)
2.メモリアドレス
(文字列データの各文字を
ポイントする)
-6(%a6)
(5) 関数内での
パラメータの使用
関数のパラメータの渡し方
1. レジスタを使用
2. システムスタックエリアを使用
こちらを説明
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
A0 の値をプッシュ
(文字列の先頭アドレス
0x0000004c push
link
A6: 0x00004052
プッシュした値を,
ここで読み出し
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
A0 の値をプッシュ
(文字列の先頭アドレス
0x0000004c をプッシュ)
プッシュした値を,
ここで読み出し
pop しても仕方が無いので,
A7 4 足すだけ
(6) 関数での処理結果の,
呼び出し側への引渡し
.data
str1:
.ascii "My Name is David!¥0"
SYS_STK:
.ds.b 0x4000
SYS_STK_TOP:
.text
stringlength:
link.w %a6,#-8
clr.w -2(%a6)
move.l 8(%a6),-6(%a6)
start1:
move.l -6(%a6),%a0
cmp.b #0,(%a0)
beq break1
addq.l #1,-6(%a6)
addq.w #1,-2(%a6)
bra start1
break1:
move.w -2(%a6),%a0
move.l %a0,%d0
unlk %a6
rts
main:
lea.l SYS_STK_TOP,%a7
lea.l str1,%a0
move.l %a0,-(%a7)
jsr stringlength
addq.l #4,%a7
.dc.w 0x4848
stop #0
.end
C言語
68000アセンブラ言語
関数での処理結果を,
呼び出し側に引き渡す
(データレジスタ D0 を使用)
関数での処理結果の,
呼び出し側への引渡し
1. レジスタ
2. 所定のメモリアドレスに書き込み
3. 関数へのパラメータ(システムスタックエ
リア内)を書き換える