2: 2010-01-16 (土) 15:42:53 lina[6] [7] | 現: 2024-01-08 (月) 12:58:58 lina[6] [8] | ||
---|---|---|---|
Line 57: | Line 57: | ||
・・・順調だったのに・・・orz・・・エラーで止まってしまった・・・ | ・・・順調だったのに・・・orz・・・エラーで止まってしまった・・・ | ||
+ | |||
+ | **エラーの解析と対処 [#v0619d68] | ||
+ | COLOR(red){このセクションは移動or削除ora大改編が予想されますのでその旨ご容赦w} | ||
+ | |||
+ | 「NASKのエラーなんて、ググってもなんもわかんないよおぉぉ(泣」 | ||
+ | |||
+ | ・・・って思ってたら、それはそれ。インターネットってスゲーよね? めっけた。 | ||
+ | |||
+ | http://www.rapuos.net/scrsvr.html | ||
+ | |||
+ | これによると、''外部変数が多いと''NASKがこのエラーを吐くらしいことがわかった。外部変数ってなに??? 調べてみると、グローバル変数のことをこう呼ぶことがあるらしい。 | ||
+ | |||
+ | osalink1.cの内部をざーーっと眺めてみる。グローバル変数? ほとんど使ってないじゃん。容量が上がるほどの変数なんて・・・お??? | ||
+ | |||
+ | これかなぁ。先頭で | ||
+ | |||
+ | #define BUFSIZE 2 * 1024 * 1024 | ||
+ | |||
+ | こんなことをやっている。これが大きすぎるってことなのかなぁ。試しに、この行を1024とか小さい値と置き換えて・・・ | ||
+ | |||
+ | うはぁ!!! NASKのコンパイルが通ったぞ??? | ||
+ | |||
+ | COLOR(red){もちろん単にここを小さくするのは問題のはずだ。なぜこの値を指定していたのかは、ちゃんと意味があるんだからね。・・・でも、とにもかくにも、ここで宣言されている''値''によってNASKの挙動が左右されるってことだけは確認できた。正式な対処はちょっと先送りで、進めまするw} | ||
+ | |||
+ | |||
+ | *ld.exe [#b58350ff] | ||
+ | さていよいよldの登場ですw~ | ||
+ | |||
+ | **なんなの?それは??? [#e83060e6] | ||
+ | 今、まだ積み残しの問題があるとしても、とにもかくにもnasuka(NASK)がアセンブル(コンパイル)を完了してosalink1.oを作ってくれました。これはもうバイナリです。(いままでと違ってエディタでは開けませんよw バイナリエディタでないと) | ||
+ | |||
+ | じゃあ、このバイナリは動かせるのでしょうか?~ | ||
+ | 答えは No! です。 | ||
+ | |||
+ | なぜかって? このosalink1.oには''プログラムが書かれていないから''ですw | ||
+ | |||
+ | たとえば。「xxxをディスクに書き込みする」という命令があるとします。仮に、その命令は、 | ||
+ | |||
+ | 51 01 89 C2 C1 FA 10 C1 F8 18 88 51 02 88 41 03 5D C3 55 89 E5 8B 55 08 5D 0F B6 02 0F B6 52 01 | ||
+ | |||
+ | こんなんだとしますよね? (もちろん機械語ですよw) この命令をはじめから実行してゆくと、ディスクが動いて磁気ヘッドに電流を流し、書き込みを行うとします。 | ||
+ | |||
+ | ・・・しかし、この段階では、この命令はosalink1.o内には書かれていないのです。~ | ||
+ | 同じように、他の命令も書かれていません。 | ||
+ | -画面に一文字書き出せ | ||
+ | -メモリをxxxバイト確保しろ | ||
+ | -書かれている文字を数値に変換して計算し、結果を再び文字に変換しろ | ||
+ | -etc・・・・ | ||
+ | |||
+ | osalink1.o内には様々な動作をする命令がちゃんと沢山書かれているのですが、上記のようなよく使われる大事な命令達は書かれていません。では、そういう命令はどうするのでしょう? これから自分で別に作るのでしょうか?? | ||
+ | |||
+ | もちろんそれも可能です。しかし、こういうよく使われる・いろいろなプログラムから共通で統一的に使われる命令達はライブラリ(図書館?)と呼ばれる別のファイルに、あらかじめ書かれ、すでに用意されているのです。 | ||
+ | |||
+ | ldは「リンカ」と呼ばれるプログラムで、こういったバラバラの部品として完成しているファイル(中間ファイル・オブジェクトファイルなどと呼ばれる)をお互いに合体させ、最後にキチンと本当に動くプログラムに組み立てるという働きをするのです。 | ||
+ | |||
+ | |||
+ | |||
+ | **さて! いざ、リンク! [#q664086e] | ||
+ | ..\z_tools\ld.exe --stack 0x2000000 -o osalink1.exe osalink1.o ..\z_tools\win32/libmingw.lib | ||
+ | |||
+ | ・・・ダメだった・・・・orz・・・(やっぱみようみまねじゃアカンなw) | ||
+ | |||
+ | ..\z_tools\ld.exe: warning: cannot find entry symbol _mainCRTStartup; defaulting to 00401000 | ||
+ | osalink1.o(.text+0x85):osalink1.ca: undefined reference to `__main' | ||
+ | osalink1.o(.text+0xba):osalink1.ca: undefined reference to `fopen' | ||
+ | osalink1.o(.text+0xdf):osalink1.ca: undefined reference to `fscanf' | ||
+ | osalink1.o(.text+0xf4):osalink1.ca: undefined reference to `fopen' | ||
+ | osalink1.o(.text+0x11d):osalink1.ca: undefined reference to `fread' | ||
+ | osalink1.o(.text+0x125):osalink1.ca: undefined reference to `fclose' | ||
+ | osalink1.o(.text+0x164):osalink1.ca: undefined reference to `tolower' | ||
+ | osalink1.o(.text+0x262):osalink1.ca: undefined reference to `fclose' | ||
+ | osalink1.o(.text+0x270):osalink1.ca: undefined reference to `__stderr' | ||
+ | osalink1.o(.text+0x275):osalink1.ca: undefined reference to `fprintf' | ||
+ | |||
+ | さて。このエラーはなんだろうか?~ | ||
+ | 上記の命令だと、osalink1.oとlibmingw.libを合体させてosalink1.exeを作り出せってしてるんだけど、ldはいざ合体させ始めると、 | ||
+ | |||
+ | 「おいおい! osalink1.o内で、fopenって命令を使ってるじゃないかよ! osalink1.o内にも、libmingw.lib内にも、その命令は書かれてないぞ? 命令が間違ってるんじゃね? もしくは、これらが書かれているライブラリを教えてよ!」 | ||
+ | |||
+ | と、こういう答えを出して来たと。こういうわけ。 | ||
+ | |||
+ | 他のライブラリを指定してあげれば、それらから命令を拾ってきて合体させてくれる。これでOKだ!!! | ||
+ | |||
+ | ..\z_tools\ld.exe -s -Bdynamic --stack 0x2000000 -o osalink1.exe osalink1.obj ..\z_tools\win32\w32clibc.lib ..\z_tools\win32 \golibc.lib ..\z_tools\win32\libmingw.lib | ||
+ | |||
+ | osalink1.obj(.text+0xda):osalink1.ca: undefined reference to `fscanf' | ||
+ | osalink1.obj(.text+0x15f):osalink1.ca: undefined reference to `tolower' | ||
+ | osalink1.obj(.text+0x41a):osalink1.ca: undefined reference to `tolower' | ||
+ | osalink1.obj(.text+0x45d):osalink1.ca: undefined reference to `tolower' | ||
+ | |||
+ | ・・・ダメですた・・・orz・・・ | ||
+ | |||
+ | あっれぇ?? 今、ざーっと調べてみたんだけど、そういえばz_tools\win32\stdio.h内にはfscanfって関数、ないような・・・ | ||
+ | |||
+ | COLOR(red){さらに発覚! tolower関数は、あの、''ctype.h''で定義されている命令なんだって!? ・・・うわぁ・・・まいったなぁ・・・} | ||
+ | |||
+ | |||
+ | *やべ・・・いろいろゴチャゴチャになってきたぞw [#ab1b8e1e] | ||
+ | **tolower関数 [#uff7855f] | ||
+ | 逆に言えば!! | ||
+ | |||
+ | ctype.hをインクルードしてるけど、この関数さえあればいいわけでしょ? 自作 できんか? これ? | ||
+ | |||
+ | tolower関数は、文字が大文字なら小文字に変換。大文字以外なら、そのままの値を返すというものだよね? | ||
+ | |||
+ | A~Zってーのは、41h~5Ahまで。で、a~zまでは61h~7Ahまでだよね? おぉ!綺麗に20h差で揃ってるじゃんwww | ||
+ | |||
+ | char tolower_hide(char moto){ | ||
+ | if ( (moto > 0x41) && (moto < 0x5a ) ){ | ||
+ | return moto + 0x20; | ||
+ | } | ||
+ | else{ | ||
+ | return moto; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | ・・・これじゃダメか??? | ||
+ | |||
+ | ぶははは。なんかうまく行きそうな予感wwwww | ||
+ | |||
+ | **fscanf関数 [#v4927eff] | ||
+ | うーーーん・・・・・・・(汗 | ||
+ | |||
+ | fscanfそのものはなんかけっこう複雑なもののように思う。・・・でもさぁ。なにも丸々搭載することはない・・・よね?? | ||
+ | |||
+ | osalink1.c内ではfsnanfはこんな形で使われている。 | ||
+ | |||
+ | for (i = 0; fscanf(fp0, " %s", fname) == 1; i++) { | ||
+ | fp1 = fopen(fname, "rb"); | ||
+ | if (fp1 == NULL) { | ||
+ | |||
+ | トーシローのオイラも目には、これはosalink.optを''一行づつ''読み込んで、その読み込んだ文字列と同じ名前のファイルのオープンを試みている・・・というゆうに読める。んん?? 一行??? | ||
+ | |||
+ | ・・・これ、fgets()じゃダメなの?(幸いstdio.hにはfgets関数がある) | ||
+ | |||
+ | なんでKタンはfgets()を使わずにfscanf()を使ったんだろう?なにか意味がきっとあるはず・・・ | ||
+ | |||
+ | とにもかくにも!!!!! | ||
+ | |||
+ | こんなことしたら、コンパイルが通った。 | ||
+ | fp0 = fopen(optfile, "r"); | ||
+ | if (fp0 == NULL) { | ||
+ | fprintf(stderr, "Can't open \"%s\".\n", optfile); | ||
+ | return 1; | ||
+ | } | ||
+ | // for (i = 0; fscanf(fp0, " %s", fname) == 1; i++) { | ||
+ | for (i = 0; fgets(fname,32,fp0) != NULL; i++) { | ||
+ | fp1 = fopen(fname, "rb"); | ||
+ | if (fp1 == NULL) { | ||
+ | |||
+ | さーて。乱暴者のオラはこれでOSASKをコンパイルしてみようwwww | ||
+ | |||
+ | ダメか・・・ | ||
+ | |||
+ | どうも、fgetsだと改行コードが入り込むらしい。そんならってんで、こんな改行コード抜きを載せてみる。 | ||
+ | |||
+ | for (i = 0; fgets(fname,32,fp0) != NULL; i++) { | ||
+ | |||
+ | //改行コードの引っこ抜き | ||
+ | for ( i2 = 31; i2 != 0; i2--){ | ||
+ | if ( fname[i2] == 0x0a ) fname[i2] = 0; | ||
+ | if ( fname[i2] == 0x0d ) fname[i2] = 0; | ||
+ | } | ||
+ | |||
+ | fp1 = fopen(fname, "rb"); | ||
+ | if (fp1 == NULL) { | ||
+ | err1: | ||
+ | fclose(fp0); | ||
+ | |||
+ | ・・・やっぱだめだなぁ・・・orz | ||
+ | |||
+ | わからんなぁ・・・・・・。こうしてみると・・・ | ||
+ | strcpy (fname,"base.exe"); osalink.optの一行目 | ||
+ | fp1 = fopen(fname,"rb"); | ||
+ | if (fp1 != NULL){ | ||
+ | fprintf(stderr, "testOpenOK!\n", fname); ちゃんとオープンが成功してくれる! | ||
+ | fprintf(stderr, "nagasa=%d\n", strlen(fname)); 長さは8と表示される | ||
+ | fclose(fp1); | ||
+ | } | ||
+ | |||
+ | // for (i = 0; fscanf(fp0, " %s", fname) == 1; i++) { | ||
+ | for (i = 0; fgets(fname,32,fp0) != NULL; i++) { | ||
+ | |||
+ | //改行コードの引っこ抜き | ||
+ | for ( i2 = 31; i2 != 0; i2--){ | ||
+ | if ( fname[i2] == 0x0a ) fname[i2] = 0x0; | ||
+ | if ( fname[i2] == 0x0d ) fname[i2] = 0x0; | ||
+ | } | ||
+ | |||
+ | fp1 = fopen(fname, "rb"); | ||
+ | if (fp1 == NULL) { | ||
+ | err1: | ||
+ | fclose(fp0); | ||
+ | fprintf(stderr, "Can't openaaa \"%s\".\n", fname); オープンに失敗する | ||
+ | fprintf(stderr, "nagasa=%d\n", strlen(fname)); 長さも同じ8。 | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | なぜ読み込んで改行抜きをしたfnameではエラーになるんだろう????? | ||
+ | |||
+ | こうやったらうまくいった!!! ・・・・でも納得できない・・・なんでだろう??? | ||
+ | |||
+ | strcpy (fname2,fname); | ||
+ | fp1 = fopen(fname2, "rb"); | ||
+ | |||
+ | |||
+ | *最後! 例のバッファ! [#bb8a6fe7] | ||
+ | |||
+ | このbuf0って、文字通り、対象ファイルを読み込んだものを格納するバッファだよね?? で! | ||
+ | |||
+ | static unsigned char buf0[BUFSIZE]; | ||
+ | |||
+ | この命令で、2 × 1024 × 1024バイトの''空文字が格納された文字変数''を用意したわけだよね?(しかもグローバル変数)~ | ||
+ | ・・・''グローバル変数じゃないもの''にすればOK?? | ||
+ | |||
+ | そんなわけで、こんなことしてみた。すると・・・・ | ||
+ | |||
+ | const int main(int argc, char **argv) | ||
+ | { | ||
+ | FILE *fp0, *fp1; | ||
+ | int i, i2,j, k, size, totalsize = 0; | ||
+ | unsigned char fname[32], name[8], c; | ||
+ | unsigned char fname2[32]; | ||
+ | unsigned char bufX[2*1024*1024]; | ||
+ | |||
+ | おぉ!bufXは使っていないんだけど、とにもかくにもこうやって''グローバルではない変数''しさえすれば、エラーを吐かないぞ? つまり、大きさが問題なんじゃなくて、でかい''グローバル変数''が問題ってことじゃないか! | ||
+ | |||
+ | なぜbuf0はわざわざグローバル変数になってるんだろ? それは、他の関数内でも使われてるからだよね? | ||
+ | |||
+ | const int script(char *opt, char *inp, char *out) | ||
+ | /* スクリプトが4KBを超えたら死にます */ | ||
+ | { | ||
+ | unsigned char *buf = buf0 + 4 * 1024, *scr0 = buf0, *scr1, *s, *s1; | ||
+ | FILE *fp; | ||
+ | int size, memofs, filofs; | ||
+ | |||
+ | |||
+ | ・・・あれ? この、script関数内だけじゃないか!!!!~ | ||
+ | だったらさぁ。こうやって、script関数の引数に、buf0のアドレス(ポインタ)を渡してあげればそれでいいんじゃないの?? | ||
+ | |||
+ | const int script(char *opt, char *inp, char *out, char *helmes_buf) | ||
+ | /* スクリプトが4KBを超えたら死にます */ | ||
+ | { | ||
+ | |||
+ | unsigned char *buf = helmes_buf + 4 * 1024, *scr0 = helmes_buf, *scr1, *s, *s1; | ||
+ | FILE *fp; | ||
+ | int size, memofs, filofs; | ||
+ | |||
+ | COLOR(blue){うぎゃあぁぁぁぁぁぁぁぁぁぁぁぁ!!!!! 動いた! OSASKがうごいたぞおぉぉぉぉ!!!!!} | ||
+ | |||
+ | *誰かCに詳しい人検証してくれww [#x4f02bf0] | ||
+ | |||
+ | #ref(osalink1_src_1.2.zip) |
(This host) = http://osask.net