1220317
Jun's Homepage

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21|


どうやら・・ 投稿者:志穂 投稿日:2003/01/07(Tue) 04:58 No.148  
>よくわかりませんが、(5+1)=5+1 と同じように
>単に式のように思います。symbol がすでにsymbolの値を
>アドレスとするメモリ内容を意味しているので、(symbol)
>も同じではありませんか?

junさんの言うとおり、これは式のようです。
で、
(%ebx)のようにレジスタを介すときのみ、
間接アドレッシングとなるみたいです。
少しずつですが、みえてきたようです。
ありがとうございます!



Re: どうやら・・ 志穂 - 2003/01/08(Wed) 13:24 No.149  

http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html
をみると
以下のような記述がありました。


Addressing what a register points to:

AT&T: (%eax)
Intel: [eax]

"what a register points to"
より、
レジスタが指しているものにアドレッシング
する場合に括弧で囲むっていうことなので、
レジスタでなければ単なる式ってことで
いいみたいですね。


ポインタかな? 投稿者:志穂 投稿日:2003/01/03(Fri) 20:34 No.142  
http://paran0ia.virtualave.net/documents/asm1.html
でみつけたんだけど、
文字列
char *var="abcDE"; # C言語
var: .ascii "abcDE" # アセンブラ

だとすると、
varは文字列の先頭アドレスを保持していることになりますね。
すると、これは
movl (var),%eax
文字列の先頭アドレスから、4バイト分を%eaxに転送しなさい
と解釈していいのかな?






Re: ポインタかな? jun - 2003/01/03(Fri) 21:58 No.144  

そのサイトにも連絡先があるので、聞いていただければと...
まあ、そういうことだと思います。


あけましておめでとうございます。 投稿者:志穂 投稿日:2003/01/02(Thu) 03:43 No.139  
お久しぶりです。今年もご指導よろしくおねがいします。
・・で、いきなり質問です。

Intelマシンなんですが、

.data
string: .ascii "abcdef"

movl string,%eax・・・@
movl $string,%ebx・・A
movl (string),%ecx・・・B
movl (string+1),%edx・・・C

@は、変数名になにもついていないので、
アドレス$string、すなわち変数stringの先頭アドレスの
メモリの内容を転送している。
で、
Aは、変数の先頭に$がついているので、これは
変数stringのアドレス値を転送している。

さて、問題はB、Cなんです。

デバッグすると、%ecxには'a'が、%edcには'b'が
転送されていることがわかりました。

これがわからないんです。

(string)のstringはなんですか?
変数名の先頭になにもついてないので、
メモリの内容ということになってしまいます。
()はポインタをあらわすんですよね?
(%ebx)だったら、%ebxがさすメモリの内容を意味するんです
よね。
そうやって考えていくと、stringっていうのは
いったいなに?みたいな。
ここで、もうこんがらがってしまって・・・
で、
今みている教科書には、
共通領域arrayがメモリ上に12バイトとられているとすると
movl $4,array+2

のようなことができるとあるんですが、
arrayはメモリ内容ですよね。
とすると、array+2という表現はおかしいようにおもうんです。
これって、($array+2)と解釈されているんですかね?
つまり、アドレス$array+2のメモリの内容と。
それならつじつまがあうんですが。

新年早々、質問攻めですが、回答よろしくお願いします。



Re: あけましておめでとうございます。 jun - 2003/01/03(Fri) 16:33 No.140  

> デバッグすると、%ecxには'a'が、%edcには'b'が
> 転送されていることがわかりました。

%ecx には "dcba", %edx には "edcb" ではないですか?
%cl と %dl はそれぞれ "a" と "b" になると思いますが。

> (string)のstringはなんですか?
> 変数名の先頭になにもついてないので、
> メモリの内容ということになってしまいます。
> ()はポインタをあらわすんですよね?

シンボルの場合もポインタですか?
$symbol の場合はアドレスというより、即値です。

> * AT&T immediate operands are preceded by `$'; Intel immediate
> operands are undelimited (Intel `push 4' is AT&T `pushl $4').
> AT&T register operands are preceded by `%'; Intel register operands
> are undelimited. AT&T absolute (as opposed to PC relative)
> jump/call operands are prefixed by `*'; they are undelimited in
> Intel syntax.

ということです。

> そうやって考えていくと、stringっていうのは
> いったいなに?みたいな。

この場合の string はシンボルで32bit整数につけた名前です。


Re: あけましておめでとうございます。 志穂 - 2003/01/03(Fri) 20:24 No.141  

レスありがとうございます!

>%ecx には "dcba", %edx には "edcb" ではないですか?
>%cl と %dl はそれぞれ "a" と "b" になると思いますが。

