ページへ戻る

− Links

 印刷 

hideyosi​/osalink1でお勉強 のバックアップソース(No.8) :: OSASK計画

osaskwiki:hideyosi/osalink1でお勉強 のバックアップソース(No.8)

« Prev[4]  Next »[5]
*なんすかこれ? [#r15fad1b]
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 [#r2f6284e]
こいつはなにをやっているのか。たしか、ソースコード内にShift-jisの文字が入っているとうまくないってんでそれをお掃除してくれるor変換してくれるツールだったはず。まずはコイツで・・・

 ..\z_tools\sjisconv.exe -s osalink1.c osalink1.ca

osalink1.caの中身を見てみると日本語部分がぜーんぶ「\203」とかそういうのになってる。変換されたわけですなw(なんだべこれ? rawとかそういうのになるのかな??)

*cc1.exe [#w696591b]
CのソースなんだからCでコンパイルすると。(あったりまえだぁw)

COLOR(red){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 [#g1a7aa7d]
cc1で出来上がったosalink1.gas。これは先に述べたように、''単なるアセンブラコード''に過ぎない。その証拠に、エディタで開けたりするw

さて。28GO(GO 0023)のCコンパイラは元々gccだった。そのため、このコンパイラが吐き出すアセンブラコードはgccとペアで使うことが想定されている GAS(The GNU Assembler)用のものなのだ。

つまり、このosalink1.gasをGASでコンパイル(アセンブル)すれば実行ファイルが出来上がると。COLOR(red){未確認ですサーセン}

・・・しかし! 我らが28GO(笑)にはGASよりカッチョイイnasuka(NASK)があるのだ!

・・・そんなわけで。GAS用のアセンブラコードをnasuka用に変換してやればいいわけ。それがgas2naskの役目ね。

 ..\z_tools\gas2nask.exe -a osalink1.gas osalink1.nas

これで、nasukaでアセンブルできるコード、osalink1.nasが出来上がったと。

*nask.exe(本名 nasuka ) [#uf795a47]
アセンブラのnask.exeでアセンブルすると、これで初めて''バイナリコード''が生成されるわけ。

 ..\z_tools\nask.exe osalink1.nas osalink1.o

 NASK : TMPBUF is not enough

・・・順調だったのに・・・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ではエラーになるんだろう?????


« Prev[4]  Next »[5]