page0099
の編集
http://osecpu.osask.jp/wiki/?page0099
[
トップ
] [
編集
|
差分
|
バックアップ
|
添付
|
リロード
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
-- 雛形とするページ --
BracketName
FormattingRules
FrontPage
Fulyn
Fulyn-v2
Fulyn_Samples
Help
InterWiki
InterWikiName
InterWikiSandBox
K
KOR_PIT8254
KWVM.NET
Liva
MANA
MenuBar
OSECPU_FPGA
PG_MANA
PHP
PukiWiki
PukiWiki/1.4
PukiWiki/1.4/Manual
PukiWiki/1.4/Manual/Plugin
PukiWiki/1.4/Manual/Plugin/A-D
PukiWiki/1.4/Manual/Plugin/E-G
PukiWiki/1.4/Manual/Plugin/H-K
PukiWiki/1.4/Manual/Plugin/L-N
PukiWiki/1.4/Manual/Plugin/O-R
PukiWiki/1.4/Manual/Plugin/S-U
PukiWiki/1.4/Manual/Plugin/V-Z
RecentDeleted
SandBox
WikiEngines
WikiName
WikiWikiWeb
YukiWiki
hikalium
hikarupsp
hikarupsp_ELCHNOS
hikarupsp_ELCHNOS_IDE
hikarupsp_FrontEndCode
hikarupsp_WebCPU-VM
hikarupsp_WebCPU-VM_internal
hikarupsp_study_hh4
impressions
impressions0000
jpag0000
jpag0001
jpag0002
jpag0003
jpag0004
jpag0005
lambdalice
mandel59
members
memo0000
memo0001
memo0002
memo0003
memo0004
memo0005
memo0006
memo0007
memo0008
memo0009
memo0010
osask
osecpu4android
page0000
page0001
page0002
page0003
page0004
page0005
page0006
page0007
page0008
page0009
page0010
page0011
page0012
page0013
page0014
page0015
page0016
page0017
page0018
page0019
page0020
page0021
page0022
page0023
page0024
page0025
page0026
page0027
page0028
page0029
page0030
page0031
page0032
page0033
page0034
page0035
page0036
page0037
page0038
page0039
page0040
page0041
page0042
page0043
page0044
page0045
page0046
page0047
page0048
page0049
page0050
page0051
page0052
page0053
page0054
page0055
page0056
page0057
page0058
page0059
page0060
page0061
page0062
page0063
page0064
page0065
page0066
page0067
page0068
page0069
page0070
page0071
page0072
page0073
page0074
page0075
page0076
page0077
page0078
page0079
page0080
page0081
page0082
page0083
page0084
page0085
page0086
page0087
page0088
page0089
page0090
page0091
page0092
page0093
page0094
page0095
page0096
page0097
page0098
page0099
page0100
page0101
page0102
page0103
page0104
page0105
page0106
page0107
page0108
page0109
pagenames
populars
seccamp2013
seccamp2014
seccamp2017
ttwilb
ttwilb-asmi
yao
* OSECPU-ASKA入門 #0016 -(by [[K]], 2013.07.08) ** (0) はじめに -以下の記事はosecpu118dのWindows版を前提にしています。他の版を使っている場合は適宜読み替えてください。 --ちなみに[[page0074]]を読めばrev2の最新版が見つかります。 ~ -もくじ --[[page0087]]: #0010 --[[page0088]]: #0011 --[[page0089]]: #0012 --[[page0093]]: #0013 --[[page0095]]: #0014 --[[page0098]]: #0015 --[[page0099]]: #0016 ** (1) メモリ(配列変数)を使う -OSECPU-ASKAでは配列変数のことを「メモリ」といいます。そしてメモリには型があります。つまりInt32sでもいいけれど、それ以外の型も使えるということです。 -一例として、メモリを使ってちょっとした絵を描いてみます。 #include "osecpu_ask.h" #define L_invader LOCAL(0) LOCALLABELS(1); do { Int32s c:R00, x:R01, y:R02, i:R03; VPtr p:P01; PLIMM(p, L_invader); for (y = 0; y != 16; y++) { for (x = 0; x != 32; x++) { i = y * 32 + x; PALMEM0(32, c, T_UINT1, p, i); c *= 2; // これで0か2になる. ちなみに2は緑色. api_drawPoint(MODE_COL3, c, x, y); } } } DAT_SA(L_invader, T_UINT1, 32 * 16); D1B(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0); D1B(0,0,0,0, 0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0); D1B(0,0,0,0, 0,0,0,0, 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, 0,0,0,0); D1B(0,1,0,0, 0,0,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,1,0); D1B(0,1,0,1, 1,1,1,1, 1,1,0,0, 1,1,1,1, 1,1,1,1, 0,0,1,1, 1,1,1,1, 1,0,1,0); D1B(0,1,0,1, 1,1,1,1, 1,1,0,0, 1,1,1,1, 1,1,1,1, 0,0,1,1, 1,1,1,1, 1,0,1,0); D1B(0,1,0,1, 1,1,1,1, 1,1,0,0, 1,1,1,1, 1,1,1,1, 0,0,1,1, 1,1,1,1, 1,0,1,0); D1B(0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0); D1B(0,0,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0); D1B(0,0,0,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, 0,0,0,0, 0,1,1,1, 1,1,1,1, 1,0,0,0); D1B(0,0,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0); D1B(0,0,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0); D1B(0,0,0,0, 0,0,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,1, 0,0,0,0, 0,0,0,0); D1B(0,0,1,0, 0,0,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,1, 0,0,0,0, 0,1,0,0); D1B(0,0,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,1, 1,1,1,1, 1,1,0,0); D1B(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0); DAT_END(); -これを実行するとインベーダの絵が出てきます。これを例にいろいろと命令を紹介したいと思います。 ~ -最初の#defineは関数を作った時と同じ構文です。こうやって配列データにラベルを付けます。 -データを宣言しているのは、末尾にあるDAT_SA()...DAT_END();の部分です。これは末尾にしなければいけないということはなく、main関数の前においても平気です。 -DAT_SA(ラベル名, 型名, データの個数); という記述になります。 --使える型名は以下の通りです。 ---T_SINT1, T_UINT1 ---T_SINT2, T_UINT2 ---T_SINT4, T_UINT4 ---T_SINT8, T_UINT8 ---T_SINT12, T_UINT12 ---T_SINT16, T_UINT16 ---T_SINT20, T_UINT20 ---T_SINT24, T_UINT24 ---T_SINT28, T_UINT28 ---T_SINT32, T_UINT32 --T_SINT32はInt32sに相当します。 -ここで使っているT_UINT1というのは、1ビットの符号なしの整数型で、0か1しか記憶できません。しかし今回のようなドット絵ではそれで十分なので、これを使いました。 -D1Bというのは、データを記述するための命令でData1Bitの略です。他にD2BやD4Bなどの命令があります。 -結局、これはC言語で言うところの、 int invader[32 * 16] = { 0, 0, 0, 0,... }; -とほぼ同じです。違うのは1ビットの配列だというところだけです。 -注意点としては、総ビット数は8の倍数になっている必要があります。だからT_SINT4を5個、というのはできません(4x5=20で8の倍数になっていない)。ダミーの0を1つ追加して、6個にしてください。 -VPtr p:P01; : --これは、変数pの宣言で、P01レジスタを割り当てています。Pxxレジスタはポインタレジスタで、このように配列データを指し示すためのものです。なお、P00はリザーブされているので、P01からP27までを自由に使っていくことになります。 --RxxはいつもInt32s型でしたが、PxxはいつもVPtr型になります(void-pointerの略です)。 -PLIMM(p, L_invader); : --この命令で p = L_invader; になります。こうやってPxxレジスタに入れないと、PALMEM0命令でデータを読めないので、これをやっています。 -PALMEM0(32, c, T_UINT1, p, i); --C言語風に言えば、 c = p[i]; ということです。 --最初の32は「この処理を32ビットでおこなえ」という意味で、まあ深く考えずいつも32にしておくことをお勧めします。 --T_UINT1はpの型です。iはレジスタ変数である必要があって、定数や式であってはいけません。 --なおMEM0は「メモ」ではなく、「メム・ゼロ」です。つまりオーではなくゼロなので、注意してください。 -do { ... } の末尾にapi_end();を置いてもいいですが、置かなくても大丈夫です。なぜなら間違ってDAT_SA()命令を実行してしまったとしても、何も有害なことは起きずに、DAT_END()のところまで読み飛ばされるからです。 ** (2) メモリに書き込む&mallocを使う -以下のプログラムは、999までの素数を表示するプログラムです。 #include "osecpu_ask.h" do { VPtr p:P01; Int32s i:R00, j:R01, v:R02; // 初期化. api_malloc(p, T_UINT1, 1000); v = 0; for (i = 0; i != 1000; i++) { PASMEM0(32, v, T_UINT1, p, i); } // 倍数に印をつけていく. v = 1; for (i = 2; i != 1000; i++) { for (j = i * 2; ; j += i) { if (j >= 1000) break; PASMEM0(32, v, T_UINT1, p, j); } } // 素数の表示. for (i = 2; i != 1000; i++) { PALMEM0(32, v, T_UINT1, p, i); if (v == 0) { api_putStringDec('\1 ', i, 3, 1); } } } -初期値をDAT_SA()構文で設定する必要がない場合、上記の例のようにapi_malloc()でメモリを確保できます。 -PASMEM0()はPALMEM0の読み書きを逆転させたもので、メモリに書くことができます。定数や式の値を書き込むことはできないので、一度レジスタに格納してからPASMEM0してください。 -しかし当然ながら、型に収まらない値を書いてはいけません。それはセキュリティ例外になります(ダメな例:T_UINT1なメモリに2を書こうとするとか)。 --これはセキュリティ上の問題というよりも単なるバグというべきだと思いますが、しかしプログラマは値を確実にメモリに保存したと思ったのに、実は保存できていないわけですから(このメモリを読みこんだらデータが化けてしまう)、意図せずに情報が失われた!というわけで、まあセキュリティ上の問題といえなくもないです。 ---- -ここで少しセキュリティ上のポイントを紹介しておこうと思います。 -(a) このプログラムで、初期化処理のPASMEM0をコメントアウトしてしまったらどうなるでしょうか。そうすると、表示処理のところで、初期化されていないメモリを一部読むことになるのですが、これはもちろんやってはいけないことです。OSは他のアプリが解放したメモリを、初期化せずに渡してきたかもしれず、そうなれば他のアプリのデータを盗み見ることが可能になってしまいます。ということで、初期化されていないメモリを読む行為はOSECPU-VMでは許されません。ということでセキュリティ例外になります。 -(b) if (j >= 1000) break; の部分をコメントアウトしたらどうなるでしょうか。そうです、確保した領域をはみ出してアクセスしてしまいます。これもセキュリティ例外になります。 ** (3) つづく -(工事中) * こめんと欄 #comment
タイムスタンプを変更しない
* OSECPU-ASKA入門 #0016 -(by [[K]], 2013.07.08) ** (0) はじめに -以下の記事はosecpu118dのWindows版を前提にしています。他の版を使っている場合は適宜読み替えてください。 --ちなみに[[page0074]]を読めばrev2の最新版が見つかります。 ~ -もくじ --[[page0087]]: #0010 --[[page0088]]: #0011 --[[page0089]]: #0012 --[[page0093]]: #0013 --[[page0095]]: #0014 --[[page0098]]: #0015 --[[page0099]]: #0016 ** (1) メモリ(配列変数)を使う -OSECPU-ASKAでは配列変数のことを「メモリ」といいます。そしてメモリには型があります。つまりInt32sでもいいけれど、それ以外の型も使えるということです。 -一例として、メモリを使ってちょっとした絵を描いてみます。 #include "osecpu_ask.h" #define L_invader LOCAL(0) LOCALLABELS(1); do { Int32s c:R00, x:R01, y:R02, i:R03; VPtr p:P01; PLIMM(p, L_invader); for (y = 0; y != 16; y++) { for (x = 0; x != 32; x++) { i = y * 32 + x; PALMEM0(32, c, T_UINT1, p, i); c *= 2; // これで0か2になる. ちなみに2は緑色. api_drawPoint(MODE_COL3, c, x, y); } } } DAT_SA(L_invader, T_UINT1, 32 * 16); D1B(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0); D1B(0,0,0,0, 0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0); D1B(0,0,0,0, 0,0,0,0, 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, 0,0,0,0); D1B(0,1,0,0, 0,0,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,1,0); D1B(0,1,0,1, 1,1,1,1, 1,1,0,0, 1,1,1,1, 1,1,1,1, 0,0,1,1, 1,1,1,1, 1,0,1,0); D1B(0,1,0,1, 1,1,1,1, 1,1,0,0, 1,1,1,1, 1,1,1,1, 0,0,1,1, 1,1,1,1, 1,0,1,0); D1B(0,1,0,1, 1,1,1,1, 1,1,0,0, 1,1,1,1, 1,1,1,1, 0,0,1,1, 1,1,1,1, 1,0,1,0); D1B(0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0); D1B(0,0,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0); D1B(0,0,0,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, 0,0,0,0, 0,1,1,1, 1,1,1,1, 1,0,0,0); D1B(0,0,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0); D1B(0,0,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0); D1B(0,0,0,0, 0,0,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,1, 0,0,0,0, 0,0,0,0); D1B(0,0,1,0, 0,0,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,1, 0,0,0,0, 0,1,0,0); D1B(0,0,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,1, 1,1,1,1, 1,1,0,0); D1B(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0); DAT_END(); -これを実行するとインベーダの絵が出てきます。これを例にいろいろと命令を紹介したいと思います。 ~ -最初の#defineは関数を作った時と同じ構文です。こうやって配列データにラベルを付けます。 -データを宣言しているのは、末尾にあるDAT_SA()...DAT_END();の部分です。これは末尾にしなければいけないということはなく、main関数の前においても平気です。 -DAT_SA(ラベル名, 型名, データの個数); という記述になります。 --使える型名は以下の通りです。 ---T_SINT1, T_UINT1 ---T_SINT2, T_UINT2 ---T_SINT4, T_UINT4 ---T_SINT8, T_UINT8 ---T_SINT12, T_UINT12 ---T_SINT16, T_UINT16 ---T_SINT20, T_UINT20 ---T_SINT24, T_UINT24 ---T_SINT28, T_UINT28 ---T_SINT32, T_UINT32 --T_SINT32はInt32sに相当します。 -ここで使っているT_UINT1というのは、1ビットの符号なしの整数型で、0か1しか記憶できません。しかし今回のようなドット絵ではそれで十分なので、これを使いました。 -D1Bというのは、データを記述するための命令でData1Bitの略です。他にD2BやD4Bなどの命令があります。 -結局、これはC言語で言うところの、 int invader[32 * 16] = { 0, 0, 0, 0,... }; -とほぼ同じです。違うのは1ビットの配列だというところだけです。 -注意点としては、総ビット数は8の倍数になっている必要があります。だからT_SINT4を5個、というのはできません(4x5=20で8の倍数になっていない)。ダミーの0を1つ追加して、6個にしてください。 -VPtr p:P01; : --これは、変数pの宣言で、P01レジスタを割り当てています。Pxxレジスタはポインタレジスタで、このように配列データを指し示すためのものです。なお、P00はリザーブされているので、P01からP27までを自由に使っていくことになります。 --RxxはいつもInt32s型でしたが、PxxはいつもVPtr型になります(void-pointerの略です)。 -PLIMM(p, L_invader); : --この命令で p = L_invader; になります。こうやってPxxレジスタに入れないと、PALMEM0命令でデータを読めないので、これをやっています。 -PALMEM0(32, c, T_UINT1, p, i); --C言語風に言えば、 c = p[i]; ということです。 --最初の32は「この処理を32ビットでおこなえ」という意味で、まあ深く考えずいつも32にしておくことをお勧めします。 --T_UINT1はpの型です。iはレジスタ変数である必要があって、定数や式であってはいけません。 --なおMEM0は「メモ」ではなく、「メム・ゼロ」です。つまりオーではなくゼロなので、注意してください。 -do { ... } の末尾にapi_end();を置いてもいいですが、置かなくても大丈夫です。なぜなら間違ってDAT_SA()命令を実行してしまったとしても、何も有害なことは起きずに、DAT_END()のところまで読み飛ばされるからです。 ** (2) メモリに書き込む&mallocを使う -以下のプログラムは、999までの素数を表示するプログラムです。 #include "osecpu_ask.h" do { VPtr p:P01; Int32s i:R00, j:R01, v:R02; // 初期化. api_malloc(p, T_UINT1, 1000); v = 0; for (i = 0; i != 1000; i++) { PASMEM0(32, v, T_UINT1, p, i); } // 倍数に印をつけていく. v = 1; for (i = 2; i != 1000; i++) { for (j = i * 2; ; j += i) { if (j >= 1000) break; PASMEM0(32, v, T_UINT1, p, j); } } // 素数の表示. for (i = 2; i != 1000; i++) { PALMEM0(32, v, T_UINT1, p, i); if (v == 0) { api_putStringDec('\1 ', i, 3, 1); } } } -初期値をDAT_SA()構文で設定する必要がない場合、上記の例のようにapi_malloc()でメモリを確保できます。 -PASMEM0()はPALMEM0の読み書きを逆転させたもので、メモリに書くことができます。定数や式の値を書き込むことはできないので、一度レジスタに格納してからPASMEM0してください。 -しかし当然ながら、型に収まらない値を書いてはいけません。それはセキュリティ例外になります(ダメな例:T_UINT1なメモリに2を書こうとするとか)。 --これはセキュリティ上の問題というよりも単なるバグというべきだと思いますが、しかしプログラマは値を確実にメモリに保存したと思ったのに、実は保存できていないわけですから(このメモリを読みこんだらデータが化けてしまう)、意図せずに情報が失われた!というわけで、まあセキュリティ上の問題といえなくもないです。 ---- -ここで少しセキュリティ上のポイントを紹介しておこうと思います。 -(a) このプログラムで、初期化処理のPASMEM0をコメントアウトしてしまったらどうなるでしょうか。そうすると、表示処理のところで、初期化されていないメモリを一部読むことになるのですが、これはもちろんやってはいけないことです。OSは他のアプリが解放したメモリを、初期化せずに渡してきたかもしれず、そうなれば他のアプリのデータを盗み見ることが可能になってしまいます。ということで、初期化されていないメモリを読む行為はOSECPU-VMでは許されません。ということでセキュリティ例外になります。 -(b) if (j >= 1000) break; の部分をコメントアウトしたらどうなるでしょうか。そうです、確保した領域をはみ出してアクセスしてしまいます。これもセキュリティ例外になります。 ** (3) つづく -(工事中) * こめんと欄 #comment
テキスト整形のルールを表示する