そのとおりです!
デバッグの仕方に問題がありました。
display/c $ecx
とやっていたのです。これだと、一文字しか出力されないん
ですよね。
それにIntelなんで、リトルエンディアンでした!

低位アドレス
| a・・アドレス$string
| b
| c
| d
| e
| f
v
高位アドレス

movl (string),%ecx・・・B
の場合、
l・・4バイト転送なので、
低位から4バイト分(abcd)転送される。

ah|al
--+---
dc|ba



movl (string+1),%edx
の場合、
bcdeの4バイトが転送される。

ah|al
--+--
ed|cb

・・・ちょっとあいまいにしてるところなんですが、
ahは高位レジスタなので、高位のアドレス2バイト分が
格納され、alは低位レジスタなので、低位アドレス2バイト
分が格納される
と考えていいのでしょうか?

で、結局、
(string)はいったいなんなんでしょう?

>シンボルの場合もポインタですか?
いいえ。シンボルってのは識別子のこと?
だとしたら、メモリの内容です。
変数名になにもつけないと、メモリ内容と
いうことになります。

stringは、変数名になにもついてないので
通常はメモリ内容でしょ?
それともこう考えるのでしょうか?
変数名は、CPUが理解できるようなアドレス値に変換される
ので、stringはアドレス値である。
すると、(string)はポインタ?
・・・またあいまいになってきてしまいました。
たとえば、%ebxがアドレスXを保持しているとしたら、
movb (%ebx),var
ならば、アドレス%ebxのメモリの内容を変数varのメモリ内容に転送しろ
ということになりますよね。
(string)のstringはアドレス値だとしても、
stringがそのアドレス値を保持しているわけでは
ない。stringは単なるラベルだ。
・・・頭痛くなってきました。
お助けを。


Re: あけましておめでとうございます。 jun - 2003/01/03(Fri) 21:54 No.143  

よくわかりませんが、(5+1)=5+1 と同じように
単に式のように思います。symbol がすでにsymbolの値を
アドレスとするメモリ内容を意味しているので、(symbol)
も同じではありませんか?

GASのAT&Tのsyntaxがわかりにくいのでnasmに逃げています。

ところで、EAXの下位2バイトはAH と AL に各1バイト保持されます。
EAXの上位2バイトは直接1バイトずつアクセスすることはできません。
16ビット右シフトして、AXに入れてからアクセスします。


junさん、すみません。 投稿者:志穂 投稿日:2002/12/25(Wed) 23:23 No.133  
・・とたんにわかんなくなってきちゃった。
ちょっとまとめてから質問するね。
あー、もう最悪。


Re: junさん、すみません。 jun - 2002/12/27(Fri) 01:35 No.134  

いったい、なんだろー。。。

気になりますよね。>皆様


Re: junさん、すみません。 ODIN - 2002/12/27(Fri) 12:44 No.135  

