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

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

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

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

C

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

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

Q&A

解決済

4回答

2355閲覧

NASM GCC オブジェクトファイルをリンクさせたい

kazuyakazuya

総合スコア193

アセンブリ言語

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

C

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

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

0グッド

0クリップ

投稿2020/03/07 00:45

どうしても解決できそうにありません。どうかお願いします


リンク内容
上記の方法もやってみましたが
NASM形式に変換するツールというのが正常に動いているのかの判断が難しいうえに
マクロ、アセンブリ側のラベルをC言語側で参照できなさそうなので
こちらの方法は諦めました。


アセンブリプログラムとCプログラムをくっつけたいです。
カーネルをすべてアセンブリ言語で書くのは嫌なのでC言語も使いたい

リンカでオブジェクトファイルをくっつけたい場合
そのオブジェクトファイルたちの形式はそれぞれ同じにしなければいけない(と聞きました)
私が最終的に作りたいのはディスクイメージです。(つまり、ELF形式とかではなくただのバイト列)

①アセンブリプログラムとCプログラムをなんらかの方法で同じオブジェクト形式のファイルを生成する。
②2つのオブジェクトファイルをgcc,ld binutilのツール群でリンクさせる
③生成された何らかの形式の実行可能ファイルからobjdumpを使いバイナリ形式に変換させる。

前提としてCプログラムにはGCC
アセンブリプログラムにはNASM を使います。

1:Cプログラム gcc
Cプログラム(リンカを使う場合セクションを決める必要があるが それ以前のところで躓いているので
今回は省略 プログラムは適当にどっかから持ってきました。)
ファイル名:sample.c

c

1int function1 (void){ 2 int i,j; 3 for(i=1;i<21;i++) 4 j= i + 100; 5 return 0; 6 }

生成したオブジェクトファイル名:sample.o
以下のコマンドを使ってオブジェクト形式に!

cmd

1gcc -c -o sample.o sample.c

objdumpで何の形式でできているのか確認します。

cmd

1 2sample.o: file format pe-i386 3 4 5Disassembly of section .text: 6 700000000 <_aaa>: 8 0: 55 push %ebp 9 1: 89 e5 mov %esp,%ebp 10 3: 83 ec 28 sub $0x28,%esp 11 6: c7 45 f4 01 00 00 00 movl $0x1,-0xc(%ebp) 12 d: eb 0d jmp 1c <_aaa+0x1c> 13 f: 8b 45 f4 mov -0xc(%ebp),%eax 14 12: 83 c0 64 add $0x64,%eax 15 15: 89 45 f0 mov %eax,-0x10(%ebp) 16 18: 83 45 f4 01 addl $0x1,-0xc(%ebp) 17 1c: 83 7d f4 14 cmpl $0x14,-0xc(%ebp) 18 20: 7e ed jle f <_aaa+0xf> 19 22: 8b 45 f4 mov -0xc(%ebp),%eax 20 25: 89 44 24 04 mov %eax,0x4(%esp) 21 29: c7 04 24 00 00 00 00 movl $0x0,(%esp) 22 30: e8 00 00 00 00 call 35 <_aaa+0x35> 23 35: b8 00 00 00 00 mov $0x0,%eax 24 3a: c9 leave 25 3b: c3 ret

2:アセンブリプログラム nasm

アセンブリプログラム 
ファイル名: boot.s
(ちょっと長いので省略)

s

1BOOT_LOAD equ 0x7C00 2ORG BOOT_LOAD 3 4;/_/_/_/_/_/_/_/ 5;マクロ 6;/_/_/_/_/_/_/_/ 7%include "../include/marco.s" 8%include "../include/define.s" 9 10;/_/_/_/_/_/_/_/ 11;BPB 12;/_/_/_/_/_/_/_/ 13 14entry: 15jmp ipl 16times 90 - ($ - $$) db 0x90 ;先頭から90バイトまでをnop命令で埋め尽くす。 17 18;/_/_/_/_/_/_/_/ 19;ブートローダー本体 20;/_/_/_/_/_/_/_/ 21

以下のコマンドを使います!
生成するファイル名: boot.o

cmd

1nasm -o boot.o boot.s

ファイル形式を確認します。

objdump

1>objdump -d boot.o 2objdump: boot.o: file format not recognized

