アセンブラ初心者スレッド 2©2ch.net

■ このスレッドは過去ログ倉庫に格納されています
2017/04/13(木) 17:35:55.70ID:1WMn3pSz
初心者OK!質問大歓迎!のアセンブラのスレッドです。
基本情報の勉強中の人、PICやH8を勉強中の学生などなど…

前スレ
アセンブラ初心者スレッド
http://echo.2ch.net/test/read.cgi/tech/1314502612/

関連スレ
アセンブラ 13
http://echo.2ch.net/test/read.cgi/tech/1314512680/
2018/09/27(木) 12:02:53.61ID:yf1/OigC
みんなここを読んでいるのが自分と同じ業界の専門家だと思っているのかな?
初心者スレなんだから上級者は来るなよ
2018/09/27(木) 12:09:02.87ID:JRG0evD8
>>250
PDFファイルは、Adobe純正のものではなく、SumatraPDFがお勧め。
場合によっては、それと、PDF-XChange Viewerとの両使いも便利。

2つのビューアーがあると、同じファイルの異なるページを同時に
見ることが出来る。

特に、SumatraPDFは、ネットブラウザやWindows用の
テキスト・エディタなどとよく似た使い勝手で便利。
2018/09/27(木) 12:29:35.23ID:nUEopGTJ
>>245
ISAってISAバスしか思い浮かばないんだがw
アセンブラやるなら、ASMソースとかニーモニックコードとかのほうが一般的だろうね
254デフォルトの名無しさん
垢版 |
2018/09/27(木) 12:30:49.36ID:lrUHFZkm
自分の知識不足を棚に上げて絡む馬鹿アスペ
2018/09/27(木) 12:34:10.71ID:JRG0evD8
お互いに知識に偏りがあるからしょうがないんだよ。

だから、分からない言葉があれば言葉の確認が必要となると思う。

名プログラマやIQ170の人でも、知らない分野では知識不足はあるよ。
2018/09/27(木) 12:51:27.68ID:BciEc+9A
>>255
うん、78K0S、8051、AVRがなじみの無いCPUと聞いてショックを受けている。
2018/09/27(木) 12:59:24.22ID:JRG0evD8
>>256
78K0Sが、NEC製のマイコンだということだけは、昔知ったことがある。
でも、昔といってもとても最近。

8051は、PC-8801のシリアルコントローラに、似たような型番のものがあったような
気がしたが、たぶん関係ないけど、正確な型番は思い出せない。
2018/09/27(木) 13:05:15.67ID:JRG0evD8
>>256
8251が、Serial Controller、8255 がParallel Controller、
8085、8086がCPUだった。

8051というのは、知らないかも。
2018/09/27(木) 16:23:11.07ID:JRG0evD8
>>236
命令が多いのは、基本的には、MMX, SSE〜SSE4, AVX, AVX2, AVX512 が
追加されたことが大きい。その辺の命令はまずは、無視。
整数命令(汎用命令)から見るといい。
なおその前に、どんなレジスタがあるかについて勉強する。
「basic execution environment」みたいな節に書いてある。
レジスタは拡張につぐ拡張があったので、理解するのにそれなりの時間がかかる。

アルファベットごとの命令表の、mov, add, sub, mul, div, imul, idiv,
push, pop, call, jmp, jcc 系を中心に見た後、ModRMについて書かれた節を見る。
最初は、16BIT/32BIT の ModRM、SIB について理解する。
その際、operand prefix, address prefix について理解する。
その後、64BIT の long mode, compatible mode の説明を読んだ後、
64BIT の ModRM, SIB について、REX prefix とまとめて理解する。


ちなみに、以下は後回しにする:
fadd, fsub, fmul, fdiv, fldp, fld, fstp, fld は、x87 FPU。
padd, psub は、MMX, addps, addss, subps, subss, mulps, mulss は、SSE系。

mm0〜mm7, xmm, ymm, zmm, に関する movxxxx も最初は無視。
これらの movxxxx は、アルファベット順の命令ごとについての書かれた章
のに解説が書かれているが、アラインだとかの説明が難しい。
実は、同じマニュアルセットの全然別の場所にこれらの movxxxx 命令の
説明が割りと平易な言葉で書かれているので参考になる。ただし、英語。
翻訳版の日本語だと余計に意味が分からないかもしれないの注意。

AVX系命令は、まず、VEX, EVEX prefix を読む。REX prefix が完全に理解
してないと理解は難しいと思う。
2018/09/27(木) 16:33:04.36ID:JRG0evD8
>>259
ちなみに、命令表は、

1. マニュアルの中心付近にアルファベット順に書かれているもの
2. ずっと後の付録の当たりに確か2進数の BIT 的に書かれているもの
3. マシン語から命令へ逆にたどれるもの

の3種類ある。

以上の命令表のうち、最初に読むべきなのは、上記の「1」のもの。
その命令表を見るための準備も必要。
マニュアルをよく探すと、/0〜/7 の意味、+b, +w, +d, +q の意味などが書かれた
部分がある。基本的には、そこを読まないとちゃんとした理解は出来ない。
それだけでなく、命令表も2部に分かれているような独特の読み方がある。それも、
上記の説明と同じような場所にまとめて出ている(分かりにくいが)。
(オペランドの種類を1つの表では表しにくいので、ポインタ参照のような感じで
記号で、後の表の行を指定するような感じになっている。)

REX prefixについては、AMD社のAMD64のManualも当然参考になる。

