wiki版のintroシリーズ no.0001
- (by K, 2004.12.13)
- これはC言語でもASKAでもnaskでもとにかくごちゃまぜでintroしてしまおうというこころみ。
- これはguide/wintro0000の続きなので、それを読んでない人はそれを読んでね。
- 最初から読みたい人はguide/Cやguide/ASKAやguide/naskからどうぞ。
- C言語をやる人はintroaを読むといいでしょう。ここのプログラムは、introaと同一内容です。
- これはguide/wintro0000の続きなので、それを読んでない人はそれを読んでね。
- 質問とか感想とかはこめんと欄にレッツゴー。
color
- C版:"colorc1.c" [tolset08では 546バイト]
/* "colorc1.c":colorをC言語で記述した例 */ /* stack:4k malloc:2k */ #include <guigui00.h> #define AUTO_MALLOC 0 void setdec2(const int i, char *s); void OsaskMain() { struct LIB_WINDOW *window; struct LIB_TEXTBOX *wintitle, *textbox; int i; static char msg[] = "color 0"; /* ライブラリ初期化 */ lib_init(AUTO_MALLOC); /* ウィンドウのオープン */ window = lib_openwindow(AUTO_MALLOC, 0x0200, 20 * 8, 8 * 16); wintitle = lib_opentextbox(0x1000, AUTO_MALLOC, 0, 7, 1, 0, 0, window, 0x00c0, 0); textbox = lib_opentextbox(0x0001, AUTO_MALLOC, 0, 20, 8, 0, 0, window, 0x00c0, 0); lib_putstring_ASCII(0x0000, 0, 0, wintitle, 0, 0, "colorc1"); /* メインルーチン */ for (i = 0; i < 16; i += 2) { setdec2(i, &msg[6]); lib_putstring_ASCII(0x0000, 0, i / 2, textbox, i, 0, msg); setdec2(i + 1, &msg[6]); lib_putstring_ASCII(0x0000, 10, i / 2, textbox, i + 1, 0, msg); } /* 終了 */ lib_waitsignal(0x0001, 0, 0); } void setdec2(const int i, char *s) /* 注意:このルーチンでは、0~99までしか扱えない */ { s[0] = '0' + i / 10; s[1] = '0' + i % 10; if (s[0] == '0') s[0] = ' '; return; }
- ASKA版:"colora1.ask" [tolset08では 210バイト]
/* "colora1.ask":colorをASKAで記述した例 */ /* stack:4k 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" [tolset08では 209バイト]
; "colorn1.nas":colorをnaskで記述した例 ; stack:4k 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_opentextbox(opt, textbox, backcolor, x_size, y_size, x_pos, y_pos, window, charset, init_char) :
- 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以外を指定できるようになります。
- lib_putstring_ASCII(opt, x_pos, y_pos, textbox, color, backcolor, str) :
まとめ
- これで、テキストボックスを使った表示は一通りできるようになったはずです。許される範囲であちこちを改造して、把握してください。この程度のことなら、決して難しくないと感じていただけるはずです。
- なお、C版でテキストボックスを広げる際には、malloc領域が不足する可能性があるので、malloc:オプションの値を大きくしてやってください。ASKA/naskでは、テキストボックス構造体のサイズを間違えなければ、mallocは0kのままでかまいません。
おまけ
- 次回(no.0002)は時間制御関係を少しやります。これで、変化のあるテキスト表示ができるようになるでしょう。
- 続編はこちら → guide/wintro0002
- 実際の開発をするにあたって
- このwintroシリーズを読んでいる人は、introシリーズを読んでいない可能性もあるので、大事な注意を書いておきます。
- 初心者がよくやることの一つに、プログラムをゼロから作り始めようとして失敗する、というのがあります。これは、いきなりプロジェクトを作って、まっさらなテキストファイルからプログラムを書いていく、ということを意味します。これはたいていうまくいきません。これはOSASKアプリ開発に限らず、他のOSのアプリ開発を最初にやろうとしたときもでも同じことです。
- うまい方法は、まず、適当なサンプルアプリを見つけてきて(helloでもいいです)、それをコピーしたところから出発することです。これを少し改造し(たとえばウィンドウサイズとウィンドウタイトルを望みの大きさに変えて)、改造したらすぐに make run してみます。それでうまく動いたらバンザイです。さらに少し改造を加えて、自分の目的のアプリに近づけていきます。・・・もし make run してうまく動かなければ、どこが悪いのかをウンウンうなったりするのではなく、まずは動いていた段階に帰ります。そして少しずつ改造を戻していくことによって、どの変更で動かなくなったのかを突き止めるのです。
- プログラムに経験があると過信している人ほど、この作業をやりません。まっさらなところから書き始めてつまづいて、それでそのプログラムを必至に眺めて、「おかしいところはないはずなんだけどなあ」とかいいます。もしくは、まめに make run するのをいやがって、一度にたくさん改造して、それでやっぱりバグを抱えて、何も分からなくなります。
- この「こまめに make run 」「おかしくなったらつべこべ言わずに動いていた段階に一度戻る」を忠実に守った人が、一番速く上達します。初心者を脱した後でさえ、この方法で救われることを僕は何度も経験しています。
- そんなわけで、僕としてはこの手法に沿った人からの質問にはできるだけ答えますが、そうでない人は自己努力不足ということで、十分な回答をしない場合があります。ご了承ください(これは具体的にどういうことかというと、問題あるソースだけではなく、問題なく動いていた段階のソースの提示を求めることがある、ということです)。
こめんと欄
- tolset08にあわせて修正。 -- K 2005-01-29 (土) 15:34:36
Counter: 258,
today: 1,
yesterday: 1
初版日時: 2004-12-13 (月) 17:17:20
最終更新: 2010-04-10 (土) 00:00:00 (JST) (319d) by k-tan
|
ぺージ情報 | 閲覧可 | 編集可 | |||
---|---|---|---|---|---|---|
ぺージ名 : | guide/wintro0001 | グループ : | すべての訪問者 | グループ : | すべての訪問者 | |
ページ作成 : | k-tan | ユーザー : | すべての訪問者 | ユーザー : | すべての訪問者 | |
ページ別名 : | 未設定 |