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

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

ただいまの
回答率

90.61%

  • C

    3563questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

nasm 擬似命令 orgについて

解決済

回答 5

投稿

  • 評価
  • クリップ 1
  • VIEW 330

binary

score 14

nasmでは擬似命令orgによってプログラムを格納するメモリーアドレスを指定できますよね?
GAS(gcc )にはnasmのorgのようなプログラムを格納するアドレスを指定するような擬似命令はあるんですか?
ない場合はどのように格納する場所を指定すれば良いのでしょうか?

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+1

 ※他の回答者さんらから既に回答ありましたので、補足の情報としてとらえてください。

 1. gas (GNU assembler)の.org擬似命令について

先の回答者さんらの回答に既に提示されたように、gasにも .org擬似命令があります。ですがその効果はnasmや、masm(Microsoft Macro Assembler)のものとは異なります。

まず前提として .org擬似命令はプログラムをどのアドレスへロードするかを指定するものではありません。どのアドレスへロードするかを実際に決定するのは、リンカーとOSの仕事です。

では.org擬似命令で何ができるかと言うと、ソースコードをアセンブルしてマシン語にする過程において、.org で指定した位置を始点としてアドレスの計算を始める、と言うようなことになります。

gingertailさんが提示されたリンク7.64 .org new-lc , fill の説明の冒頭に以下の記述があります。

Advance the location counter of the current section to new-lc.

「現在のセクションのロケーションカウンターをnew-lcへ進める」です。これはどういうことかと言うと、アセンブルの過程で、まず、仮のアドレスを決めます。(「ロケーションカウンター」と言います) そして、.org命令でnew-lcを指定するとその位置まで仮のアドレス(ロケーションカウンター)を進めると言うものです。分かりづらいので、ちょっと実験してみます。

以下は、"Hi! This is as01!!" とだけコンソール出力するgasのプログラムです。(Ubuntu 17.04 x86)

.global main

main:
    movl $4, %eax
    movl $1, %ebx
    movl $message, %ecx
    movl $21, %edx
    int  $0x80

    movl $1, %eax
    movl $0, %ebx
    int  $0x80

.data
message: .asciz "Hi! This is as01!1\n"

# gcc -Wl,Map=as01.map -o as01.exe as01.s
#
# $ ./as01.exe
# Hi! This is as01!!
# $

これをmapファイル出力付きでアセンブル~リンクして、mapファイルを確認してみます。(grepコマンドでmainを抽出)

ubuntu$ gcc -Wl,-Map=as01.map -o as01.exe as01.s
ubuntu$ ./as01.exe
Hi! This is as01!1

ubuntu$ grep "main" as01.map
                0x00000000080482c0                __libc_start_main@@GLIBC_2.0
                0x00000000080483db                main
ubuntu$ 


mainのアドレスが0x00000000080483dbになっていることが分かります。
__libc_start_main@@GLIBC_2.0は無視していいです。

次に、.org 0x100 を追加してみます。

.global main
.org 0x100

main:
    movl $4, %eax

...以下略

すると、mainのアドレスは以下のようになり、0x100 増えているのがわかります。0x100番地と言うわけではありません。相対的に0x100増えているだけです。つまり、mainをアセンブルするときに、元の始点から0x100番地進める(advance)ということになります。

ubuntu$ grep "main" as01.map
                0x00000000080482c0                __libc_start_main@@GLIBC_2.0
                0x00000000080484db                main


gdb でロードして、確認してみます。

ubuntu$ gdb -q as01.exe
Reading symbols from as01.exe...(no debugging symbols found)...done.
(gdb) b main
Breakpoint 1 at 0x80484db
(gdb) run
Starting program: /home/user01/dev_share/as01.exe 
d
Breakpoint 1, 0x080484db in main ()
(gdb) disassemble
Dump of assembler code for function main:
=> 0x080484db <+0>:    mov    $0x4,%eax
   0x080484e0 <+5>:    mov    $0x1,%ebx
   0x080484e5 <+10>:    mov    $0x804a018,%ecx
   0x080484ea <+15>:    mov    $0x15,%edx
   0x080484ef <+20>:    int    $0x80
   0x080484f1 <+22>:    mov    $0x1,%eax
   0x080484f6 <+27>:    mov    $0x0,%ebx
   0x080484fb <+32>:    int    $0x80
   0x080484fd <+34>:    xchg   %ax,%ax
   0x080484ff <+36>:    nop
End of assembler dump.
(gdb) 


mainが0x80484db から始まっていることが分かります。

ちなみに.org new-lc , fillfillとは、new-lcまでに埋める値を指定するものです。(デフォルトは0x00)
実験として、0xcc を指定し、mainから前の0x100バイト分の領域を0xccで埋めてみます。

.global main
.org 0x100, 0xcc

main:
    movl $4, %eax

...以下略


gdbでmain まで実行して、mainの前後32バイトをダンプしてみます。以下のように、mainの前は0xccで埋められ、main以降はマシン語になっているのが分かります。

(gdb) x/32bx main-16
0x80484cb <frame_dummy+283>:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0x80484d3 <frame_dummy+291>:    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc    0xcc
0x80484db <main>:    0xb8    0x04    0x00    0x00    0x00    0xbb    0x01    0x00
0x80484e3 <main+8>:    0x00    0x00    0xb9    0x18    0xa0    0x04    0x08    0xba
(gdb) 

 2. リンカーで配置アドレスを指定

