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

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

新規登録して質問してみよう
ただいま回答率
85.51%
C

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

Q&A

解決済

5回答

3486閲覧

nasm 擬似命令 orgについて

binary

総合スコア33

C

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

0グッド

1クリップ

投稿2018/05/10 03:47

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

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

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

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

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

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

guest

回答5

0

ベストアンサー

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

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)

x86asm

1.global main 2 3main: 4 movl $4, %eax 5 movl $1, %ebx 6 movl $message, %ecx 7 movl $21, %edx 8 int $0x80 9 10 movl $1, %eax 11 movl $0, %ebx 12 int $0x80 13 14.data 15message: .asciz "Hi! This is as01!1\n" 16 17# gcc -Wl,Map=as01.map -o as01.exe as01.s 18# 19# $ ./as01.exe 20# Hi! This is as01!! 21# $

これを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 を追加してみます。

x86asm

1.global main 2.org 0x100 3 4main: 5 movl $4, %eax 6 7...以下略

すると、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/18 04:37

dodox86

総合スコア9181

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

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

binary

2018/05/22 03:41

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

0

あります。

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

投稿2018/05/10 03:55

y_waiwai

総合スコア87715

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

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

binary

2018/05/13 08:48

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

2018/05/13 13:57

だいたい、アセンブラのコードだけでプログラムを組む場合、一つだけのファイルで済むなら、ORG命令でコードのアドレスを決めてやればいいですが、そのファイルが数十とか数百とかの数になった場合、そのすべてのソースでORG命令でそれぞれのアドレスを決めていく、というのはいかに非現実的か想像できるでしょう。 ということで、通常はセクションという単位で、ブロックをまとめ、そのセクションをどういうアドレスで、どういう配置で割り当てていくか、ということを行います その仕事を行うのがリンカというプログラムとなります GCCなんかの場合は、そのリンカに与える実行コードのブロック配置、アドレス割当を決定するのは、リンカスクリプト、というスクリプトファイルとなります そのすべてをここで解説する、というわけにもいかないんで、そこらへんのキーワードで調べてみてください。
guest

0

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

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

投稿2018/05/13 14:10

HogeAnimalLover

総合スコア4830

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

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

pepperleaf

2018/05/13 14:18

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

0

投稿2018/05/10 12:21

gingertail

総合スコア317

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

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

0

どんな用途に使うのでしょうか? インラインアセンブラ or ....

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

投稿2018/05/10 11:19

pepperleaf

総合スコア6383

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問