REX prefix は、色々と注意が必要で、細かい点を正確に理解するのは
しばらく時間がかかる。
261デフォルトの名無しさん
垢版 |
2018/09/27(木) 16:36:18.33ID:qYKYy6B3
墓場に一番近いスレ
2018/09/27(木) 16:49:13.96ID:JRG0evD8
>>260
分かっているかもしれないが、x86系では、if()文に相当するものは、
基本的には、cmp aaa,bbb 命令で、(仮想的に)引き算をした後、
結果に基づいて、
zf, cf, sf, of(zero flag, carry flag, sign flag, overflow flag) など
のフラグ類に値が設定されて、そのあと、フラグ類に基づいて、
jz, jnz, jg, jge, jl, jle, ja, jae, jb, jbe などで jump (branch) する仕組み。

cmp命令は、ほとんど sub と同じだが、sub は、結果を destination
に実際に代入するのに対し、cmpは、結果はフラグ類以外にはどこにも
返さない。

subでも、フラグ類は設定されるので、上記の条件ジャンプは cmpと
全く同様に使える。実は、add や test, and, xor などでも、
条件ジャンプは行える場合がある。

整数で多倍長の加算を行うには、caryy flag を使って、add, adc を続けて行う。
減算の場合は、sub, sbb。

add ・・・
adc ・・・
adc ・・・
adc ・・・
・・・

みたいにすると、どれだけでも桁数は増やせる。

掛け算や、割り算の多倍長計算については、もっと数学的に行うが足し算と
引き算だけは、簡単に行える。
2018/09/27(木) 17:57:17.06ID:ry/jwNzc
そもそも>>1
>PICやH8を
などと書いてあるのに「組み込み用プロセッサなんて知らなくて当然だ」的な態度は回答者としてどうなんだ?
2018/09/27(木) 19:29:19.93ID:fZkL81UT
まずはCコンパイラにアセンブラ出力させて、
それを元に命令の動作をリファレンスマニュアルで確認していった方が楽なのでは?
いきなりマニュアルだけ読むだけだと大変だろうね
ちなみにC++よりもC言語の方がアセンブラ出力を読むのは簡単なはず
あと、Visual C++なら32bitのx86でやった方がいいよ
64bitのアセンブラ出力はそのままアセンブラでアセンブルできないはず
32bitならVisual C++のアセンブラ出力をアセンブラでそのままアセンブルできる
2018/09/27(木) 19:51:12.89ID:fZkL81UT
gccなら64bitでもアセンブラ出力できる
AVRを使ったことがあってgcc使ってたのならLinux上でgcc使ってみるのもあり
この場合、コマンドライン主体になるけどね
Linuxなら
objdump -M intel -d hogehoge
という感じで実行ファイルやオブジェクトファイルの逆アセンブルができる

gccでx86のアセンブラ出力をするときは-masm=intelのオプションを忘れずに
やり方はこんな感じ
gcc -S -masm=intel -o hogehoge.s hogehoge.c
このアセンブラリストを
as -a=hogehoge.lst -o hogehoge.o hogehoge.s
とアセンブルできる
これでできたオブジェクトファイルを
gcc -o hogehoge hogehoge.o
これで実行ファイルが完成

gdbではdisasで逆アセンブルできる
逆アセンブルする前にset disassembly-flavor intelを1回入力してやれば
それ以降の逆アセンブルがintel記法で出力される

最後に、WindowsとLinuxでは関数の呼び出し規約が違ったりするのをお忘れなく
2018/09/27(木) 19:58:33.40ID:fZkL81UT
gccなら上のように64bitのx86_64のアセンブラ出力もasでアセンブルできるよ
267デフォルトの名無しさん
垢版 |
2018/09/27(木) 20:02:31.89ID:fZkL81UT
x86のアセンブラで注意が必要なのは
例えば、
mov eax, data01
とあった場合、data01のメモリの内容がeaxに入る
決してdata01のアドレスではない
data01のアドレスを読み込みたかったら
mov eax, offset data01
こうすること
2018/09/27(木) 23:08:23.40ID:F6rrREqm
まただよ…
269デフォルトの名無しさん
垢版 |
2018/09/28(金) 15:40:04.81ID:O5kQkBkV
lea だろう常考
2018/09/29(土) 06:54:45.13ID:31v81hqm
32bitでは
lea eax, hogehoge
よりも
mov eax, offset hogehoge
の方が命令が1バイト少なくなる

64bitでは
lea rax, hogehoge
だとアドレスはRIP相対の32itDISPになって7バイト
mov rax, offset hogehoge
だと64bitのimmを読み込むので10バイトになって3バイト長くなるけど
2018/09/29(土) 07:01:44.57ID:31v81hqm
gccやgasだとx86_64で64bit immを読み込む命令のニーモニックが違うんだよな
movabs rax, offset flat hogehoge
gasだとこうなるかな
272デフォルトの名無しさん
垢版 |
2018/09/29(土) 09:36:52.97ID:31v81hqm
>>271
movabs rax, offset flat: hogehoge
でした
2018/09/29(土) 10:00:32.42ID:31v81hqm
Linuxでx86_64のgccでコンパイルしたものをとアセンブラのリンクする時に
lea rax, hogehoge
これや
mov rax, hogehoge
これをやるとリンク時にエラーが出るね