(NASMは余計な情報を付けずにコンパイルしてくれる)
Cオブジェクトファイルのファイル形式はpe-i386
アセンブリオブジェクトファイルのファイル形式もpe-i386にしないとリンクできない(たぶん)
ので
nasmで指定できる出力形式一覧を表示

cmd

1bin flat-form binary files (e.g. DOS .COM, .SYS) 2 ith Intel hex 3 srec Motorola S-records 4 aout Linux a.out object files 5 aoutb NetBSD/FreeBSD a.out object files 6 coff COFF (i386) object files (e.g. DJGPP for DOS) 7 elf32 ELF32 (i386) object files (e.g. Linux) 8 elf64 ELF64 (x86_64) object files (e.g. Linux) 9 elfx32 ELFX32 (x86_64) object files (e.g. Linux) 10 as86 Linux as86 (bin86 version 0.3) object files 11 obj MS-DOS 16-bit/32-bit OMF object files 12 win32 Microsoft Win32 (i386) object files 13 win64 Microsoft Win64 (x86-64) object files 14 rdf Relocatable Dynamic Object File Format v2.0 15 ieee IEEE-695 (LADsoft variant) object file format 16 macho32 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files 17 macho64 NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files 18 dbg Trace of all info passed to output stage 19 elf ELF (short name for ELF32) 20 macho MACHO (short name for MACHO32) 21 win WIN (short name for WIN32)

見た限りpe-i386はありません。
nasm -f (形式) -o boot.o boot.s
ですべてのパターンを試しましたが
bin,ith,srec以外はエラーが発生しオブジェクトファイルにするこができませんでした。
(boot.s:2: error: parser: instruction expected
ORGなどの疑似命令のところで躓きます。)

アセンブリ側もC言語側もsrec形式なら正常にオブジェクトファイルに変換することができたので
srec形式にした2つのオブジェクトファイルをリンカでくっつけます。

cmd

1>objdump -d sample.bin 2 3sample.bin: file format srec 4 5objdump: can't disassemble for architecture UNKNOWN! 6 7 8>objdump -d boot.o 9 10boot.o: file format srec 11 12objdump: can't disassemble for architecture UNKNOWN! 13 14

cmd

1>gcc boot.o sample.o 2c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: unknown architecture of input file `boot.o' is incompatible with i386 output 3c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: unknown architecture of input file `sample.o' is incompatible with i386 output 4c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../libmingw32.a(main.o):(.text.startup+0xb0): undefined reference to `WinMain@16' 5collect2.exe: error: ld returned 1 exit status 6 7 8 9 10 11 12>ld boot.o sample.o 13ld: unknown architecture of input file `boot.o' is incompatible with i386 output 14ld: unknown architecture of input file `sample.o' is incompatible with i386 output 15 16 17 18 19 20 21 22 23 24>ar rvs sample.o boot.o 25ar: sample.o: file format not recognized 26

できませんでした・・・。
何か解決策はないでしょうか?
boot.o
イメージ説明
sample.o
イメージ説明
同じsrec形式のはずですが・・・
なんか違いますよね?

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

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

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

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

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

dodox86

2020/03/07 02:13

何でsrecの話が出てくるのか分かりません。テキストファイルですよ。tftpブートか何か知りませんが、Sレコードを扱うブートローダーでも使っているのですか。
dodox86

2020/03/07 02:17

失礼、質問を読み違えていました。srec形式で出力して後で何とかしようという意図ですね。
dodox86

2020/03/07 02:20

mingwを使っている時点でなんか難しそうな気がしますが、大丈夫なのでしょうか。一般的にmingwはWindow環境下でWindows用のアプリを作る為のツールセット、と言う立場のはずですが。
kazuyakazuya

2020/03/07 03:12 編集

>sample.oのほうが合ってます。 では、boot.oのほうがsrecにできていないということですね。 >srec形式で出力して後で何とかしようという意図ですね。 srec形式(srecとはなんなのかはよくわかっていなかったが)のオブジェクトファイルを生成し リンカでくっつけたのち objdumpを使ってELFでいうところの.text領域だけを抽出してディスクイメージを作れないのか?と 考えました。 >一般的にmingwはWindow環境下でWindows用のアプリを作る為のツールセット、と言う立場のはずですが。 windows用というのは知りませんでした・・・。 システムコールは一切使っていない場合でも考慮する必要があるのでしょうか?
dodox86

2020/03/07 03:24