回答がありましたが、リンカーで配置アドレスを指定する方法です。

リンカーldで実行プログラムの配置アドレスを指定することができます。と言ってもオプションは多いので一例にとどめます。実行プログラムは textセグメントに配置されるので、-Tオプションでデフォルトの指定を変え、0x8049000にしてみます。

ubuntu$ gcc -Wl,-Map=as01.map,-Ttext-segment=0x8049000 -o as01.exe as01.s

ubuntu$ grep "main" as01.map
                0x00000000080492c0                __libc_start_main@@GLIBC_2.0
                0x00000000080494db                main


0x8049000からtextセグメントが始まるため、このようになります。増やす単位はlinuxでのページサイズ0x1000(4KiB)の倍数でなければなりません。

 3. 終わりに

.orgでの指定も、リンカーでのtextセグメントの指定も、OSからローダーで読み込まれる実行プログラムでは通常、指定することはありません。また、むやみに指定することでOS上では異常な動きになることがあるので、熟知していない限りは変更することはお勧めできません。既に他の回答者様らから指摘があったように、これらは一般的に組み込み用途で、プログラマーが責任をもってROMやRAM上にプログラムとデータを配置する為に使うものと思っていてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/22 12:41

    回答ありがとうございました。
    org疑似命令やその他いろいろ誤解していましたした。
    本当に勉強になりました。
    ありがとうございました。

    キャンセル

+1

あります。

が、特別な場合を除き、配置アドレスはソースには書かないで、リンク時に指定するようにしますね

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/13 17:48

    回答ありがとうございます。
    いろいろ調べたのですがリンク時に指定する方法を自分では発見することができませんでした。
    もしよろしければ、具体的な方法を教えていただけないでしょうか
    よろしくお願いします。

    キャンセル

  • 2018/05/13 22:57

    だいたい、アセンブラのコードだけでプログラムを組む場合、一つだけのファイルで済むなら、ORG命令でコードのアドレスを決めてやればいいですが、そのファイルが数十とか数百とかの数になった場合、そのすべてのソースでORG命令でそれぞれのアドレスを決めていく、というのはいかに非現実的か想像できるでしょう。

    ということで、通常はセクションという単位で、ブロックをまとめ、そのセクションをどういうアドレスで、どういう配置で割り当てていくか、ということを行います
    その仕事を行うのがリンカというプログラムとなります

    GCCなんかの場合は、そのリンカに与える実行コードのブロック配置、アドレス割当を決定するのは、リンカスクリプト、というスクリプトファイルとなります
    そのすべてをここで解説する、というわけにもいかないんで、そこらへんのキーワードで調べてみてください。

    キャンセル

0

どんな用途に使うのでしょうか? 

セクションで区切って、そのセクションを割り付けるアドレスをリンカで指定するのが一般的と思ったのですが、違うのでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

Windowsの場合ならば、究極的にはバイナリエディタで編集するといった方法がありますので、GASでもできるかもしれません。(WindowsならばPEヘッダとかPEフォーマットで調べれば資料が見つかるはず)

もっとも、ロードアドレスに起因する処理が必要というケースはあまり想像できません。OSレベルならばわかりますけれど、これ以外ならば使用する必要があると思えません。あまりにもOS寄りも処理をやろうとするとウイルス対策ソフトに誤検知される恐れがあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/13 23:18

    Windowsアプリなんでしょうか?
    それにしても Windowsの場合、簡単に絶対アドレスで参照できるものでしょうか? 大抵は仮想アドレスと思います。

    キャンセル

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

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    ホスト設定てざっくりいうとなんなんでしょうか。

    こんにちは。Web制作会社で働く新人ディレクターgohansukunameです。 現場ではまだまだ聞き慣れない単語が飛び交う毎日です。 先輩> おい、gohansukuname!

  • 解決済

    アセンブリ言語とブートストラップ

    実験でフロッピーディスクにアセンブリ言語でプログラムを作ってブートストラップデータ領域で実行してみたんですが・・・ [org 0] [bits 16] jmp 0x07c

  • 解決済

    メモリの分割で混乱しています。

    よく本で。論理アドレス → リニアアドレス(仮想アドレス)→ 物理アドレス という順で変換しています・・・・みたいに書いてあるのですが、 1、セグメントで分割しているという

  • 解決済

    ASLRについて

    実験のためにソースコードを作ってやってみました。 両方ともASLR > 2で設定しています。 .#include <stdio.h> .#include <stdlib.

  • 解決済

    C# wi-fiのIPアドレスを取得する方法は無いものなのでしょうか?

    wi-fiに繋いで使用しているパソコンがあります。 そのパソコンが接続しているwi-fiの接続先は、随時変わっていく環境にありまして、接続先のIPアドレスを、一定時間ごとに記

  • 解決済

    迷惑メール対策(DKIM,SPF)の設定について

    システムからPostfixを使用してメールの送信を行っているのですが Fromアドレスのドメインをメールサーバーのドメインと異なるものを 設定し送信する必要があり、宛先によって

  • 解決済

    メールサーバーで怪しいログが出力される。

    いつもお世話になっております。 先日、下記のようなログが出力されたのですが、何らかの攻撃をされているのでしょうか? 危険度、および対応すべきかどうかわかりません。 ご指摘

  • 解決済

    [::1]とは

    http://[::1]/ci/index.php/controllers_login この[::1]ってどういう意味ですか? ログインした後に出てきます。

同じタグがついた質問を見る

  • C

    3563questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。