lea rax, hogehoge[rip]
mov rax, hogehoge[rip]
こうしないといけないみたい
2018/09/29(土) 12:31:21.31ID:1LSQxS0k
>>273
x64 独特の事情からかんがみて、言いたいことは分かってるつもりだが、
一応、MASM の元々の書き方の仕様では、C言語で言うと、

mov rax, hogehoe[rip]  ; rax = *(rip + &hogehoge)
mov rax, hogehoe     ; rax = *(&hogehoge)

の「意味」なので、本来は、働きが異なるのでその辺は注意を払う必要がある。

x64 だと、メモリオペランドでは、「絶対アドレス指定」より、
「rip 相対」が短いコードになり、なおかつその場合は、
disp 部分に 64BIT値が入れられないので色々と話が複雑になるけれど。

( gcc(gas)でどう意味に解釈されているかは知らないけど。 )
2018/09/29(土) 12:34:45.26ID:1LSQxS0k
>>274
元々の、masm の syntax 的には、
   mov rax,[addr]    ;絶対アドレス指定
と、
   mov rax,[rip + (addr - offset label1)]   ;相対アドレス指定
label1:

が rax に入る値が同じになるハズ。
2018/09/29(土) 12:40:11.70ID:1LSQxS0k
>>274
ちなみに、x86(IA32)モードでは、

[addr]

の ModRM のオペランドのマシン語 encode と全く同じ encode が、
x64(AMD64)では、

[rip + rel32]

になってしまって、しかも後者には、rel32 のための disp32 の4BYTE値が、
ModRM の直後に埋め込まれる仕様になっている。


これは、色々と誤解を招きやすい仕様で、初心者に混乱なく説明するのが難しくなってしまう。
2018/09/29(土) 13:18:43.07ID:31v81hqm
>>274
MASMだとx64で
mov rax, hogehoge
こう書くと
mov rax, [hogehoge+rip]
の意味になるよ
マシン語は48 8B 05 xxxxxxxxでRIP相対の32bitDISPの解釈になる

Linuxのgccやgasだと
mov rax, hogehoge
これが32bitの絶対アドレスと解釈される模様
マシン語は48 8b 04 25 xxxxxxxxと
スケールインデックスの基数を持たない32bitDISPになってしまってる
これだとRIP相対にならないのでリンク時にエラーになる
mov rax, hogehoeg[rip]
これだとマシン語は48 8b 05 xxxxxxxxとRIP相対の32bitDISPになる

Linuxのgccやgasで64bit絶対アドレス読み込みや64bit絶対アドレス指定のデータロードは別のニーモニックになる
movabs rax, offset flat: hogehoge
マシン語は48 b8 xxxxxxxxxxxxxxxx

movabs rax, hogehoge
マシン語は48 a1 xxxxxxxxxxxxxxxx
(64bit絶対アドレス指定のデータロードはraxのみ)
2018/09/29(土) 13:25:59.67ID:31v81hqm
ちなみにMASMで
mov rax, offset hogehoge
こう書くと
マシン語は48 b8 xxxxxxxxxxxxxxxx
となる
2018/09/29(土) 13:37:18.16ID:31v81hqm
MASMは実用性を重視した仕様で
gccやgasはより厳密な仕様になってる言えるな
280デフォルトの名無しさん
垢版 |
2018/09/29(土) 13:55:45.43ID:31v81hqm
そもそもMASMのx64版で
mov rax, [hogehoge+rip]

mov rax, hogehoge[rip]
こうするとエラーになるよ
2018/09/29(土) 14:34:50.49ID:1VwJZM7J
>>277
>MASMだとx64で
>mov rax, hogehoge
>こう書くと
>mov rax, [hogehoge+rip]
>の意味になるよ
>マシン語は48 8B 05 xxxxxxxxでRIP相対の32bitDISPの解釈になる


言いたいことが間違っているわけではないけど、厳密には、

MASMだとx64で
  mov rax, hogehoge
と書くと、
  mov rax, [rip + (offset hogehoge - offset label1)]
label1:


の「意味になる」。
2018/09/29(土) 14:36:51.71ID:1VwJZM7J
そもそも、IA32までは、jmp, call 以外ではRIP相対は無かったので、
RIP相対については、masm も gas も、今のところ書式(syntax)的に
無理がある気がする。
2018/09/29(土) 14:39:38.93ID:1VwJZM7J
つまり、今のところメモリオペランドの syntax に一貫性がなくなってきてしまっていると思う。
2018/09/29(土) 15:05:27.10ID:31v81hqm
>>281
つっこむならMASMで試してからつっこめよ
そもそもripはundefined sysmbolになって使えないっての

あなたのつっこみは話がややこしくなるだけだよ
2018/09/29(土) 15:07:28.65ID:1VwJZM7J
>>284
「意味」になるだけで、通じないことは知ってるよ。

そもそも、masm は [ ] の中に、offset hogehoge 書くと、その通りの
意味にはならないことがあるよ。
286デフォルトの名無しさん
垢版 |
2018/09/29(土) 15:08:54.79ID:31v81hqm
MASMは実用性を重視して
mov rax, hogehoge
こういう書式

gcc、gasはより厳密に
mov rax, hogehoge[rip]

