なんすかこれ?
hideyosiのお勉強のページ♪
GOとかtolsetとかの中にosalink1.exeっつーのがある。これは予測だけど、ポツンと.cファイルがあるだけってことから、たぶんGOとか(Kタンの自前開発環境)が出来る前に作られたものだと思う。
(そうなると、MinGWだとか、別のきれいに整った開発環境で作られてるはず。そういう完成した環境ではみーんな付いてるので、.cをひとつ作ればツルっとexeが作れちゃうと。その証拠にMinGWだとペロっとコンパイルできて動いちゃうw)
・・・こいつが、28GOでコンパイルできない・・・
なんかムカつく!
っつーわけで、よい教材になるかなと思って28GOでコンパイルできるように弄っていこうかと。こういうわけ!
ちなみに、ここからダウンロードできるぞよ?
http://sourceforge.jp/projects/osask/downloads/45468/osalink1_src_1.0.tar.gz/
sjisconv.exe
こいつはなにをやっているのか。たしか、ソースコード内にShift-jisの文字が入っているとうまくないってんでそれをお掃除してくれるor変換してくれるツールだったはず。まずはコイツで・・・
..\z_tools\sjisconv.exe -s osalink1.c osalink1.ca
osalink1.caの中身を見てみると日本語部分がぜーんぶ「\203」とかそういうのになってる。変換されたわけですなw(なんだべこれ? rawとかそういうのになるのかな??)
cc1.exe
CのソースなんだからCでコンパイルすると。(あったりまえだぁw)
osalink1のソース内に、ctype.hが宣言されてる。これちょっと迷ったんだけど、MinGWではここ削除してもそのままコンパイルできちゃうので神頼み的にこれで進めちゃいます・・・
ここで復習。Cコンパイラはなにをしてるのか。総合環境だと忘れがちなんだけど、Cコンパイラは実行ファイルなんかつくってくれない!
あくまでも、Cソースを元にアセンブラコードを作ってくれるだけなのだ。
こんなことしてアセンブラコードであるosalink1.gasを作ると・・・
..\z_tools\cc1.exe -I../z_tools/win32/ -Os -Wall -quiet -o osalink1.gas osalink1.ca
gas2nask.exe
cc1で出来上がったosalink1.gas。これは先に述べたように、単なるアセンブラコードに過ぎない。その証拠に、エディタで開けたりするw
さて。28GO(GO 0023)のCコンパイラは元々gccだった。そのため、このコンパイラが吐き出すアセンブラコードはgccとペアで使うことが想定されている GAS(The GNU Assembler)用のものなのだ。
つまり、このosalink1.gasをGASでコンパイル(アセンブル)すれば実行ファイルが出来上がると。未確認ですサーセン
・・・しかし! 我らが28GO(笑)にはGASよりカッチョイイnasuka(NASK)があるのだ!
・・・そんなわけで。GAS用のアセンブラコードをnasuka用に変換してやればいいわけ。それがgas2naskの役目ね。
..\z_tools\gas2nask.exe -a osalink1.gas osalink1.nas
これで、nasukaでアセンブルできるコード、osalink1.nasが出来上がったと。
nask.exe(本名 nasuka )
アセンブラのnask.exeでアセンブルすると、これで初めてバイナリコードが生成されるわけ。
..\z_tools\nask.exe osalink1.nas osalink1.o
NASK : TMPBUF is not enough
・・・順調だったのに・・・orz・・・エラーで止まってしまった・・・
エラーの解析と対処
このセクションは移動or削除ora大改編が予想されますのでその旨ご容赦w
「NASKのエラーなんて、ググってもなんもわかんないよおぉぉ(泣」
・・・って思ってたら、それはそれ。インターネットってスゲーよね? めっけた。
http://www.rapuos.net/scrsvr.html
これによると、外部変数が多いとNASKがこのエラーを吐くらしいことがわかった。外部変数ってなに??? 調べてみると、グローバル変数のことをこう呼ぶことがあるらしい。
osalink1.cの内部をざーーっと眺めてみる。グローバル変数? ほとんど使ってないじゃん。容量が上がるほどの変数なんて・・・お???
これかなぁ。先頭で
#define BUFSIZE 2 * 1024 * 1024
こんなことをやっている。これが大きすぎるってことなのかなぁ。試しに、この行を1024とか小さい値と置き換えて・・・
うはぁ!!! NASKのコンパイルが通ったぞ???
もちろん単にここを小さくするのは問題のはずだ。なぜこの値を指定していたのかは、ちゃんと意味があるんだからね。・・・でも、とにもかくにも、ここで宣言されている値によってNASKの挙動が左右されるってことだけは確認できた。正式な対処はちょっと先送りで、進めまするw
なんなの?それは???
今、まだ積み残しの問題があるとしても、とにもかくにも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は「リンカ」と呼ばれるプログラムで、こういったバラバラの部品として完成しているファイル(中間ファイル・オブジェクトファイルなどと呼ばれる)をお互いに合体させ、最後にキチンと本当に動くプログラムに組み立てるという働きをするのです。
さて! いざ、リンク!
..\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って関数、ないような・・・
さらに発覚! tolower関数は、あの、ctype.hで定義されている命令なんだって!? ・・・うわぁ・・・まいったなぁ・・・
tolower関数
逆に言えば!!
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関数
うーーーん・・・・・・・(汗
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");
最後! 例のバッファ!
この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;
うぎゃあぁぁぁぁぁぁぁぁぁぁぁぁ!!!!! 動いた! OSASKがうごいたぞおぉぉぉぉ!!!!!
Counter: 286,
today: 2,
yesterday: 2
初版日時: 2010-01-16 (土) 14:38:45
最終更新: 2010-01-18 (月) 00:00:00 (JST) (319d) by lina
|
ぺージ情報 | 閲覧可 | 編集可 | |||
---|---|---|---|---|---|---|
ぺージ名 : | hideyosi/osalink1でお勉強 | グループ : | すべての訪問者 | グループ : | 登録ユーザ | |
ページ作成 : | lina | ユーザー : | すべての訪問者 | ユーザー : | なし | |
ページ別名 : | 未設定 |