質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

アーキテクチャ

アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

Q&A

解決済

3回答

2542閲覧

ハンドアセンブラ

strike1217

総合スコア651

アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

アーキテクチャ

アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

0グッド

0クリップ

投稿2017/05/08 15:14

編集2017/05/08 15:55

objdump -d a.out の <main>セクションの一番最初は、
push %rbp → 0x55 となっていました。

binutilsのopcodesの中に、ニーモニックとレジストリの値の一覧を探しました。

// ニーモニック { "push", 1, 0x50, None, 1, { "push", 1, 0xff, 0x6, 1, { "push", 1, 0x6a, None, 1, { "push", 1, 0x68, None, 1, { "push", 1, 0x6, None, 1, { "push", 1, 0xfa0, None, 2, { "push", 1, 0x50, None, 1, { "push", 1, 0xff, 0x6, 1, { "push", 1, 0x6a, None, 1, { "push", 1, 0x68, None, 1, { "push", 1, 0xfa0, None, 2, { "pusha", 0, 0x60, None, 1, { "pushf", 0, 0x9c, None, 1, { "pushf", 0, 0x9c, None, 1,

レジストリに関して、、、

static const char *intel_names64[] = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" };
rbx, Reg64|BaseIndex, 0, 3, Dw2Inval, 3 rsp, Reg64, 0, 4, Dw2Inval, 7 rbp, Reg64|BaseIndex, 0, 5, Dw2Inval, 6 rsi, Reg64|BaseIndex, 0, 6, Dw2Inval, 4 rdi, Reg64|BaseIndex, 0, 7, Dw2Inval, 5
{ "rbp", { { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, 0, 5, { Dw2Inval, 6 } },

push命令だけではなく、オペランドをくっつけたときにバイナリコードになりますが・・・
#どのような手順で計算すれば、push + %rbp が, 16進数で0x55となるのでしょうか?

やり方を知っている方はぜひ教えてください。

Linux 64bit です。

[追記]

printf("you will make me happy!!\n");

をアセンブルすると、 mov $0x4005a4,%edi
you will make me happy!! という文字列が逆順に入っているのは、「リトルエンディアンだから」という理由でしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

どのような手順で計算すれば、push + %rbp が, 16進数で0x55となるのでしょうか?

可能な限り、一次情報源をあたってください。Intel社より "Intel® 64 and IA-32 Architectures Software Developer Manuals" が公開されています。"Intel® 64 and IA-32 architectures software developer’s manual combined volumes: 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4" が全部入りドキュメントです。

"Volume 2: Instruction Set Reference, A-Z" の PUSH—Push Word, Doubleword or Quadword Onto the Stack より:

OpcodeInstruction
50+rdPUSH r64

表中 "+rd" は 3.1.1.1 Opcode Column in the Instruction Summary Table (Instructions without VEX Prefix), Table 3-1. Register Codes Associated With +rb, +rw, +rd, +ro より RBP == 5 と定義されています。

以上より、PUSH RBP のオペコード(16進数)は 50+5 つまり 55 となります。

補足:Intel社マニュアルは「Intel記法」で記載されていますが、GNU系ツールでは「AT&T記法」とよばれる表現方法を採用します。この回答の範囲では、レジスタ名称RBP(Intel記法)/%rbp(AT&T記法)の読み替えが必要です。

投稿2017/05/09 00:56

編集2017/05/09 02:08
yohhoy

総合スコア6189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2017/05/09 01:29 編集

一番最後typoです;) > $rbp
strike1217

2017/05/09 03:28

50+5 ですね! rbpレジスタが 0x5 であることを見つければ、よろしいのですね!
strike1217

2017/05/09 03:54

単純に論理和にならない場合もあるんですか?
yohhoy

2017/05/09 04:26 編集

どこから論理和がでてきたのでしょうか?? 意図不明ですが、一般に機械語命令はハードウェア回路で処理されることを考えると、オペコードからのビット抽出で済むように設計されるのが自然かと思います。
strike1217

2017/05/09 04:26

あ、ビットごとではありませんね・・・ 算術加算ですね! 全ての「ニーモニック+オペランド」は算術加算によって機械語に変換できるんでしょうか?
strike1217

2017/05/09 04:35

オペコードからのビット抽出・・・ 連続的に2進数のビットが抽出されているということでしょうか? ニーモニックとオペランドのビットを連続的に並べていけば、機械語になるということですよね?
fuzzball

2017/05/09 04:47

算術加算でもありません。論理演算の和(OR)です。
strike1217

2017/05/09 04:52

論理演算の和 = 論理和 とは違うんですか?
yohhoy

2017/05/09 04:56

> 全ての「ニーモニック+オペランド」は算術加算によって機械語に変換できるんでしょうか? > ニーモニックとオペランドのビットを連続的に並べていけば、機械語になるということですよね? "いいえ"という答えの方が適切かと思います。正確に答えるなら、いずれも「プロセッサと命令セットアーキテクチャ(ISA)の設計次第」です。おっしゃるようなルールが適用される場合もあるでしょうし、そうでない場合もあるでしょう、としか言えません。 > 連続的に2進数のビットが抽出されているということでしょうか? 強いて言えば、"はい"という回答の方が適切かなという程度… ハードウェア回路的にはビットを抽出する=信号線を選ぶだけ という操作が最も簡単ですから、そのメリットを生かせるよう機械語命令体系を整備するのが自然です。
strike1217

2017/05/09 05:00

アーキテクチャのよって異なるのですね! ニーモニックとオペランドの情報から機械語を算出するには、CPUによりけりということですね・・・
yohhoy

2017/05/09 05:14 編集

Intelプロセッサは下方互換性を最重要視しているため、複雑怪奇な機械語命令体系になっています。おかげでマーケット的には成功していますが、学習(?)向けにはもっとシンプルな命令体系のプロセッサの方が良いかもしれません... またアセンブラを学ぶという話と、機械語命令について学ぶ話はレイヤが異なると思います。後者に興味があるならば書籍「コンピュータの構成と設計」シリーズをお勧めしておきます。著者名から"パタヘネ本"と呼ばれたりします。
strike1217

2017/05/09 05:14

複雑怪奇な機械語命令体系 そ、そうなんですか! Intel CPU であれば、互換性を保つために、機械語の算出は1通りのやり方で行える可能性もあるんですかね・・・
guest

0

ベストアンサー

Linux 64bit です。

OSは関係ないです。プロセッサの種類が問題になるので、例えば「AMD64プロセッサ」などというべきでしょう。

どのような手順で計算すれば

こうした疑問を解決するにはプロセッサのデータシートを参照すればよいと思います。言語プロセッサーを書いた人たちはこうしたデータシートを参照してコンパイラー、アセンブラー、逆アセンブラーなどのユーティリティーを書いたはずです。

インターネット上でAMD64プロセッサ(IA32の互換プロセッサ)での命令一覧を探してみると、PUSH reg(汎用レジスタ)はレジスターの種類に応じて0x50~0x57になり、汎用レジスターは%eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %espの8個なんてことが書いてあるので、オペコードのビット列は0101 0rrrであり、rrrは%eax=0,%ebx=1,...となっているであろうことが想像できます。

訂正:上記のレジスターの名前は自分がみたページからコピペしましたが順番がおかしいのと記法が違いますね・・・yohhoyさんがおっしゃるように一次情報を参照すること、記法の違いなどに注意しないといけませんね。失礼しました。

ちなみにAMD64プロセッサのアセンブリー命令の全てを把握するには自然プロセッサの仕様を把握することが必要で、そのためにはプロセッサのハードウェアとしての背景知識が必要になってくるので個人で学ぼうとするのはなかなかに敷居が高いように思えました。そうではなく基本的なデータ転送命令や演算命令、分岐命令程度と汎用レジスターの一覧の程度を把握するだけならそれほど難しくはないです。またそれだけでもそこそこの役には立つとは思います。

you will make me happy!! という文字列が逆順に入っている

メモリー上には別に逆順に入ってません。C言語の素直な実装では'y','o','u',...の順番にメモリー上に配置されますが、単にそれを4バイトずつダンプしたような表現をみたとき逆順になっているかのように見えただけだと思います。

投稿2017/05/08 20:01

編集2017/05/09 05:33
KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/05/09 03:16

確かに、OSは関係ありませんね。すいません。 データシートを参照するんですね! binutils内にあるか探してみます。
KSwordOfHaste

2017/05/09 03:21 編集

データシートって・・・他の方がコメントされているように「プロセッサの仕様書」ですのでbinutils内には存在しません。
strike1217

2017/05/09 03:24

あ、そうなんですか!
strike1217

2017/05/09 03:25

では、gasなどのアセンブラはどのようにして、アセンブリ言語を機械語に変換しているんですか?
KSwordOfHaste

2017/05/09 03:31

むむむ?機械語をどうやってハンドアセンブルするかの話とgasがどうやってそれをプログラミングしているかは別の話題と思いますよ?ちなみに自分ならpushという命令とオペランドの解析結果が汎用レジスターであることの両方が確認できたらオペコードが0x50で汎用レジスター%rbpが5という情報から論理和を取って0x55を生成します。
strike1217

2017/05/09 03:35

ああ~~ 単純に論理和なのですね! 全ての「ニーモニック+オペランド」は、論理和を取れば機械語になる!ということで良いのでしょうか?
KSwordOfHaste

2017/05/09 03:42

それはデータシートに書かれたオペコードの仕様をきちんとみて判断してください。必ずしもそうならない場合もあるかも知れませんし。同じpushでも0x50-0x57でないものもありますよ? 一般的にはプロセッサの設計者が機械語をどのように設計するかに依存して様々に変わります。それはプロセッサの設計に深くかかわってます。汎用レジスターはプロセッサの中では番号によって識別する設計が一般的でしょうからレジスター番号を基本のオペコードの特定のビット位置に置くという設計はよくあるとは思います。
strike1217

2017/05/09 03:46

わかりました。 結構面倒なのですね!
guest

0

KSwordOfHasteさんの補足のようになりますが、

まずは386DXのデータシート。
http://pdf.datasheetcatalog.com/datasheet/Intel/mXtuvqv.pdf

p.96より、

PUSH Register (short form) 0 1 0 1 0 reg

レジスタに関してはp.112より、

000 EAX 001 ECX 010 EDX 011 EBX 100 ESP 101 EBP 110 ESI 111 EDI

よって、push ebpは、

0 1 0 1 0 1 0 1 = $55

投稿2017/05/09 00:14

fuzzball

総合スコア16731

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/05/09 03:58

0 1 0 1 0 1 0 1 = $55 これ単純に論理和ですね! 論理和にならない場合もあるんですか?
fuzzball

2017/05/09 04:14

インストラクションセットを見た上で質問しているのでしょうか? 質問の意図も不明です。
strike1217

2017/05/09 04:31

すいません。論理和ではありません。 0 1 0 1 0 + 101 → 01010101 ニーモニックとオペランドから機械語を作り出す時は、全て、この方法でできるんですか?
fuzzball

2017/05/09 04:48

出来たらどうで、出来なかったらどうなんでしょうか? 何のために質問しているのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問