あくまでそういう決まりごとってこと
書式は違ってくるが
そもそもVisual C++やMASMとgcc、gasでは違うところが多すぎるから問題ない
gccやgasではアセンブラはデフォルトではAT&T記法だしな
2018/09/29(土) 15:10:56.60ID:31v81hqm
>>285
何、その意味不明な記述
[ ]の中にoffset入れるわけないだろ
そういう突っ込みはいいから。
あなたのつっこみは話をややこしくするだけだろ
2018/09/29(土) 15:13:20.76ID:31v81hqm
こういう変なのがアスペってやつか
2018/09/29(土) 15:18:29.23ID:1VwJZM7J
>>287
C 言語での、*(&hogehoge) の MASM 版は、意味的には、

[offset hogehoge]

になって、ちょうどそれは、「hogehoge」 の意味に戻るはずなんだけど、
実際に masm でやってみると、変になる。記憶によると、masm では、

[hogehoge]

が hogehoge と書いたのと同じ意味になったはず
(論理的にはそんなはずは無いんだけども)。
2018/09/29(土) 15:19:17.57ID:1VwJZM7J
>>288
アスペかも知れんけど、数学は主席みたいな感じだったよ。
2018/09/29(土) 15:23:02.46ID:P6L1chXc
C言語との対応関係も知らずにアセンブラ語ってたとは驚き
で、また火病って連投してるね
2018/09/29(土) 15:24:36.40ID:1VwJZM7J
こういうのが2ch/5chの問題点なんだよな・・・。
2018/09/29(土) 15:29:01.40ID:31v81hqm
>>289
あなたの書いてることの意味はもともとわかってるっての
MASMではと書いておきながらMASMで通らない命令を書いて人の発言に横槍入れて
したり顔してるのがおかしいってだけ
2018/09/29(土) 15:32:55.38ID:P6L1chXc
>>292
普通だったら
&array[x]
はどうやって書くか考えるよね
295デフォルトの名無しさん
垢版 |
2018/09/29(土) 15:37:30.74ID:31v81hqm
>>291
もともとわかってることなのに
実際のアセンブラでアセンブルできない命令を書いて因縁つけてスレを混乱させてるのは
ID:1VwJZM7Jの方だぞ
2018/09/29(土) 15:38:31.02ID:31v81hqm
実際に試してみればわかることだよ
2018/09/29(土) 15:41:02.87ID:31v81hqm
ID:1VwJZM7Jは論理的にとか書いてるが
実際のアセンブラの仕様を無視して、アセンブラで通らない命令書いてドヤ顔してるやつ
コンピュータなんて論理的におかしい命令とか普通にあるだろ
アスペはそういうのが我慢ならないらしい
2018/09/29(土) 15:43:55.02ID:P6L1chXc
>>295
そんな状態ならx86_64については語らないでくれ
正直迷惑
2018/09/29(土) 15:46:13.22ID:31v81hqm
>>298
あなたもx86_64のアセンブラの仕様関して全く理解してないのはわかった
あなたもしたり顔で語るなよ
ここに書かれてる命令を実際にアセンブルしてその結果を見れば誰が正しいことを言ってるかわかるはず
2018/09/29(土) 15:50:43.93ID:31v81hqm
>>298

>>280にも書いたが
MASMでは
mov rax, hogehoge[rip]
こんな書き方や
mov rax, [hogehoge+rip]
こんな書き方をすると
error A2006:undefined symbol : rip
とエラーになるんだよ
2018/09/29(土) 15:50:52.23ID:P6L1chXc
>>299
>>274が理解できてなくて「わかってる」はずないだろ
302デフォルトの名無しさん
垢版 |
2018/09/29(土) 15:52:36.05ID:IuTgmxg/
論理的におかしい命令なんかない
処理されるまでの過程は別にして計算機は命令されたとおりに動く

処理結果がおかしいのはキミラのオツムの問題

そもそもアセンブラなんか
キャッシュミスをできるだけむりやり回避するためにインラインアセンブラ書くとか
非常に明確な理由がないかぎりまず使われることなんかまずない

つまりココではアホ同士がアホなことでもめてる
2018/09/29(土) 15:54:58.28ID:31v81hqm
>>301
> x64 独特の事情からかんがみて、言いたいことは分かってるつもりだが、
> 一応、MASM の元々の書き方の仕様では、C言語で言うと、
>
> mov rax, hogehoe[rip]  ; rax = *(rip + &hogehoge)
> mov rax, hogehoe     ; rax = *(&hogehoge)
>
> の「意味」なので、本来は、働きが異なるのでその辺は注意を払う必要がある。

そもそもMASMでは
mov rax, hogehoe[rip]
こんな記述は未サポート

mov rax, hogehoe
これが*(rip + hogehoge)の意味
2018/09/29(土) 15:57:13.97ID:31v81hqm
>>302
アスペ君は
mov rax, hogehoge
これが*(hogehoge + rip)の意味になるところが気に入らなくて突っ込みいれてるだけ
でも、実際に仕様なのだからしょうがないってこと
2018/09/29(土) 16:01:34.18ID:P6L1chXc
>>273みたいなこと書く奴が「理解できてる」はずないだろw
今回も「リンク時にエラーが出る」とか言ってさ
306デフォルトの名無しさん
垢版 |
2018/09/29(土) 16:06:06.66ID:31v81hqm
>>305
MASMでは
mov rax, hogehoge
こう書くのが正解なんだが
Linuxでgccとgas使ってプログラム組むと
mov rax, hogehoge
これを書くとリンク時にエラーが出る
理由は>>277に書いてある

