アセンブラ初心者スレッド 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/08/24(金) 07:53:32.13ID:CXKCSzYg
>>191
25個並べることにしてループ回数を一桁増やしたが早くならないぞ
そういうのを机上の空論というんだ
2018/08/24(金) 07:59:52.52ID:568m+iHd
なんか初心者スレの趣旨とずれまくりなんだけど。
コンパイラのABIが「変わった」のなら、それに合わせたのを紹介しないと。

Visual Cは64bitではインラインアセンブラも使えなくなったし、AVXやSSEは組み込み関数で大概は満足できるはずって判断されたのだろう。
今のご時世わざわざアセンブリ言語でプログラミングしたいって用途は動画のコーデックやフィルタプラグインDLL、将棋とかの思考ルーチンとかでしょ。
こういうのは2GB制限下でしか使えないコードでは困るはず。
2018/08/24(金) 08:09:12.98ID:568m+iHd
>>189
静的配列だとサイズが決まってるから、恐らく最適化されてポインタとオフセット(ディスプレースメント)に変換されるよね。
>実質差が無いメリットの為に絶対アドレスに依存したコードにする
>時代に逆行だ
これに同意。
2018/08/24(金) 12:53:22.92ID:7MrYBE0R
>>192
ヒント HTT
2018/08/24(金) 14:52:13.41ID:PMMpdZPT
>>185
自分は 64BIT 用C/C++コンパイラをインストールして無いので、試せません。

link.exe に、 /largeaddressaware:no を渡した場合にのみ、
GlobalAlloc() が失敗する理由は何ですか?

ポインタが32BITになる? それとも、GlobalAlloc の関数が別のものに
入れ替わってしまう?

そのどちらでもないとしたら何が原因ですか?
197デフォルトの名無しさん
垢版 |
2018/08/24(金) 14:54:32.88ID:PMMpdZPT
>>187
>/largeaddressaware:noを付けると64bitアプリでも動的メモリも含めてすべてのメモリで2GB以下までしか使えなくなる
>PGIのコンパイラのページでわかりやすく解説してあるよ
>https://www.softek.co.jp/SPG/Pgi/TIPS/opt_64.html

リンク先のページを見たのですが、自分には、
 「動的メモリの場合にも2GB以下しか使えなくなる」
という文書が見つかりませんでした。

どこに書かれているか、ご指摘いただければ幸いです。
2018/08/24(金) 16:51:48.72ID:VlbdtNmU
実験したけど2GBまでだったよ
malloc

アドレスは32bitで保持出来る
32bitアプリからの移植用だろうね
2018/08/24(金) 16:55:58.09ID:VlbdtNmU
>>196
メモリはOS側の管理でしょ?
OSがアプリ種別を判別してアドレスを割り当てる

31bit
32bit
64bit

の3種類かな?
2018/08/24(金) 17:07:40.76ID:PMMpdZPT
>>199
リンカオプションによって、API の挙動まで変わってしまうんでしょうか。

そして、Win64 API の GlobalAlloc() などが返す値が 31 BIT までに
なるので、malloc() もそれにつられて、勝手に 31BIT までになると?

64BIT COFF だと、COFF Image に、/largeaddressaware:no かどうか
を示す BIT か何かが追加された???
2018/08/24(金) 19:11:45.47ID:5OB8VNk6
>>196
無料のVisual Studio Expressでも2013以降は64bitのビルドにも対応してるよ
64bitのWindowsプログラミングに興味があるなら入れてみれば?

プログラムのコードを見ればわかるように
10MBずつメモリを確保していき
メモリが確保できなくてGlobalAllocの戻り値にNULLが返るか
確保したメモリが4500MBを越えたらbreakでループを抜けて
確保したメモリ容量を表示して終了するようになってる

で、/largeaddressaware:noを指定すると
俺の環境では1970MB確保したところでループを抜けて終了してる
つまり、1970MB確保したところで、
次にGlobalAllocを実行するとメモリが確保できなくてNULLが返る
これは、動的メモリも2GB以下しか確保できないということを示してる

/largeaddressaware:noを指定せずにコンパイルすると
4510MBまで確保して終了する
2018/08/24(金) 19:16:32.91ID:5OB8VNk6
>>200
Visual Studioに入ってるdumpbin.exeでコマンドプロンプトで
dumpbin /headers hogehoge.exe
とやると/largeaddressawareを指定した状態(/largeaddressaware:noを指定しない状態)だと
FILE HEADER VALUESの項目とのところに