> objdumpを使ってELFでいうところの.text領域だけを抽出してディスクイメージを作れないのか?と 考えました。 Sレコード形式というのはcateyeさんのご案内にもあるように、単純にはマシンコードとそれをどのアドレスに割り付けるか、を記述したテキストファイルです。objdumpがそれを読み込んでフラットなバイナリのファイルに出力できているのであれば、可能だということでしょう。(実際にできているかは私は分かりません) > システムコールは一切使っていない場合でも考慮する必要があるのでしょうか? あるでしょうね。それが、PE形式の実行ファイルを最終的に正しく出力するためのコード中の疑似命令だったりします。Windows用のオブジェクトファイルを生成するに足りない情報があったら、エラーで終わってもおかしくありません。
guest

回答4

0

gccでnasmとリンクする方法自体は調べれば出てきます。

ただし、ORG疑似命令はリンカを使わずにフラットバイナリを作る時専用の命令なので
オブジェクトファイルの生成のためには使えません。


MBRの制約として主に2点あります。

  • フラットバイナリである
  • 読み込まれるサイズが512バイトと極小である

よって、ブートローダーはそもそもリンカで生成するのか?という疑問があります。
カーネルローダー以降になればサイズ制限は緩和されますが
依然としてフラットバイナリもしくはそれに近い形式である必要があり
リンカスクリプトを自作するなりしないといけないので難しいです
(aoutならいけるかもしれんが、20年くらい前の形式なのでgccが対応してないとか)

Windows上でビルドを行うのならばUEFIを検討してみるのもいいかもしれません。


個人的にはカーネルからすべてC
それ以前はすべてアセンブリ
でやろうと思っているのですが。。。

えっと、ブートローダーとカーネルローダー(2nd boot loader)は別のプログラムですしカーネルも別のプログラムです。

それぞれ別個のファイルを生成した後にディスクイメージ生成ツールなどでディスクイメージに纏めます。
ですので、ブートローダーのオブジェクトファイルを作ったり、それをリンクする必要はありません。

もし万が一、「各プログラムをクラスタサイズ以下でなんとかする」場合(or「FATなんてしるか」)
incbin疑似命令を用いる事でnasmでディスクイメージを作る事も不可能ではないです。
私は管理領域作るのが面倒くさいのでやりたくないですが

投稿2020/03/08 23:59

編集2020/03/09 17:04
asm

総合スコア15149

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

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

kazuyakazuya

2020/03/09 13:38

>オブジェクトファイルの生成のためには使えません。 私は ①pe-i386オブジェクトファイル生成 ②リンク という手順でやっていますが つまり ①の段階でORG命令が使えなくなっていたんですね・・・。 ORG命令がないブートプログラム(何もしないけど・・・) section .text [BITS 16] ;ORG 0x7C00 jmp $ TIMES 510 - ($ - $$) DB 0 DW 0xAA55 リンカスクリプト OUTPUT_FORMAT("pe-i386"); /* OUTPUT_ARCH(v850);*/ /* ENTRY(__startup); */ SECTIONS { .text 0x7C00: { boot2.o(.text) } } nasm -f win32 -o boot.o boot.s ld -T linker.c boot.o objcopy -O binary a.exe os.img こちらで正常にブートプログラムをリンクを使いディスクイメージを作成することができました。
kazuyakazuya

2020/03/09 13:39

ただ、Cプログラムのリンクはまだ成功していません・・・。 >ブートローダーはそもそもリンカで生成するのか?という疑問があります。 ここが理解できないのですが ブートローダーをリンカで生成してはまずいのですか?
asm

2020/03/09 14:40 編集

512バイトですので 1命令2バイト換算で256命令、4バイトで計算すると128命令です。 大体200命令程度でサイズオーバーになる事が予想されます。 リンカによって機械的に命令をつなぎ合わせようとするとアラインメントなどの関係で空き領域ができます。 またC言語を書いている時に何バイト消費し残り何バイトかを把握するのは困難です。 さらにいうとコンパイラによって生成する命令が変わってくるのも問題になりえます。 以上からMBRについてはC言語およびリンカは適していないように思います。 (さらにいうとGRUB使えば自作する必要に疑問があります)
kazuyakazuya

2020/03/09 14:53

それというのはアセンブリ言語とC言語を組み合わせてMBR付近を作成する場合でしょうか? 個人的にはカーネルからすべてC それ以前はすべてアセンブリ でやろうと思っているのですが。。。
asm