Linuxでgcc、gasでは
mov rax, hogehoge[rip]
これでMASMのときのmov rax, hogehogeと同じマシン語が生成されえる
コンパイラやアセンブラが違えば仕様が違うってこと
2018/09/29(土) 16:18:56.60ID:P6L1chXc
32bitではきちんと理解してなくてもなんとかなったってだけなの
x64知らないなら出てこなきゃいいのに
2018/09/29(土) 16:24:58.15ID:31v81hqm
>>307
x86_64をわかってないのはあなただろ
MASMでは
mov rax, hogehoge
こう書く仕様だっての

gcc、gasでは
mov rax, hogehoge[rip]
こう書くのが仕様

ただそれだけ
マシン語ではどちらも48 8b 05 xxxxxxxxとRIP相対の32bitDISPになる
2018/09/29(土) 16:32:57.40ID:31v81hqm
offsetを使ったものも

MASMでは
mov rax, offset hogehoge
これでマシン語は48 b8 xxxxxxxxxxxxxxxxと64bit絶対アドレスになる

gcc、gasでは
movabs rax, offset flat: hogehoge
これでマシン語は48 b8 xxxxxxxxxxxxxxxxと64bit絶対アドレスになる

leaを使うと
MASMでは
lea rax, hogehoge
これでマシン語は48 8d 05 xxxxxxxxとRIP相対32bitDISPになる

gcc、gasだと
lea rax, hogehoge[rip]
これでマシン語は48 8d 05 xxxxxxxxとRIP相対32bitDISPになる
2018/09/29(土) 16:43:03.59ID:31v81hqm
x86_64のRIP相対アドレッシングは歴史的には
32bitの時の32bit絶対アドレッシングの仕様を変更してRIP相対をねじ込んだ形だからね
アセンブラの記述的に、論理的におかしくてもしょうがないんだよ
論理的なものよりも実用性を重視したのがMASM
より論理的に厳密にしたのがgasということだろうな
2018/09/29(土) 17:11:34.41ID:kF9GSkBg
ちょっと質問なんだけど
dataセクションは32bitアドレス内にないとアクセスできないってこと?

extern int aaa[10];
int bbb (int i) {return aaa[i];}

このコードがこんな感じになってたんだけど

00000000004011a0 <bbb>:
4011a0: 48 63 ff movslq %edi,%rdi
4011a3: 8b 04 bd 40 40 40 00 mov 0x404040(,%rdi,4),%eax
4011aa: c3 retq

aaaがdataセクションの0x404040にあったからこうやってアクセスできたけど
32bit超えてたらこの命令は翻訳できない?
2018/09/29(土) 17:23:41.07ID:31v81hqm
>>311
アセンブラのみではそういうことはないけど、C言語とリンクする場合はそうなるね
64bitでも通常はグローバル変数などのシンボルやジャンプ先のラベルは32bitを前提としてコンパイルされている
x86_64だとRIP相対の32bitDISPで届かないところにはアクセスできない
他のCPUでも似たようなもの

Windowsだと回避方法はない
LinuxだとHPCなどで-mcmodel=mediumを指定することで回避できる方法はあるけどね
2018/09/29(土) 17:34:12.56ID:mdNhb+fJ
>>290
首席のことか
2018/09/29(土) 17:35:24.77ID:31v81hqm
>>311を俺の環境でgccでコンパイルしてみたらこうなった
オブジェクトファイルなのでアドレスは00 00 00 00のまま
gccのバージョンは7.3.0

0000000000000000 <bbb>:
0: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 7 <bbb+0x7>
7: 48 63 ff movslq %edi,%rdi
a: 8b 04 b8 mov (%rax,%rdi,4),%eax
d: c3 retq
2018/09/29(土) 17:36:30.80ID:kF9GSkBg
ありがとう
>>311のはa.outにしてアドレスが分かるようにした後だったから
2018/09/29(土) 17:37:16.65ID:31v81hqm
AT&Tニーモニックの貼ってしまった

Intelニーモニックはこっち
0000000000000000 <bbb>:
0: 48 8d 05 00 00 00 00 lea rax,[rip+0x0] # 7 <bbb+0x7>
7: 48 63 ff movsxd rdi,edi
a: 8b 04 b8 mov eax,DWORD PTR [rax+rdi*4]
d: c3 ret
2018/09/29(土) 17:42:37.03ID:kF9GSkBg
一旦axに入れてるんだ
そっちの方が遠くまでアクセスできそう
俺のはlinuxだからかな
gccは8.2.0だけど7.3でも>>311のようになりそう
2018/09/29(土) 18:11:22.67ID:31v81hqm
俺のもLinuxだよ
2018/09/29(土) 18:29:50.29ID:kF9GSkBg
7.3でも5.3でも>>311のになった
configure 設定: ../gcc-7.3.0/configure --prefix=/usr --libdir=/usr/lib64 --mandir=/usr/man --infodir=/usr/info --enable-shared
--enable-bootstrap --enable-languages=ada,brig,c,c++,fortran,go,lto,objc --enable-threads=posix --enable-checking=release
--enable-objc-gc --with-system-zlib --enable-libstdcxx-dual-abi --with-default-libstdcxx-abi=new --disable-libunwind-exceptions
--enable-__cxa_atexit --enable-libssp --enable-lto --disable-install-libiberty --with-gnu-ld --verbose --with-arch-directory=amd64
--disable-gtktest --disable-multilib --target=x86_64-slackware-linux --build=x86_64-slackware-linux --host=x86_64-slackware-linux
スレッドモデル: posix
gcc バージョン 7.3.0 (GCC)