Application can handle large (>2GB) addresses

これが表示される
なので詳しくは知らないが実行ファイルの中に/lageaddressawareの指定をする部分があるはず


これまたVisual Studioに入ってるeditbin.exeを使うと
実行ファイルそのものに/largeaddressawareや/lageaddressaware:noの指定ができる

LAAを有効にするには
editbin /lageaddressaware hogehoge.exe

LAAを無効にするには
editbin /lageaddressaware:no hogehoge.exe
2018/08/24(金) 19:47:12.65ID:568m+iHd
VCで64bitの静的配列にアクセスするコードを調べてみた。
#include <math.h>

volatile char str[1024];
volatile char c;

main(int argc, char *argv[])
{
int idx;

idx = (int)(rand() * 1024);
c = str[idx];
}

これの配列アクセス部分が
; 11 : c = str[idx];

0001c 48 63 44 24 20 movsxd rax, DWORD PTR idx$[rsp]
00021 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:str
00028 0f b6 04 01 movzx eax, BYTE PTR [rcx+rax]
0002c 88 05 00 00 00
00 mov BYTE PTR c, al

00028は[rcx+rax]で配列アクセスしてる
そして、00021と0002cはrip相対アドレッシングだよね?(エンコードは自信ないので)
2018/08/24(金) 19:58:50.48ID:568m+iHd
>>198
時々ポインタをDWORDに変換して構造体に突っ込んでたりすることがあるからね。
argeaddressawareは、こういうコードが含まれたアプリをどうしても64bitで動かさなきゃいけなくなった時とかに仕方なく使うオプションでしょう。
でないと、GlobalAlloc()が大きなアドレス返したら動かなくなるし。
2018/08/24(金) 20:08:42.11ID:568m+iHd
>>200
プロセスを起動する時にexeのLAAフラグを見てメモリとかハンドルを返すAPIが32bitに収まる値を返すように設定されるんだと思う。
こういうのはプロセスごとに32bitとかにも切り替えられる(この場合はシステムDLLは64bitとは別だけど)ので、
互換性を確保する仕組みが裏で動いてるはずだよ。
2018/08/24(金) 20:18:03.36ID:568m+iHd
>>203のコードバイトの折り返し部分のタブが詰められて見にくいので

0001c 48 63 44 24 20 movsxd rax, DWORD PTR idx$[rsp]
00021 48 8d 0d 00 00 00 00 lea rcx, OFFSET FLAT:str
00028 0f b6 04 01 movzx eax, BYTE PTR [rcx+rax]
0002c 88 05 00 00 00 00 mov BYTE PTR c, al
2018/08/24(金) 21:46:35.00ID:5OB8VNk6
>>203
VC++だと/FAオプションを指定するとアセンブラ出力もされるよ
ただ、64bitのVC++コンパイラが吐き出すアセンブラコードは
そのままではml64.exeでアセンブルできないけど
ml64.exeでアセンブルできるように修正できたらml64.exeでアセンブルする時に
/Flオプションを指定するとリスティングファイルを出力してくれる
2018/08/24(金) 22:08:39.28ID:568m+iHd
>>207
>>203は/FAscで出力された.codから抜粋したもので、リンク前だから変数のアドレスが変な値になってる。
最適化オプションつけ忘れてるのでimul使ってるけど、/O2でも配列へのアクセスはインデックスレジスタ付きなのは変わらなかった。

このサンプルでは配列の添え字がコンパイル時に推定できないようにしたのでインデックスレジスタ付きになってるけど、
普通のループでは、この部分は最適化されてポインタに変更されて、レジスタ間接とポインタ操作するコードになるはず。
2018/08/25(土) 04:35:15.70ID:gxBSyOuw
プロセスのアドレス空間が、4GB までだから

その内、Linux では1GB、Windows では2GB を、カーネル空間に割り当てているから、
残りのユーザー空間は、3GB, 2GB になる