2020/03/09 15:29

ブートローダーの話ですので、カーネルはまた違ってきます。
kazuyakazuya

2020/03/10 01:03

追加で悪いのですが・・・ 追記の部分に関して ブートプログラム(S)もカーネル(C)もバイナリ形式にして typeコマンド(?)とかで連結させるだけでいけるのでしょうか?
asm

2020/03/10 01:22

あなたが何を生成したいのかにもよりますが、基本ダメです FATなんてしるか、FD/CD/USBひとつでカーネルがロードできればそれでいい というのならば、それでもいいのかもしれませんが・・・ (CDは無理かな エラー訂正せんとダメな気がする)
kazuyakazuya

2020/03/10 04:55

わかりました ありがとうございます。
guest

0

自己解決

直接的な解決ではないですが目的は達成しました。
objcopyコマンドでC・アセンブリコードをrawバイナリ形式に変換します。
(ブートローダーのコードに関しては最終的にCで書かれたカーネルへジャンプする
ように仕向ける。)
バイナリエディタでうまくそれぞれをくっつけることで
アセンブリ言語で書かれたブートプログラムからCで書かれたカーネルへ制御を移らせることができました。

投稿2020/03/14 06:00

kazuyakazuya

総合スコア193

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

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

0

解決への直接の回答ではなく、質問文を読んで気が付いた点の指摘と、考えうる次の方法の提示のみです:

Windows上でmingwのツールセットを使って作業をされているようですが、質問へのコメントにも書きましたように、MinGWは(Minimalist GNU for Windows)の名の通り、Windows上においてWindowsアプリケーションを作る為のgccのツールセットです。その為、それ以外のプラットフォームで使われることを想定したオプションは使えない可能性があります。コマンド自体gccldなど、さもLinux上で使う場合と同じように見えますが、それらのコマンド実行ファイルをビルドするときにMinGW用のカスタマイズをしているでしょうから、今回質問者さんが使いたいオプションが省かれていることも充分考えられます。それが、MinGW版ldの以下のエラー出力に表れているものと思えます。

ld: unknown architecture of input file `boot.o' is incompatible with i386 output

MinGW版ldはWindows用の実行ファイル形式のみを正しく取り扱える(のではないか)と言うことです。

nasmにも同様のことが言えていて、そのnasmを実行しているプラットフォーム用の出力しかできない、と言うことでしょう。pe-386とはWindowsの実行形式ファイルのPortable Executableの32ビット版を指していると思いますが、pe-386と言う単語はただの自己都合の略称です。質問文中に提示されたnasmの出力形式の一覧で言うと、

win32 Microsoft Win32 (i386) object files

に相当するはずです。すべてのパターンを試されたもののこのwin32が失敗したというのであれば、pe-386(= win32)のオブジェクトファイルを作成する、つまりはWindows用の実行形式ファイルで持っていなければならないセクションなどを指定する疑似命令が存在せず、適切なオブジェクトファイルを出力できない、と言うことなのでしょう。たぶん。

あくまで推測ですが、MinGWのツールセットで作業を続行するのは限界があると思います。より可能性があるのはUbuntuなどのLinux上で使うgcc/binutilのツールセットですが、それすらもMinGWと同じ事情があってもおかしくありません。Linuxカーネルのビルドシステムはこれらツールセットを含め、注意深くオプションが設定されていますが、質問者であるkazuyakazuyaさんのケースではもともと特異なことに挑戦されているのですから、それなりに適切で手間がかかる作業があって当然です。場合によってはgccldnasmも、自分で出力するオプションをカスタマイズしてそれらコマンドをビルドしなければならないことになってもおかしくありません。

投稿2020/03/07 03:09

dodox86

総合スコア9256

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

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

kazuyakazuya

2020/03/07 03:23

うーん、わかりました。
guest

0

気軽にアセンブリプログラムを、といってますが、ニーモニック書いたからと言ってそのままリンク、実行できるわけじゃありません
そのコードをどういう属性でどこに配置するのか、データエリアはどこに確保しどう初期化するのかという情報を全部指定してやらなければなりません

あなたが削除、省略した疑似命令というのはそこらへんの必要な指定命令なんです。

まずはそこらへんの知識をつけましょう。

投稿2020/03/07 01:40

y_waiwai

総合スコア88042

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問