configure 設定が違うのかな
2018/09/29(土) 18:31:39.06ID:1VwJZM7J
>>303
>mov rax, hogehoe
>これが*(rip + hogehoge)の意味

それは明らかに間違っているよ。

正しくは、>>281 のように、

MASM だと 64bit mode で
  mov rax, hogehoge
と書くと、
  mov rax, [rip + (offset hogehoge - offset label1)]
label1:

の「意味」になって(ただし、実際の masm ではこの書き方はエラーになるはず)、

C言語で書けば、
rax = *( rip + (&hogehoge - &label1) )
label1:

の「意味」になる。
2018/09/29(土) 18:37:57.88ID:1VwJZM7J
>>320
理解のポイントは、(64BIT)命令ポインタ rip は、CPUが、ModRM
の間接(メモリ)オペランドを解釈する時には、命令の直後の
アドレスを指しているかのようにみなされて、丁度、

rip = offset label1

または、

rip = &label1


であるかのように解釈されるということ。
322デフォルトの名無しさん
垢版 |
2018/09/29(土) 18:52:23.15ID:31v81hqm
>>320
RIP相対32bitDISPって書いてるんだからわかってるんだよ、そんなこと
わかりきったことをしたり顔で書いてんじゃねーよ
2018/09/29(土) 19:02:53.64ID:31v81hqm
>>319
自分でビルドしたやつじゃないけど
gcc -vをやると
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.3.0-27ubuntu1~18.04'
--with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++
--prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared
--enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie
--with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror
--with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic
--enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release
--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
2018/09/29(土) 19:23:24.57ID:kF9GSkBg
分かった-fPICつけると>>314と同じになった
2018/09/29(土) 19:30:06.39ID:P6L1chXc
MASMはデフォルトがrip相対だからな
offset演算子使った段階でアドレスではなくただの数値になってるのが理解できんのか
だから絶対アドレスになんだよ
2018/09/29(土) 19:42:48.86ID:31v81hqm
>>325
ただの数値じゃないぞ
だって再配置される時に64bitの絶対アドレスが再配置されたアドレスに置き換わる
だからただの数値じゃない、64bit絶対アドレスとして認識されてるはず
2018/09/29(土) 19:54:13.97ID:31v81hqm
変な突っ込みする人がいるから書くが
CPUの命令的にはx86_64で
mov rax, offset hogehoge
これは64bitのimmを読み込むマシン語に変換される
要するにただの64bitの数値を読み込む命令
マシン語は48 b8 xxxxxxxxxxxxxxxx
ただ、アセンブラはちゃんと64bit immの部分が64bitの絶対アドレスということを認識してる
だから再配置された時に64bit絶対アドレスが再配置後のhogehogeのアドレスに置き換わる
2018/09/29(土) 20:19:25.44ID:31v81hqm
こんなことみんな知ってるとは思うが
実際に64bit絶対アドレスが確定するのはプログラムがメモリ上にロードされる時
このときに、絶対アドレスなどの情報が配置されるアドレスによって正しい値に書き換えられる
2018/09/29(土) 21:07:16.90ID:P6L1chXc
そもそも
lea rax, [hogehoge]
って書いときゃNASMでも通るのに
>data01のアドレスを読み込みたかったら
>mov eax, offset data01
>こうすること
なんて教えようとするのかね?
2018/09/29(土) 21:11:28.97ID:P6L1chXc
MASMって
mov eax, [rsp][16]
mov eax, [rsi][rcx]
みたいな変態な表現も通るんだよな
2018/09/30(日) 00:47:29.69ID:KtGjBt6/
Microsoft (R) Macro Assembler (x64) Version 12.00.40629.0
mov al, hogehoge
mov al, [hogehoge]
mov rax, offset flat:hogehoge ; error A2006:undefined symbol : flat
lea rax, [hogehoge]
lea rax, offset flat:hogehoge ; error A2006:undefined symbol : flat
lea rax, hogehoge

14.00.24210.0でも同じだな
2018/09/30(日) 00:54:08.42ID:KtGjBt6/
clが吐いた.codでは
lea rax, offset flat:hogehoge
みたいな表記になってるけど、ml64は受け付けない
2018/09/30(日) 01:03:38.57ID:KtGjBt6/
mov eax, offset hogehoge
とやってもエラーも出ないんだよね 当然だけど
0000001A 48/ B8 0000000000000000 E mov rax, offset hogehoge
00000024 B8 00000000 E mov eax, offset hogehoge
334236
垢版 |
2018/09/30(日) 01:18:13.92ID:PppEulsk
なんか説明が不適切だったせいで偉いことになってしまった・・・すまん

とりあえずAMD64のプログラミングマニュアルとIA32/EM64Tの日本語プログラミングマニュアルはダウンロードしてあります

やりたいことは演算ではなくて特殊?な例外処理です。C風に書くと
unsigned int *a;
unsigned int b;
&a = 0x00001000; // アドレスをセット
*a = 0x00888888; // 0x00001000へ値を書き込み
b = *(&a + 1); // 0x00001004の値を読み出し。読み出される値は0x00001000の値に0x0100を加算した物
// bの中身は0x00888988
みたいな感じかな。メモリの読み書き動作に任意の処理を挟みたいです。自分なりにこのような動作をさせる方法を考えた結果
・該当する仮想アドレスにメモリを割り当てない
・アクセスすると発生するページフォールトをハンドリングする
・ハンドラ中で値の処理とアクセス元のコードが行うつもりだった読み書き動作もする
・ページフォールトを発生させた次の命令から実行を再開する
となったのですがこれらを高級言語のみで実装するのは無理そうな気がするのでアセンブラを読み書きできる必要があるかなと・・・
各OSごとの例外処理がらみの情報も必要ですがこの辺もなかなか見つけられないです
2018/09/30(日) 04:51:47.08ID:fqhkGGw5
>>322
64bitのcl.exeが吐き出すアセンブラ出力はml64.exeでそのままではアセンブル通らないよ
何箇所か、修正が必要になる
ちなみに32bitのcl.exeが吐き出すアセンブラ出力はそのまま32bitのml.exeでアセンブルできる