こんにちは。ROMばっかりのODINです。
「>皆様」と言われたので出てきてしまいました(^-^


Re: junさん、すみません。 jun - 2002/12/27(Fri) 23:23 No.136  

ODINさん、お久しぶりです。
風邪で寝たきりのjunでした。


質問です。教えて下さい。 投稿者:志穂 投稿日:2002/12/25(Wed) 20:00 No.131  
[@//test]cat test2.c
#include<stdio.h>

int a[3];
int main(void){
a[0]=3;
a[1]=5;
a[2]=9;
return 0;
}
[@//test]cat test2.s
.file "test2.c"
.version "01.01"
gcc2_compiled.:
.text
.align 4
.globl main
.type main,@function
main:
pushl %ebp
movl %esp,%ebp
movl $3,a
movl $5,a+4
movl $9,a+8
xorl %eax,%eax
jmp .L2
.p2align 4,,7
.L2:
movl %ebp,%esp
popl %ebp
ret
.Lfe1:
.size main,.Lfe1-main
.comm a,12,4
.ident "GCC: (GNU) 2.95.3 19991030 (prerelease)"
[@//test]


このときですね、

.comm a,12,4

は、

「共通領域に12バイト(=int x 3 = 4バイト x 3)を取る。
 ただし、その領域の先頭アドレスは相対アドレスaとする」

と解釈して問題ないでしょうか?


Re: 質問です。教えて下さい。 jun - 2002/12/25(Wed) 21:34 No.132  

それでいいと思います。


Perlなんだけど・・ 投稿者:志穂 投稿日:2002/12/17(Tue) 03:29 No.113  
junさんは、Perlにも明るいですか?
バイナリファイルを読むところで
苦しんでるんだけど。。
unpackの使い方がよくわかんなくて。


Re: Perlなんだけど・・ jun - 2002/12/17(Tue) 22:59 No.114  

明るくありませんが、本は何冊も持ってます。
Perlに明るい人が少なくとも一人、ここ読んでます(^^)。
具体的に質問すれば、答えてくれるかも?


なんとか解決はしましたが・・ 志穂 - 2002/12/19(Thu) 14:31 No.115  

UNIX由来のFortranコンパイラが出力するバイナリ(unfomatted)
ファイルをperlで読み込むのに苦労してたんです。
こうなってるんですよ。

レコード長 | データ | レコード長
レコード長 | データ | レコード長
レコード長 | データ | レコード長
・・・
だから、データを抽出しようとおもったら、
このレコード長の情報を切り出さないといけないと。

@]cat test2.f
write(1) 'shiho'
stop
end

[@]hexdump -c fort.1
0000000 005 \0 \0 \0 s h i h o 005 \0 \0 \0
000000d

この005 \0 \0 \0 の4バイトがレコード長の情報を
もっていて、

shihoを切り出そうとおもったら、

read(IN,$buf,4) #左のレコード長情報切り出し
read(IN,$buf,5) #データ抽出
read(IN,$buf,4) #左のレコード長情報切り出し


[@]cat test2.f
write(1) 'shiho'
stop
end

[@]cat test2.pl
#!/usr/bin/perl

open(IN,"<fort.1");
read(IN,$buf,4); #左のレコード長情報切り出し
read(IN,$buf,5); #データ抽出
print $buf,"\n";
read(IN,$buf,4); #左のレコード長情報切り出し
close(IN);
[@]./test2.pl
shiho
[@]


で、質問なんですが、
32bitオペレーティングシステムの場合、レコード長は
32bitの場合がほとんど
という説明が書かれてあったんですが、
"32bitオペレーティングシステム"とはいったい
どういうものを指すんですか?
CPUが32bit or レジスタが32ビット?








Re: Perlなんだけど・・ jun - 2002/12/20(Fri) 02:20 No.119  

> read(IN,$buf,5) #データ抽出
データ長を5バイトに決めうちしているような気がするのはいいとして、

> 32bitオペレーティングシステムの場合、レコード長は
> 32bitの場合がほとんど

「レコード長は32bitを単位とする場合がほとんど」という意味でしょう。

> "32bitオペレーティングシステム"とはいったい
> どういうものを指すんですか?
> CPUが32bit or レジスタが32ビット?

文脈に依存するような気がしますが、accumulater (演算用のレジスタ)
が32ビットのCPU用に設計されたOSという感じでしょうか?


Re: Perlなんだけど・・ 志穂 - 2002/12/20(Fri) 15:16 No.120  

> read(IN,$buf,5) #データ抽出
>データ長を5バイトに決めうちしているような気がするのはいいとし
>て、

うん?
0000000 005 \0 \0 \0 s h i h o 005 \0 \0 \0

005っていうのが"データが5バイト長"っていうのを表しているので、
read(IN,$buf,5)としたのです。

     


Re: Perlなんだけど・・ jun - 2002/12/20(Fri) 21:07 No.123  

せっかくデータ長を読み込んでいるので、
それを使うべきかと思います。
複数のファイルをコマンドラインの引数で渡せるバージョン。

#!/usr/bin/perl
if (@ARGV > 0) {
foreach $file (@ARGV) {
open(IN, $file) || die "$file : $!";
while (<IN>) {
read(IN, $len, 4);
read(IN, $buf, $len); # 読み出したデータ長を使う
print $buf,"\n";
read(IN, $len, 4);
}
close(IN);
}
}


あ!!ほんとだ!!(笑) 志穂 - 2002/12/21(Sat) 02:58 No.126  

なるほど!!
せっかくレコード長読んできてるのに
利用してなかった!!(笑)お間抜けー(笑)
junさん、ありがとう!!
プログラムなおします!!


Re: Perlなんだけど・・ 志穂 - 2002/12/22(Sun) 00:28 No.130  

あっ!!まった!!(笑)
読み込んだ情報を
unpack("d",$buf)
としてやらないとだめでした。


閑話休題 投稿者:志穂 投稿日:2002/12/21(Sat) 03:14 No.127  
>アセンブリ言語の欠点として
>わかりにくい.
>大規模なプログラムが作成しにくい.

って、junさんは書かれてますが、

わかりにくいっていうのは、
ソースの可読性という点から、ですか?

大規模なプログラムが作成しにくいってことですが、
アセンブラーなプログラマー達はなんらかの工夫を
おこなってるんですか?
アセンブラのお仕事されてる人たちにすごい興味があります。
ハードの特性にあった、ドライバーを作成するような技術に
はすごい興味がありますね。LINUXでDVDを使うには、この
ドライバーが不可欠じゃないですか?これって、アセンブラ
なんでしょ?それともC言語?

時間の関係で、それほど多く、アセンブラの勉強に
時間を費やせないのですが、やりはじめるとすごく
おもしろくて。junさんのおかげで、順調に勉強
すすんでます。感謝、感謝です。


Re: 閑話休題 jun - 2002/12/21(Sat) 17:59 No.128  

linux のドライバはCで書かれています。

アセンブラは使われていないのか確認したところ、

/usr/src/linux/drivers$ find -name "*.S" -print
./usb/serial/xircom_pgs.S
./usb/serial/keyspan_pda.S
./scsi/oktagon_io.S
./acorn/scsi/acornscsi-io.S
./acorn/block/mfm.S
./acorn/block/fd1772dma.S
./sound/vidc_fill.S

少しは使われていますね(kernel 2.4.20)。ということで、
ドライバの作成に不可欠ではありません(って、作ったことないです)。

linuxではブート時の各種設定やシステムコールの入り口部分
などで使われていますが、i386の場合で210Kバイト、9000行
弱です。拙作のrvtlとあまり変わりません。
linuxは12種類程のCPUアーキテクチャをサポートしていますが、
ほとんどCで書かれているために広範囲のCPUで動作できます。
もしすべてをアセンブラで書いていたら 170MB x 12 = 2GB の
コードが必要です。(計算が単純すぎますが)

アセンブラの最大の問題は「移植が困難」ということだと思います。
抽象度をあげた言語(例えばC)で記述して、各アーキテクチャへの
翻訳はコンパイラに任せることでプログラムの生産性をあげています。
しかし、誰かがアセンブリ言語を知っている必要はあります。
誰かが鉄鉱石を掘っているおかげで料理に包丁が使えるのですから。

ところで、私は仕事でプログラムを書くことはほとんどありません。


Re: 閑話休題 志穂 - 2002/12/22(Sun) 00:27 No.129  

>>私は仕事でプログラムを書くことはほとんどありません。


ええ!!
そうなの?
もったいない。
こんなにコンピュータに精通してるなら
ネットワーク管理でもプログラマーでも
どっちでもできそうにおもうけど。


これがどうやったら777.0D0? 投稿者:志穂 投稿日:2002/12/20(Fri) 18:47 No.122  
@]cat test2.f
write(1) 'shiho'
stop
end

これはフォートランのプログラムで、
バイナリ形式で、ファイルにshihoという文字列
を出力。結果はfort.1というファイルに出力されます。

次に、この出力したファイルはバイナリ形式なので、
開いてみることはできない。
そこでつぎのコマンドhexdumpをつかいます

hexdump は、fileが指定されていればそのファイルを、指定されていなければ標準入力を読み込み、指定されたフォーマットに従ってダンプ表示します。デフォルトでは 2 バイト単位で 16 進数でダンプします。

オプション -c
1 バイト単位で ASCII キャラクタでダンプします。


[@]hexdump -c fort.1
0000000 005 \0 \0 \0 s h i h o 005 \0 \0 \0

ここで、

0000000:行番号
レコード長 : 005 \0 \0 \0 と 005 \0 \0 \0
データ : s h i h o

行番号 | レコード長 | データ | レコード長
という構成になってます。


この005 \0 \0 \0 の4バイトがデータ(shiho)のレコード長の情報"5"を
もっていてます。
つまり、
s h i h oで5文字

では整数でためしてみますね。
[]cat test5.f
integer :: a
a=7
write(1) a <------ 整数7をバイナリ形式で出力
stop
end
[]hexdump -x fort.1
0000000 0004 0000 0007 0000 0004 0000

オプション -x
バイト単位で 16 進数でダンプします。

0000 0007 で4バイト長


今度はdouble型でためします。

double precision :: a
a=777.0D0
write(1) a
stop
end

オプション-b
1 バイト単位で 8 進数でダンプします。

[]hexdump -b fort.1

0000000 010 000 000 000 000 000 000 000 000 110 210 100 010 000 000 000



0000000 行番号
010 000 000 000 レコード長 : 10(-> 8進数表示なので、10->0x08->長さ8)
000 000 000 000 000 110 210 100 データ (長さ8)
010 000 000 000 レコード長


000 000 000 000 000 110 210 100
が777.0D0を表してるようですが、
どういう変形をしたらそうなるんでしょうか?




Re: これがどうやったら777.0D0? jun - 2002/12/20(Fri) 21:57 No.124  

むー。

IEEEの浮動小数点表現について調べてください。
符号 1 ビット、指数 11 ビット、仮数 52 ビットで格納されますが、
指数ビットのバイアス、仮数部の正規化など説明するのは大変です。
nasm で 777.0 の内部表現を調べてみたところ、
00 00 00 00 00 48 88 40 でした(hex)。一致してますね。


Re: これがどうやったら777.0D0? jun - 2002/12/21(Sat) 01:50 No.125  

そういえば、64bit ではありませんが 80bit の場合のプログラムを
http://www.nk.rim.or.jp/~jun/lxasm/asm11.html に書きました。
参考になりませんか?
といっても、2年前なので自分でも忘れてしまっています(^^;


アラインとは? 投稿者:志穂 投稿日:2002/12/19(Thu) 14:38 No.116  
>というわけで、2^4=16バイトでアラインしています。

アラインというのがよくわかりません。

.align -> .align nで次の分を2のn乗の倍数の
番地におく
とあるんですが。

たとえばスタックは4バイトで整列されてますが、
この境界条件のことをいってるんですか?



Re: アラインとは? 志穂 - 2002/12/19(Thu) 14:49 No.117  

アラインメント
奇数アドレスのワードデータをアクセスするには、メモリアクセスが2回必要になり、8086と80186で最低4クロック、80286で最低2クロックの追加サイクル(メモリアクセスのウェイトによる)が必要になる。ワードデータはなるべく偶数アドレスに置く(アラインする)ようにする

ワードデータはなるべく偶数アドレスに置く=アラインする ?


Re: アラインとは? jun - 2002/12/20(Fri) 01:59 No.118  

ほとんど正解と思います。
8ビットCPUからの習慣でメモリのアドレスは1バイト単位で数えていますが、
最近のハードウェアでは、32ビットとか64ビット(グラフィックカードでは256ビット?)
の幅で一度にメモリにアクセスするため、中途半端なアドレスを先頭にすると
2回に分けてアクセスする必要が発生するためです。
私は試したことはありませんが、奇数アドレスを先頭にして32ビットのデータを
読み書き(例えば1億回)した場合と、8バイトにアラインして同じことを実行した
場合で、時間を比較してみたらどうでしょう。
データだけでなく、命令もアラインしているほうが速くなるはずです。



Re: アラインとは? 志穂 - 2002/12/20(Fri) 15:18 No.121  

>読み書き(例えば1億回)した場合と、8バイトにアラインして同じこと>>を実行した場合で、時間を比較してみたらどうでしょう。
>データだけでなく、命令もアラインしているほうが速くなるはずです。

そんな高度な技もってませーん(^^;






おひさでーす 投稿者:志穂 投稿日:2002/12/13(Fri) 18:07 No.111  
.comm x,4,4
.comm y,4,4
.comm z,4,4



$ cat main.c
int x,y,z;
int main(void){
x=2;
y=3;
z=x+y;
}
$ cat main.s
.file "main.c"
.version "01.01"
gcc2_compiled.:
.text
.align 4
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
movl $2, x
movl $3, y
movl y, %eax
addl x, %eax
movl %eax, z
popl %ebp
ret
.Lfe1:
.size main,.Lfe1-main
.comm x,4,4
.comm y,4,4
.comm z,4,4
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-85)"

さいごの
.comm x,4,4
.comm y,4,4
.comm z,4,4
なんですが、

4バイト分メモリ領域を確保せよってのは
わかるんですが、

最後の4はなにを意味してるんでしょう?
コンパイラ特有のもの?


Re: おひさでーす jun - 2002/12/13(Fri) 22:15 No.112  

まあ、コンパイラというかアセンブラ特有のものとです。
アラインメントを調整しています。

as.infoによると:
-------------------------------------------------------
When using ELF, the `.comm' directive takes an optional third
argument. This is the desired alignment of the symbol, specified as a
byte boundary (for example, an alignment of 16 means that the least
significant 4 bits of the address should be zero). The alignment must
be an absolute expression, and it must be a power of two. If `ld'
allocates uninitialized memory for the common symbol, it will use the
alignment when placing the symbol. If no alignment is specified, `as'
will set the alignment to the largest power of two less than or equal
to the size of the symbol, up to a maximum of 16.
-------------------------------------------------------
というわけで、2^4=16バイトでアラインしています。

インテル系のCPUは奇数アドレスを先頭とするメモリアクセス
が可能ですが、8バイトや16バイトというキリのいいアドレス
からアクセスすると速くなるためです。