|
1: 2004-12-15 (水) 18:03:19 |
| + | * wiki版のintroシリーズ no.0002 |
| + | -(by [[K]], 2004.12.15) |
| + | -これはC言語でもASKAでもnaskでもとにかくごちゃまぜでintroしてしまおうというこころみ。 |
| + | --これは[[guide/wintro0001]]の続きなので、それを読んでない人はそれを読んでね。 |
| + | ---最初から読みたい人は[[guide/ASKA]]や[[guide/nask]]からどうぞ。 |
| + | --C言語をやる人はintroaを読むといいでしょう。ここのプログラムは、introaと同一内容です。 |
| + | -質問とか感想とかはこめんと欄にレッツゴー。 |
| | | |
| + | *** countdown |
| + | -C版:"cntdwnc1.c" [osa_dir2では バイト] |
| + | /* "cntdwnc1.c":countdwnをC言語で記述した例 */ |
| + | /* stack:20k malloc:1k */ |
| + | |
| + | #include <guigui00.h> |
| + | |
| + | #define AUTO_MALLOC 0 |
| + | |
| + | void setdec3(int i, char *s); |
| + | |
| + | void OsaskMain() |
| + | { |
| + | struct LIB_WINDOW *window; |
| + | struct LIB_TEXTBOX *wintitle, *textbox; |
| + | int count; |
| + | static char msg[] = "000"; |
| + | |
| + | /* ライブラリ初期化 */ |
| + | lib_init(AUTO_MALLOC); |
| + | |
| + | /* ウィンドウオープン */ |
| + | window = lib_openwindow(AUTO_MALLOC, 0x0200, 18 * 8, 1 * 16); |
| + | wintitle = lib_opentextbox(0x1000, AUTO_MALLOC, 0, 8, 1, 0, 0, window, 0x00c0, 0); |
| + | textbox = lib_opentextbox(0x0000, AUTO_MALLOC, 0, 3, 1, 56, 0, window, 0x00c0, 0); |
| + | lib_putstring_ASCII(0x0000, 0, 0, wintitle, 0, 0, "cntdwnc1"); |
| + | |
| + | /* メインループ */ |
| + | for (;;) { |
| + | for (count = 100; count > 0; count--) { |
| + | setdec3(count, msg); |
| + | lib_putstring_ASCII(0x0000, 0, 0, textbox, 0, 0, msg); |
| + | lib_waitsignaltime(0x0007, 0, 0, 0, 1, 0); /* 1秒待つ */ |
| + | } |
| + | lib_putstring_ASCII(0x0000, 0, 0, textbox, 0, 0, "GO!"); |
| + | lib_waitsignaltime(0x0007, 0, 0, 0, 10, 0); /* 10秒待つ */ |
| + | } |
| + | } |
| + | |
| + | void setdec3(int i, char *s) |
| + | /* 注意:このルーチンでは、0~999までしか扱えない */ |
| + | { |
| + | s[0] = '0' + i / 100; i %= 100; |
| + | s[1] = '0' + i / 10; |
| + | s[2] = '0' + i % 10; |
| + | if (s[0] == '0') { |
| + | s[0] = ' '; |
| + | if (s[1] == '0') |
| + | s[1] = ' '; |
| + | } |
| + | return; |
| + | } |
| + | |
| + | |
| + | -''以下未完成'' |
| + | |
| + | |
| + | -ASKA版:"colora1.ask" [osa_dir2では 240バイト] |
| + | /* "colora1.ask":colorをASKAで記述した例 */ |
| + | /* stack:20k malloc:0k */ |
| + | segment CODE(USE32, PARA); default(code == CODE); asmout("[FILE 'colora1.ask']"); |
| + | asmout("GLOBAL _OsaskMain"); |
| + | |
| + | void setdec2(); /* ALをDS:ESIに書き込む */ |
| + | |
| + | void _OsaskMain() |
| + | { |
| + | asmout("MOV EBX,data.init"); CALL(0xc7, 0); |
| + | |
| + | unsigned char i == AL, x == CL, y == CH; |
| + | i = 0; |
| + | do { |
| + | asmout("MOV EBX,data.putstr"); |
| + | x = 10; |
| + | y = i; |
| + | y /= 2; |
| + | if (CF == 0) |
| + | x = 0; /* yが割り切れたらxは0に */ |
| + | [EBX + 8] = x; |
| + | [EBX + 12] = y; |
| + | [EBX + 20] = i; |
| + | LEA(ESI, [EBX + 42]); |
| + | setdec2(); |
| + | CALL(0xc7, 0); |
| + | i++; |
| + | } while (i < 16); |
| + | |
| + | asmout("MOV EBX,data.sleep"); CALL(0xc7, 0); |
| + | } |
| + | |
| + | void setdec2() |
| + | { |
| + | char *s == DS:ESI; |
| + | PUSH(ECX); |
| + | PUSH(EAX); |
| + | CL = 10; |
| + | AH = 0; |
| + | DIV(CL); /* AX / CL = AL ... AH */ |
| + | EAX |= 0x3030; /* '00' */ |
| + | if (AL == 0x30) |
| + | AL = 0x20; /* ' ' */ |
| + | s[0] = AL; |
| + | s[1] = AH; |
| + | POP(EAX); |
| + | POP(ECX); |
| + | return; |
| + | } |
| + | |
| + | asmout("[SECTION .data]"); |
| + | |
| + | void data() |
| + | { |
| + | ALIGNB(4); |
| + | init: |
| + | asmout("DD 0x0004, data.work"); /* lib_init */ |
| + | asmout("DD 0x0020, data.window, 0x0200, 20 * 8, 8 * 16"); /* lib_openwindow */ |
| + | asmout("DD 0x0028, 0x1000, data.wintitle, 0, 7, 1, 0, 0, data.window, 0x00c0, 0"); /* lib_opentextbox */ |
| + | asmout("DD 0x0028, 0x0001, data.textbox, 0, 20, 8, 0, 0, data.window, 0x00c0, 0"); /* lib_opentextbox */ |
| + | asmout("DD 0x0040, 0x1000, 0, 0, data.wintitle, 0, 0, 0, 7, 'colora1'"); /* lib_putstring1 */ |
| + | DD(0x0000); /* end of functions */ |
| + | putstr: |
| + | asmout("DD 0x0040, 0x1000, 0, 0, data.textbox, 0, 0, 0, 8, 'color '"); /* lib_putstring1 */ |
| + | DD(0x0000); /* end of functions */ |
| + | sleep: |
| + | DD(0x0018, 0x0001, 0, 0); /* lib_waitsignal */ |
| + | DD(0x0000); /* end of functions */ |
| + | |
| + | ALIGNB(8); |
| + | work: |
| + | RESB(256); /* func_initに必要な256バイトのワークエリア */ |
| + | window: |
| + | RESB(128); /* ウィンドウ構造体 */ |
| + | wintitle: |
| + | RESB(64); /* テキストボックス構造体 */ |
| + | RESB(56); /* 7x1文字分 (7 * 1 * 8) */ |
| + | textbox: |
| + | RESB(64); /* テキストボックス構造体 */ |
| + | RESB(1280); /* 20x8文字分 (20 * 8 * 8) */ |
| + | } |
| + | |
| + | |
| + | -nask版:"colorn1.nas" [osa_dir2では 238バイト] |
| + | ; "colorn1.nas":colorをnaskで記述した例 |
| + | ; stack:20k malloc:0k |
| + | |
| + | [FORMAT "WCOFF"] |
| + | [INSTRSET "i486p"] |
| + | [OPTIMIZE 1] |
| + | [OPTION 1] |
| + | [BITS 32] |
| + | [FILE "colorn1.nas"] |
| + | |
| + | [SECTION .text] |
| + | GLOBAL _OsaskMain |
| + | |
| + | _OsaskMain: |
| + | MOV EBX,init |
| + | CALL 0xc7:0 |
| + | MOV AL,0 |
| + | .mainloop: |
| + | MOV EBX,putstr |
| + | MOV CL,10 |
| + | MOV CH,AL |
| + | SHR CH,1 |
| + | JC .skip |
| + | MOV CL,0 |
| + | .skip: |
| + | MOV [EBX+ 8],CL |
| + | MOV [EBX+12],CH |
| + | MOV [EBX+20],AL |
| + | LEA ESI,[EBX+42] |
| + | CALL setdec2 |
| + | CALL 0xc7:0 |
| + | INC AL |
| + | CMP AL,16 |
| + | JB .mainloop |
| + | MOV EBX,sleep |
| + | CALL 0xc7:0 |
| + | |
| + | setdec2: |
| + | PUSH ECX |
| + | PUSH EAX |
| + | MOV CL,10 |
| + | MOV AH,0 |
| + | DIV CL |
| + | OR EAX,'00' |
| + | CMP AL,'0' |
| + | JNE .skip |
| + | MOV AL,' ' |
| + | .skip: |
| + | MOV [ESI+0],AL |
| + | MOV [ESI+1],AH |
| + | POP EAX |
| + | POP ECX |
| + | RET |
| + | |
| + | ; .で始まるラベルはローカルラベル。 |
| + | ; ローカルラベルは、次のグローバルラベル宣言までが有効範囲。 |
| + | |
| + | [SECTION .data] |
| + | ALIGNB 4 |
| + | init: |
| + | DD 0x0004, work ; lib_init |
| + | DD 0x0020, window, 0x0200, 20 * 8, 8 * 16 ; lib_openwindow |
| + | DD 0x0028, 0x1000, wintitle, 0, 7, 1, 0, 0, window, 0x00c0, 0 ; lib_opentextbox |
| + | DD 0x0028, 0x0001, textbox, 0, 20, 8, 0, 0, window, 0x00c0, 0 ; lib_opentextbox |
| + | DD 0x0040, 0x1000, 0, 0, wintitle, 0, 0, 0, 7, 'colorn1' ; lib_putstring1 |
| + | DD 0x0000 ; end of functions |
| + | putstr: |
| + | DD 0x0040, 0x1000, 0, 0, textbox, 0, 0, 0, 8, 'color ' ; lib_putstring1 |
| + | DD 0x0000 ; end of functions |
| + | sleep: |
| + | DD 0x0018, 0x0001, 0, 0 ; lib_waitsignal |
| + | DD 0x0000 ; end of functions |
| + | |
| + | ALIGNB 8 |
| + | work: |
| + | RESB 256 ; func_initに必要な256バイトのワークエリア |
| + | window: |
| + | RESB 128 ; ウィンドウ構造体 |
| + | wintitle: |
| + | RESB 64 + 7 * 1 * 8; テキストボックス構造体(7x1文字分) |
| + | textbox: |
| + | RESB 64 + 20 * 8 * 8; テキストボックス構造体(20x8文字分) |
| + | |
| + | |
| + | *** 説明 |
| + | -概要: |
| + | --このプログラムは、ウィンドウを一つ開き、そのウィンドウに16色のメッセージを表示するだけのプログラムです。 |
| + | --このプログラムを通じて、テキストに色を付ける方法と、数字表示の方法について説明します。 |
| + | --OSASKでは、printf()やitoa()などの便利な関数がまだ用意されていません。したがっ |
| + | て、残念なことに数字を表示するのは少し面倒です。今回はitoaの代わりにsetdec2()という関数を作ってみました。 |
| + | --これくらいの規模の例になると、CとASKAとnaskの文法の違いが出てきますので、見比べてみるのも面白いかもしれません。どれでもいいのですので、好きな言語を活用してください。 |
| + | |
| + | -APIの説明: |
| + | |
| + | --lib_opentextbox(opt, textbox, backcolor, x_size, y_size, x_pos, y_pos, window, charset, init_char) : |
| + | ---ウィンドウにテキストボックスを貼ります。optの値は、0と0x1000しか紹介していませんでしたが、実は1も使えます。optに1を指定すると、テキストボックスに外枠が付きます。また、背景色が選べるようになり、それはbackcolorで指定します。それ以外はoptに0を指定した場合と全く同様です。なお、この枠がウィンドウをはみ出たり他の表示と重なったりしないようにしてください。 |
| + | |
| + | --lib_putstring_ASCII(opt, x_pos, y_pos, textbox, color, backcolor, str) : |
| + | ---colorc1.cでは使われていませんが、optに1を指定することにより、この関数でもbackcolorが有効になります。これは文字の背景色を文字単位で指定するものです。ちなみにスペースを表示した場合、backcolorで指定した色の四角形が表示されます。 |
| + | ---ASKA/naskのlib_putstring1も全く同様で、optの最下位ビットを1にすると、backcolorに0以外を指定できるようになります。 |
| + | |
| + | *** まとめ |
| + | -これで、テキストボックスを使った表示は一通りできるようになったはずです。許される範囲であちこちを改造して、把握してください。この程度のことなら、決して難しくないと感じていただけるはずです。 |
| + | -なお、C版でテキストボックスを広げる際には、malloc領域が不足する可能性があるので、malloc:オプションの値を大きくしてやってください。ASKA/naskでは、テキストボックス構造体のサイズを間違えなければ、mallocは0kのままでかまいません。 |
| + | |
| + | *** おまけ |
| + | -次回(no.0002)は時間制御関係を少しやります。これで、変化のあるテキスト表示ができるようになるでしょう。 |
| + | ~ |
| + | ~ |
| + | -''実際の開発をするにあたって'' |
| + | --このwintroシリーズを読んでいる人は、introシリーズを読んでいない可能性もあるので、大事な注意を書いておきます。 |
| + | --初心者がよくやることの一つに、プログラムをゼロから作り始めようとして失敗する、というのがあります。これは、いきなりプロジェクトを作って、まっさらなテキストファイルからプログラムを書いていく、ということを意味します。これはたいていうまくいきません。これはOSASKアプリ開発に限らず、他のOSのアプリ開発を最初にやろうとしたときもでも同じことです。 |
| + | --うまい方法は、まず、適当なサンプルアプリを見つけてきて(helloでもいいです)、それをコピーしたところから出発することです。これを少し改造し(たとえばウィンドウサイズとウィンドウタイトルを望みの大きさに変えて)、改造したらすぐに make run してみます。それでうまく動いたらバンザイです。さらに少し改造を加えて、自分の目的のアプリに近づけていきます。・・・もし make run してうまく動かなければ、どこが悪いのかをウンウンうなったりするのではなく、まずは動いていた段階に帰ります。そして少しずつ改造を戻していくことによって、どの変更で動かなくなったのかを突き止めるのです。 |
| + | --プログラムに経験があると過信している人ほど、この作業をやりません。まっさらなところから書き始めてつまづいて、それでそのプログラムを必至に眺めて、「おかしいところはないはずなんだけどなあ」とかいいます。もしくは、まめに make run するのをいやがって、一度にたくさん改造して、それでやっぱりバグを抱えて、何も分からなくなります。 |
| + | --この「こまめに make run 」「おかしくなったらつべこべ言わずに動いていた段階に一度戻る」を忠実に守った人が、一番速く上達します。初心者を脱した後でさえ、この方法で救われることを僕は何度も経験しています。 |
| + | --そんなわけで、僕としてはこの手法に沿った人からの質問にはできるだけ答えますが、そうでない人は自己努力不足ということで、十分な回答をしない場合があります。ご了承ください(これは具体的にどういうことかというと、問題あるソースだけではなく、問題なく動いていた段階のソースの提示を求めることがある、ということです)。 |
| + | |
| + | * こめんと欄 |
| + | #comment |