>>333
mov eax, offset hogehoge
これをx64用のml64.exeでアセンブルしてもエラーは起きないが
リンク時にこのエラーが出るよ
error LNK2017: 'ADDR32' relocation to
'hogehoge' invalid without /LARGEADDRESSAWARE:NO
LINK : fatal error LNK1165: link failed because of fixup errors
64bitのアドレスを32bit絶対アドレスに切り詰めてるのだから当たり前だけど

mov rax, offset hogehoge
これは全く問題ない
アセンブルもリンクも正常に行われるし、正常にプログラムを実行できる
2018/09/30(日) 17:26:28.46ID:KtGjBt6/
>>335
NASM(bits64, default rel)だとエラーになるよ
mov rax, offset hogehoge ; error: comma, colon, decorator or end of line expected after operand
lea rax, hogehoge ; error: invalid combination of opcode and operands
lea rax, [hogehoge] ⇒ 488D05

mov al, hogehoge ⇒ B0
にアセンブルされたりもするけど

MASMでもlea rax, [hogehoge]やmov al, [hogehoge]はNASMと同じマシン語になるはず

Windows 64bitはrip相対使ってるのに、MASMで簡単に絶対アドレスが登場するのがおかしいと思わないのかね
2018/09/30(日) 21:29:51.77ID:KtGjBt6/
>>334
いまいちやりたいことが分からないんだけど、Windowsでアクセス違反をハンドリングするのは
https://docs.microsoft.com/ja-jp/windows/desktop/Memory/reserving-and-committing-memory
が参考になるんじゃないかな
__except()のフィルタ関数でアクセス違反をチェックして、対象範囲のアドレスだったらVirtualAllocで
コミットして__except()にEXCEPTION_CONTINUE_EXECUTION返せば再実行される
対象範囲外のアドレスはEXCEPTION_CONTINUE_SEARCHを返す必要がある
メモリは事前に予約してないと例外から回復できないみたい

構造化例外処理は
http://www.ne.jp/asahi/hishidama/home/tech/vcpp/seh.html
https://msdn.microsoft.com/ja-jp/library/swezty51.aspx
を読んでみて
2018/10/01(月) 04:48:19.14ID:gNvpqBnl
>>336
LinuxのNASMとMASMは構文違うよ

NASMだと
mov rax, hogehoeg
マシン語は48 b8 xxxxxxxxxxxxxxx
これでraxにアドレスが入る

WindowsのMASMだと
mov rax, hogehoge
マシン語は48 8b 05 xxxxxxxx
hogehogeのメモリの内容がraxにロードされる
MASMの場合、
mov rax, offset hogehoge
これだとマシン語は48 b8 xxxxxxxxxxxxxxxx
これにしないとNASMのmov rax, hogehogeと同じマシン語にならない
2018/10/01(月) 05:43:56.26ID:gNvpqBnl
みんなはじめて読むMASMからやり直しだなw
2018/10/01(月) 05:51:48.63ID:gNvpqBnl
>>336
RIP相対32bitdispだとアクセスできない場合が出てくる
シンボルがRIP相対2GBに制限されるなどはあくまでCコンパイラの制限であって
アセンブラはその制限を受けない
実際にWindowsのEXEファイルは64bit絶対アドレスに対応してて
きちんと再配置してくれるわけだし
2018/10/01(月) 06:38:07.64ID:Z1gvrlLR
これこそアスペって奴だよな
質問とは関係ないCPU持ち出して勝手に「語り」をはじめたり、32bitでは1バイト短くなるだの
実用的には0.001%程度しか影響なさそうな絶対アドレスの方が速いだの、C/C++とリンクして使うのが
普通なのに「シンボルがRIP相対2GBに制限されるなどはあくまでCコンパイラの制限であってアセンブラはその制限を受けない」とか
初心者そっちのけで有害としか思えないような方法垂れ流したりと、他人の迷惑とか全く考えられないんだから

初心者にはMASMとNASMで同じように使えればそれで十分
完全に同じマシン語になるかどうかなんて知るか
特に絶対アドレスなんてWin64には不要と考えるべき
初期化領域以外の動的確保されたメモリはポインタ経由のアクセスが基本なんだから
2018/10/01(月) 06:45:27.19ID:Z1gvrlLR
>>334
こういう状態なんで、334は全く悪くないから気にしなくていいよ

アクセス違反を検出して対応するのは、使ってみたいところがあったのでちょうどいい機会だった
一応自分の書いたテストプログラムを上げとくね
https://pastebin.com/b5gZXxCF
2018/10/01(月) 06:51:19.23ID:gNvpqBnl
>>341
>>338が理解できないのか?
LinuxのNASMとWindowsのMASMは根本的に文法が違う
同じようにはプログラミングできないっての

