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

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

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

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

C

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

コンパイル

コンパイルとは、プログラミング言語のテキストソース(ソースコード)をコンピュータ上で実行可能な形式(オブジェクトコード)に変換することをいいます

リンカ

リンカはコンパイルされたオブジェクトコードに、必要なライブラリなどを付け加えて、実行可能ファイルを生成するプログラムです。コンパイルされたオブジェクトのコードを複数のファイルで取得し、"linked"という一つの実行可能のファイルを生成します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

696閲覧

C++の関数呼び出しにおけるリンクエラーの対処のしかたが分からない

freeza

総合スコア4

アセンブリ言語

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

C

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

コンパイル

コンパイルとは、プログラミング言語のテキストソース(ソースコード)をコンピュータ上で実行可能な形式(オブジェクトコード)に変換することをいいます

リンカ

リンカはコンパイルされたオブジェクトコードに、必要なライブラリなどを付け加えて、実行可能ファイルを生成するプログラムです。コンパイルされたオブジェクトのコードを複数のファイルで取得し、"linked"という一つの実行可能のファイルを生成します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

0クリップ

投稿2023/09/12 13:59

実現したいこと

  • C++の関数呼び出しのリンクエラーを対処したい

前提

ここに質問の内容を詳しく書いてください。
C++でCのコンパイラを作成しているのですが、以下のfunc.cppとtest.sをコンパイルして実行ファイルtestを実行しようとするとリンクエラーで怒られてしまいます。

発生している問題・エラーメッセージ

$ g++ -c func.cpp -o func.o $ g++ -c test.s -o test.o $ g++ -o test func.o test.o /usr/bin/ld: test.o: in function `main': (.text+0x1): undefined reference to `foo' collect2: error: ld returned 1 exit status

該当のソースコード

func.cpp

1#include <stdio.h> 2 3void foo() { 4 printf("function OK!\n"); 5}

test.s

1.intel_syntax noprefix 2.globl main 3main: 4 call foo

試したこと

コンパイラのバージョンを指定してコンパイルしてみましたが、同様のエラーが出ました。

$ g++ -std=c++20 -c func.cpp -o func.o $ g++ -std=c++20 -c test.s -o test.o $ g++ -std=c++20 -o test func.o test.o /usr/bin/ld: test.o: in function `main': (.text+0x1): undefined reference to `foo' collect2: error: ld returned 1 exit status

test.sを以下のように書き換えても同様のエラーが出ました。

test.s

1.intel_syntax noprefix 2.globl main 3.extern foo 4main: 5 call foo

また、func.cpp, test.sの二つのファイルは同じディレクトリの中にあることは確認済みです。

コンパイラやリンカ周りのことはまだあまり分かっていないのでどうやって解消すれば良いのか分かりません。ご回答よろしくお願いします。

melian👍を押しています

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

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

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

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

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

maisumakun

2023/09/12 14:35

void fooをextern "C"としてみたらどうなりますか?
freeza

2023/09/12 14:54

以下のようにvoid fooをextern "C"するとコンパイルが通りました!しかし、実行ファイルを実行するとfunction OK!と出力するのを期待しているのですが、segmentation faultとなってしまいました。 ```func.cpp #include <stdio.h> extern "C"{ void foo() { printf("function OK!\n"); } } ```
y_waiwai

2023/09/12 22:39

main関数の記述がどこにも見当たりませんが、そこらへんはどうなってるんでしょうか。 ソースコードは全部提示しましょう
freeza

2023/09/13 01:31

ご指摘ありがとうございます。ソースコードは全部提示しています。テストとしてfunc.cppに関数を書き、それをオブジェクトファイルにコンパイルして自分のコンパイラの出力とリンクさせると呼び出したい関数が呼ばれるかどうかを確認したかったです。
guest

回答2

0

ベストアンサー

Assembler names for functions

To specify the assembler name for functions, write a declaration for the function before its definition and put asm there, like this:

c

1int func (int x, int y) asm ("MYFUNC"); 2 3int func (int x, int y) 4{ 5 /* … */

This specifies that the name to be used for the function func in the assembler code should be MYFUNC.

なので、func.cppvoid foo () asm ("foo"); を追加します。

c

1#include <stdio.h> 2 3void foo () asm ("foo"); 4 5void foo() { 6 printf("function OK!\n"); 7}

bash

1$ g++ --version 2g++ (Ubuntu 12.3.0-1ubuntu1~23.04) 12.3.0 3 4$ g++ -std=c++20 -c func.cpp -o func.o 5$ g++ -std=c++20 -c test.s -o test.o 6$ g++ -std=c++20 -o test func.o test.o 7$ ./test 8function OK!

投稿2023/09/12 15:14

melian

総合スコア19840

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

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

freeza

2023/09/12 15:26

func.cppをご指摘の通りに修正するとコンパイルが通りました!しかし、実行結果がsegmentation faultとなってしまっていました。test.sは特に修正を加えていないですか?また、自分のg++のバージョンが11.40だったのですが、関係あるのでしょうか。
melian

2023/09/12 15:34

はい、test.s はそのままです。こちらでも g++ 11.4.0 で試したところ、segmentation fault になりました。差し支えがなければ g++ を 12.0 以上にアップグレードするとよいかと思います。
freeza

2023/09/13 01:27

g++のバージョン、ubuntuのバージョンを22.04から23.04に上げると通りました!ありがとうございます!ちなみに g++ -o test func.o test.o を実行すると /usr/bin/ld: warning: test.o: missing .note.GNU-stack section implies executable stack /usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker このような警告が出たのですが、melianさんはこのような警告は出ましたか?
melian

2023/09/13 01:45

はい、こちらでも出ています。少し調べてみたところ、test.s をアセンブルする際に -Wa,--noexecstack オプションを付けると警告が表示されなくなります。 g++ -std=c++20 -Wa,--noexecstack -c test.s -o test.o 詳しくは以下の記事をご参照下さい。 アセンブラを混ぜてコンパイルするとスタックが実行可になってしまう話 https://qiita.com/rarul/items/e1920e7ae5d5a28eec03
guest

0

実行結果がsegmentation faultとなってしまっていました。

call fooの後にretが要るかと思います。callから戻った後で直後にあるメモリーの内容を命令と見なして実行しようとするはず。
あるいは、jmp fooに変えるか。

投稿2023/09/12 17:45

otn

総合スコア84661

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

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

freeza

2023/09/13 01:28

ご指摘ありがとうございます。一応retがなくても関数は呼び出せました。
otn

2023/09/13 02:29

> 一応retがなくても関数は呼び出せました。 そりゃそうです。関数から戻った後の話なので。 回答に書いたとおりですが、次のメモリー内容によって、いろんな現象が出るかと思います。正常に見える現象も含め。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問