カーネル空間は、全プロセス共通の空間だから、各プロセスで使えないアドレス
2018/08/25(土) 05:52:55.11ID:5KTEEpUR
64bit Windowsでの2GB制限ってのは、単にメモリ確保時のアドレスの割り当て方やハンドルの値が変わるだけで、
アクセスできない場所では普通に例外が発生するだけのこと。
/largeaddressaware:yesの状態では、32bitの範囲のアドレスがが割り当てられてないから
rip相対を使って静的変数のあるアドレスを取得するってことね。
2018/08/25(土) 05:57:44.86ID:5KTEEpUR
割り当てられてないってのは変だったね。
アクセス権限が与えられてないからってこと。
2018/08/25(土) 11:07:20.24ID:auNeFg4G
偉そうなもんだな。
もうちょっと、言い方ってもんを学んだ方がいい。
人間性に問題あるかも。
2018/09/03(月) 04:21:34.86ID:A+X9ST7o
アセンブラの命令を覚えたいのと
デバッガーを使いこなしたいんですが
何かお勧めの勉強方法はありますか?
C入門程度だけの知識だけでアセンブラは全く知りません

よろしくお願い致します
214デフォルトの名無しさん
垢版 |
2018/09/03(月) 11:24:23.57ID:dhYkuZhG
CPUは何?
2018/09/03(月) 12:38:16.62ID:f+M/nyW5
書いてないってことは決まって無いんだろう

Visual Studio Community 2017
x86 64bit
ml64.exe

が環境としては一番簡単かな
何もしない関数をアセンブラで作って
Cからその関数を呼ぶところから始めよう
2018/09/03(月) 20:27:11.25ID:A+X9ST7o
os10 64bitです
C++でアセンブラ使えるんですね
知りませんでした。そこら辺も調べてみます
デバッガーでコードを読んで書き換えられるようになりたいです
2018/09/03(月) 20:36:15.47ID:i7qE7EE1
マカーか
2018/09/04(火) 16:50:20.52ID:ErgP6cOz
横からだけど、
それに必要なのはバイナリからアセンブラコードを出力する逆アセンブラじゃないの?

それとも基礎知識として習得したいってことなのか
2018/09/04(火) 17:01:04.80ID:hMkkrsf+
チートしたい!
2018/09/04(火) 22:32:50.81ID:snmgssEj
>>218
これから勉強するって段階で逆アセはまだ早い。まずCで簡単なコード書いてアセンブラソース出力
それを見て少しずつ変更して動作を勉強。どきどき暴走させて遊ぶのがいい。
Cやアセンブラのソースがないバイナリを逆アセしても、逆アセはコードとデータの区別なしにコード化するから混乱する。
2018/09/04(火) 22:50:42.54ID:bj+tb6HS
回答ありがとうございます;
アセンブラの実行環境整える(実機だのエミュだの)用意するのが物凄い敷居高そうに感じるので
チートエンジンやollydbg?ってやつでオフライン用のゲームでも解析しながら
アセンブラ命令群を覚えようと思ってます。
アセンブラの命令を覚えるのだけなら後者でも力つきますかね?目標はウイルスのデバッグとか出来るようになりたいです
2018/09/05(水) 01:22:32.69ID:vQx16S6k
>>221
>目標はウイルスのデバッグとか出来るようになりたいです
どうしてそう反社会的な方ばっかり目がいくんだい。

これだから、ハッカー=クラッカー、悪者、のイメージが付く。
昔は、アセンブラといえば、速さのために学んだものなのに。

君みたいなのにはプログラムになんか興味を持たないで欲しい。
2018/09/05(水) 02:37:54.86ID:wyXCwUhn
>>どうしてそう反社会的な方ばっかり目がいくんだい。

そう…ではなくてですね
将来ウイルスとかランサムウェアの対策ツールとか作ってみたいから
デバッグスキル付けたいと思って、覚えたいと思いました。
http://www5c.biglobe.ne.jp/~ecb/assembler/assembler00.html 見て実行環境頑張って作って覚えようと思ったんですけど
とっつきづらすぎると思って;
てかVisualStudioって自分のコードアセンブラで出力したり出来るんですね
全然知りませんでした。ありがとうございます
2018/09/05(水) 03:52:48.57ID:EatH13os
ウィルスってね、勉強のつもりで作っても、いざ出来上がると使ってみたくなるもんなんだよね。
そういう誘惑に勝てるかどうか
2018/09/05(水) 06:27:13.70ID:wyXCwUhn
>>224
そういう方もいらっしゃるんですね。
プログラミング歴はもといパソコンも初心者レベルにしかない自分には縁のない響きですね・・

