nasmでは擬似命令orgによってプログラムを格納するメモリーアドレスを指定できますよね?
GAS(gcc )にはnasmのorgのようなプログラムを格納するアドレスを指定するような擬似命令はあるんですか?
ない場合はどのように格納する場所を指定すれば良いのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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 , fill
のfill
とは、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
総合スコア9181
0
あります。
が、特別な場合を除き、配置アドレスはソースには書かないで、リンク時に指定するようにしますね
投稿2018/05/10 03:55
総合スコア87715
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/05/13 13:57
0
Windowsの場合ならば、究極的にはバイナリエディタで編集するといった方法がありますので、GASでもできるかもしれません。(WindowsならばPEヘッダとかPEフォーマットで調べれば資料が見つかるはず)
もっとも、ロードアドレスに起因する処理が必要というケースはあまり想像できません。OSレベルならばわかりますけれど、これ以外ならば使用する必要があると思えません。あまりにもOS寄りも処理をやろうとするとウイルス対策ソフトに誤検知される恐れがあります。
投稿2018/05/13 14:10
総合スコア4830
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/05/13 14:18
0
投稿2018/05/10 12:21
総合スコア317
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
どんな用途に使うのでしょうか? インラインアセンブラ or ....
セクションで区切って、そのセクションを割り付けるアドレスをリンカで指定するのが一般的と思ったのですが、違うのでしょうか?
投稿2018/05/10 11:19
総合スコア6383
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/05/22 03:41