MASMではMS-DOSの頃から伝統的に
mov ax, hogehoge
これをやるとhogehogeのメモリの内容をaxに読み込む
はじめて読むMASMにもそう書いてあるよw
2018/10/01(月) 07:02:13.01ID:gNvpqBnl
はじめて読むMASM
79ページ目
 データラベルは、マシンご命令のニーモニックのなかで、データを格納す
るメモリを参照するために使用することができます。次の図3−10をみてく
ださい。この図では、違いを対比させるために次節で解説するOFFSET擬似
命令の役割を併せて図解してあります。
 この場合、MESSAGEというデータラベルは01C3Hというアドレスに対応
しています。コードラベルの場合は、ラベル名がアドレスそのものと対応し
ていましたが、データラベルの場合にはちょっと違います。このことは重要
ですからよく覚えておいて下さい。
 たとえば、SYMDEBのようにアドレスを直接数値で指定する場合、そのア
ドレスのメモリの内容を参照するには、
 MOV DX, [01C3H]
のようにアドレスを[]で囲みます。これに対し、アセンブラのソースプロ
グラムでは、
 MOV
2018/10/01(月) 07:04:42.69ID:gNvpqBnl
はじめて読むMASM
79ページ目
 データラベルは、マシンご命令のニーモニックのなかで、データを格納す
るメモリを参照するために使用することができます。次の図3−10をみてく
ださい。この図では、違いを対比させるために次節で解説するOFFSET擬似
命令の役割を併せて図解してあります。
 この場合、MESSAGEというデータラベルは01C3Hというアドレスに対応
しています。コードラベルの場合は、ラベル名がアドレスそのものと対応し
ていましたが、データラベルの場合にはちょっと違います。このことは重要
ですからよく覚えておいて下さい。
 たとえば、SYMDEBのようにアドレスを直接数値で指定する場合、そのア
ドレスのメモリの内容を参照するには、
 MOV DX, [01C3H]
のようにアドレスを[]で囲みます。これに対し、アセンブラのソースプロ
グラムでは、
 MOV DX, MESSAGE
とします。このことからわかるように、データラベルはラベルに対応するア
ドレスそのものではなく、そのアドレスが示すメモリの内容を表します。
つまり、データラベルそのものを指定すると、アドレスの値を転送したり演算
したりする命令ではなくて、メモリに対して転送や演算を行う命令になりま
す。もう1度図3−10を見てじっくり確認してください。

こう書かれてる
346デフォルトの名無しさん
垢版 |
2018/10/01(月) 07:10:06.78ID:gNvpqBnl
82ページ目

3.6
OFFSET演算子とPTR演算子
OFFSET演算子
[書式] OFFSET ラベル名

データラベルをニーモニック中で使用すると、データ部分のアドレスでは
なく、データを格納したメモリの内容を表しますが、そのメモリのアドレス
はどうやって表すのでしょうか。図3−10で図解してあるので解説するまでも
ありませんが、データラベルに対応するアドレスは、次のように表します
 OFFSET データラベル
 OFFSET演算子は、ラベルに対して使用する演算子です。ラベルの前にこ
の演算子を付けると、ラベルに対応するアドレスを表す値となります。
 例題のプログラムでは図3−11の部分で使われています。これは画面に出
力するメッセージが格納されているアドレス値を、データとして定義してい
る例です。



MASMの文法は16bitの頃から一貫してる
みんなはじめて読むMASMからやりなおしだな
2018/10/01(月) 07:41:22.29ID:Z1gvrlLR
>>343
MASMでもmov al,[hogehoge]やlea rax,[hogehoge]が使えて、NASMと「同じ動作」が期待できて、
「根本的に」書き換えなくても疑似命令やマクロとかを書き換えれば移植できるってのがポイントで
NASMはLinux他とWindowsみたいなマルチプラットフォームのプロジェクトでよく使われてるから
あんたみたいなmov al,hogehogeやり方でNASMに移行すると変なバグに悩まされる可能性があんだよ
特にmov al,hogehogeがイミディエイトでアドレスの一部がコードされるのが酷い

SYMDEBで括弧で括るってのはイミディエイトと区別付かないからそうなってるんだろ
これはNASMで括弧で括るのと同じこと
時代遅れになった本の内容なんてどうでもいい
括弧で括らない表記は、8080時代を踏襲してるのか、インラインアセンブラでのCの変数参照と統一感があるってところだろう
これならNASMで異なる動作にならない方が無難

こっちが言いたいのは、初心者に有用なことが書けないなら「出てくんな」ってことだけ
2018/10/01(月) 07:55:48.93ID:gNvpqBnl
>>347
それは自分だけで書いたコードを読むだけならいいが
他人が書いたコードやコンパイラが吐き出したコードを読むのにはそれは通用しない
2018/10/01(月) 07:57:49.96ID:gNvpqBnl
それにNASMで慣れるとgccでインラインアセンブラを使うときに困る
gccはx86_64でもインラインアセンブラを扱えるのに
NASMの文法はgccのインラインアセンブラでは通用しないぞ
2018/10/01(月) 08:10:48.59ID:gNvpqBnl
多くの人がOFFSET演算子に対する理解がないようだから書いただけなのに
猛烈に反発してくる変な人がいるだけ

gccでは-mcmodel=largeのオプションを付けてコンパイルすると
movabs rax, offset flat: hogehoge
のような表現がよく出てくる
64bit絶対アドレスを扱うには必ず必要になってくる
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況