ところでC++のコードをvisualstudioでアセンブラ出力とはどうやるんでしょうか?
気になって調べてみたんですが デバック(D)→ウィンドウ→アセンブラ っと進むと出てくると書いてあるんですが
そんな項目ありません;
226デフォルトの名無しさん
垢版 |
2018/09/05(水) 11:13:33.31ID:/V9AsOwQ
debug.exe
debug64.exe
2018/09/05(水) 11:34:16.13ID:TWmx8fnR
OllyDbg とか、

うさぴょんの「うさみみハリケーン・スペシャルねこまんま」とか、
将棋AI「やねうら王」の作者、やねうらおの本「解析魔法少女 美咲ちゃん」とか

デバッガによるx86プログラム解析入門 【x64対応版】、うさぴょん、2014
2018/09/05(水) 11:55:15.09ID:gDSR0MtA
>>225
ソリューションエクスプローラーでソリューションの下にあるプロジェクトを選択してプロパティ
構成プロパティ→C/C++→出力ファイル→アセンブリの出力
2018/09/05(水) 20:44:59.69ID:wyXCwUhn
>>227-228
ありがとうございます
ソリューション周辺探しましたが https://gyazo.com/b58d77fd28f08e941c91b337938d1f6c
無かったです……
VSインストールする時2つくらいしか選択しなかったんですがそれがまずかったんでしょうか
ollydbgというのも調べてみます
2018/09/06(木) 01:20:57.16ID:UZSBUUik
VSでC/C++のデバッギングに入ってステップインしてたらアセンブラのコードが出てこないか?
2018/09/06(木) 01:24:39.50ID:uY3Jh6lT
>>229
C/C++の所のツリー開け
232デフォルトの名無しさん
垢版 |
2018/09/06(木) 05:22:06.40ID:psScFFtw
Cならインラインアセンブラ使えば良いんでない?
2018/09/06(木) 14:49:24.96ID:jOmc1UUP
いや、普通にターゲットCPUのニーモニック表を探して来て見ろよ
234デフォルトの名無しさん
垢版 |
2018/09/24(月) 01:13:48.37ID:rSek34EX
取り敢えずアセンブラ上の数字2進数(或いは16進数)を桁ごとに分けて十進数にして、+30して(文字コードに変換)する事には成功した。

何進数か関係無く、10の位なら10ずつ、100の位なら100ずつ引いて実現。

筆算のアルゴリズムだともっと速いらしいので、時間があれば挑戦したい。
時間があれば。。。
235デフォルトの名無しさん
垢版 |
2018/09/24(月) 01:17:43.11ID:rSek34EX
x 何進数か関係無く、10の位なら10ずつ、100の位なら100ずつ引いて

o 何進数か関係無く、(何進数の10でも10進数の10だと言うことは変わらないので)10の位なら10(16進数だとA)ずつ、100の位なら100ずつ引いて
2018/09/25(火) 01:58:20.74ID:4rHiZGxF
8bitISAの経験はあるんだがIA32やAMD64のプログラミングマニュアルを見ると命令の多さにめまいがする
しかもググってみるとメモリアドレッシングもなにやら作法があるようでよくわからん・・・
な状態なのだがIA32/AMD64のアセンブラを勉強するのにおすすめの資料とかあるかな
今のところ自力で書いたことのあるISAは78K0S、8051、AVR。基本的な概念はわかっているつもり
リンカ周りは不安あり。プラットフォームはWindowsかLinuxかFreeBSDを検討中
2018/09/25(火) 08:56:01.40ID:oRUMH9qn
>>236
ISAって何のこと?
2018/09/25(火) 09:25:52.53ID:oRUMH9qn
ISA=instruction set architecture=命令セットアーキテクチャ
や、
ISA=PC/ATの拡張スロットのバス仕様

??
2018/09/25(火) 18:37:53.38ID:oPuX37oa
このスレでISAをIndustry Standard Architectureと解釈する必要ってあるのか?
2018/09/26(水) 04:10:17.53ID:GMLyVXjl
誤解を生まないよう書き込む際は気を付けた方がいいね
2018/09/26(水) 10:35:31.91ID:s/2dxbJy
>>236
VCのx64はインラインアセンブラも使えなくなってるんだから、特殊なビット操作やりたいのでなければ
組み込み関数覚えてからの方が楽なんじゃないの
https://software.intel.com/sites/landingpage/IntrinsicsGuide/
右端に対応するニーモニックが書いてある
242デフォルトの名無しさん
垢版 |
2018/09/27(木) 10:28:07.85ID:+X2PETpr
>>240
アスペじゃなければこの文脈でそれはない
2018/09/27(木) 10:47:26.07ID:JRG0evD8
そもそも8bitISAなんて言い方は一般的ではないもん。
2018/09/27(木) 10:58:42.91ID:JRG0evD8
かなりアセンブラ経験あるけど、8bit ISAと聞いても意味が分からなかった。
多分、8bit CPUとか、8bit マイコンのことが言いたかったのではないかとは
思ったけど、意味がはっきりしなかったので念のため聞いてみた。

個人的には、Instrucstion Set Architectureの意味での「ISA」という
言い方は、Intelのマニュアルなどで最近目にするようになった印象が
ある言い方。

修正に告ぐ修正を重ねてが複雑化したx86系CPUのあの複雑さのニュアンス
を出すためにIntelが使い始めた言葉かもしれない。

昔、Z80が流行っていたころは、日本の雑誌などでは、8bit CPUと言われて
いたし、炊飯器や冷蔵庫では、今でもCPUよりもどちらかというと
I/OポートやA/Dコンバーターを内蔵しているみたいななニュアンスを
含めて「マイコン」と言われていると思う。

ISAという言葉は、Intelマニュアル以外ではあまり見たことない。
2018/09/27(木) 11:23:55.29ID:tmnyfQyv
ARM でも MIPS でも普通に ISA 使うけど。
8bit の頃は、セカンドソースはあっても、ISA レベルでのライセンシングが無いか稀だったんじゃないかなあ。

どっちにしろ、16bit バスの ISA を思いつくのはちょっと理解できない。
2018/09/27(木) 11:29:57.13ID:JRG0evD8
>>245
文化が違うと用語も違う。Z80 ISAなんて言葉は一度も聞いたことがない。
8BIT ISAも初耳だった。

8BIT時代、ARMやMIPSも日本では聞かなかったし。
2018/09/27(木) 11:40:30.81ID:JRG0evD8
>>245
「8-bit ISA card」
で検索すると、色々出てくる。

当時、愛器はNEC製だったのでPC/ATのバス規格であったところのISA
については知らなかったけど。

コンピュータは用語が多様なので、省略形は注意が必要だと思う。
ガングロ女子高生が省略後で通じ合えるのは、多分、興味の対象が
狭いか、語彙が少ないからこそかもしれないと思ってる。
語彙が豊富な人ほど、略さずそのまま言う傾向があると思うし。
2018/09/27(木) 11:40:33.72ID:tmnyfQyv
>>246
うん、だから ISA レベルでのビジネスがない頃はそこにタームが存在してなかっただけで、今の時代であれば、8bitISA と言われれば、いろんな8bitマイコンの事だと判るでしょ。
おまけに、その下に
自力で書いたことのあるISAは78K0S、8051、AVR
って書いてあるんだから。

>>236
FreeBSDかNetBSDの mm とか syscall とか libc 周り読むのがいいと思う。
本なら、はじめて読む486 は良かった記憶があるけど相当昔の話だし x64 はないからおすすめ度は低い。
Kindle あるみたいだから、気が向いたらレベルでおすすめ。
2018/09/27(木) 11:49:44.12ID:JRG0evD8
>>248
あまりなじみの無いCPU名が列挙されていたので、8bit ISA BUSで、組み込み系
をやっていた人かと思ったんだよ。

ネットでは、質問者の年齢も分からないし、何にも推測できないから。
2018/09/27(木) 11:55:04.47ID:JRG0evD8
アセンブラの基礎が分かっている人なら、Intelの3 Volumeがセットになった
英文マニュアルがお勧め(なお、英語が分かる人は、日本語版は読まない
方がいいと思う。混乱の元になるから。英語が分からない人は、多分、
混乱しながら時間をかけて前後関係から推定して理解することになる。)

ModRMについても書いてある。ただし、32BITのものが詳しく書かれていて、
64BITのものについては、補足のように後から書かれている。
REX prefixとかと関連して。

非常に壮大なマニュアルで、忘れたけど、総ページ数は5,000ページくらい
あったかもしれないけど、必要なところをかいつまんで読めばいい。

アセンブラ経験がある人なら読めるはず。
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言語との対応関係も知らずにアセンブラ語ってたとは驚き
で、また火病って連投してるね
■ このスレッドは過去ログ倉庫に格納されています