PCのCPUのアセンブリ言語もCPUに対してだいたいが一対一で対応しているため一つのアセンブリプログラムをアセンブラするならばリンカが必要ないと、参考書やネットなどで調べてわかりました。(高級言語を使う際はリンカがあったほうが便利ですが。)
<行いたいこと>
しかし(Linux上などで)複数のアセンブリプログラムを一つにする場合にはリンカは必要のようで、リンカのように複数のアセンブリプログラムを手作業で一つにまとめて見たいと考えています。
手作業で一つにまとめるとしたら、どの様にアセンブリプログラムを一つにまとめるのでしょうか?
調べたうちの方法の一つとしてハンドアセンブルというものがリンカの代わり?になるとも書いてありました。
できるならばマイコンなどのアセンブリ言語から始めたいと思っています。AVRなど。
いずれはLinuxをいれたPCで行いたいと思っています。
<達成目標>
私はリンカを使わないでアセンブリプログラムを一つにする方法が知りたいです!
どうかよろしくお願いします。
膨大なアセンブリプログラムをリンカを使わずに一つにするのに何か月何年かかっても構いません。
<編集>
解答して頂いた皆様どうもありがとうございます。
補足させていただきます。
OSはLinuxで想定しています。また本の一説なのかわかりませんがリンカがなかった昔の時代、自分でハンドアセンブルをしてオブジェクトファイルをリンクして実行ファイルを出力していたと書いてありました。(昔なので今のような64bitではなく、8bitなどのマイコンだと思います)
しかし、使っているPCのCPUは複雑すぎてハンドアセンブルするには不向きです。データシートがあったとしても初心者の私には無謀だし、無理です。なのでAVR、(Linuxを搭載した)ラズパイなどでハンドアセンブリを行いリンカの仕事を私の手でやってみます。
もしかしたら、AVR、(Linuxを搭載した)でハンドアセンブルが慣れればPCのCPUでもハンドアセンブルできるようになるかもしれませんがまだまだ先の話です。
<編集2>
確かに、アセンブラがあるのに、ハンドアセンブルでリンクする必要はないかもしれませんが、機械語(に直されたアセンブリ命令)をどうやって機械語で書いてあるオブジェクトファイルに使って実行ファイルにしたのか凄くきになるのです。
AVRマイコンにしても(Linuxを搭載した)ラズパイにしても、
機械語で書かれたオブジェクトファイルにハンドアセンブルして得た機械語を付け加えることで実行ファイルにしたのか、気になって仕方がありません
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/18 11:35
回答7件
0
こんにちは。
CPUに対してだいたいが一対一で対応しているため一つのアセンブリプログラムをアセンブラするならばリンカが必要ないと、参考書やネットなどで調べてわかりました。
アセンブルするのにリンカは不要です。実行可能形式へ変換するためにリンカが必要です。
もし、実行できるようにしたいのであれば、例え1つのアセンブリプログラムといえどもリンカ無しは現実的ではありません。
実行できるようにするわけでないなら、アーカイバを使って静的リンク・ライブラリに纏めることは可能です。
膨大なアセンブリプログラムをリンカを使わずに一つにするのに何か月何年かかっても構いません。
バイナリ・エディタを使って手で実行可能形式を作ることは不可能ではないと思います。実行可能形式のフォーマットの調査から始める場合は"Hello, world!"さえ1ヶ月くらい掛かるかも?
もし、これをされたいのであれば、実行可能形式のフォーマットが記載されているサイトや本について質問されたほうが良いと思います。対象OSを限定しないと回答は得られにくいと思います。
投稿2018/03/16 05:20
総合スコア23272
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/17 05:22 編集
2018/03/16 06:25
2018/03/16 06:59
2018/03/16 07:27
2018/03/16 08:18
2018/03/16 08:30
2018/03/16 12:27
2018/03/16 12:36
2018/03/16 13:42
2018/03/16 13:46
2018/03/16 19:17
2018/03/16 23:34
2018/03/17 01:04
2018/03/17 01:05
2018/03/17 01:40
2018/03/17 01:49
2018/03/17 01:51
2018/03/17 01:56
2018/03/17 01:59
2018/03/17 01:59
2018/03/17 02:01
2018/03/17 02:11
2018/03/17 02:18
2018/03/17 02:55
2018/03/17 03:09 編集
2018/03/17 03:14
2018/03/17 03:38
2018/03/17 05:06
2018/03/17 05:17
2018/03/17 05:24
2018/03/17 05:28
0
ベストアンサー
こんにちは。
元の回答のコメント・ツリーが長くなったことと、編集された質問への回答で回答内容が異なりますので、別途回答します。
リンカがなかった昔の時代、自分でハンドアセンブルをしてオブジェクトファイルをリンクして実行ファイルを出力していたと書いてありました。
ハンドアセンブルしていた時代は、オブジェクト・ファイルや実行ファイルなどは存在しないと思います。紙テープなどが良く使われていた頃と思います。
ハンドアセンブルの結果は、紙に手書きしたり、紙テープにパンチしたりです。
上記リンクは普通の紙に(恐らく)手書きしたブートローダをトグルスイッチでパチパチと入力した後、紙テープに記録されていたBasicインタプリタをロードして起動している動画です。
AVR、(Linuxを搭載した)
私がAVRを触っていた頃よりかなり進歩しているのでもしかするとあるかも知れませんが、基本的にAVRはlinuxを搭載できるようなCPUではありません。
また、ハンドアセンブルして実行可能形式を作るようなローレベルなことを行う場合は OSは無いほうがよいです。
OSの各種の約束事を学習するだけでも大変です。それらを学習する前にまずはOS上で「普通」のC言語プログラムを開発するスキルは必須です。
そして、OSのメモリ管理などの概念も把握しておかないと理解できませんので、OS配下の実行可能形式のフォーマットを理解するにはそれなりに膨大な時間がかかります。
OS配下のリンカは実行可能形式への変換を自動的に行ってくれますが、それを手でやるためには上記の理解が必要になります。
ハンドアセンブルでリンク
アセンブルとリンクは全く別の作業です。「ハンドアセンブルでリンクする」は「自転車をこいで海を渡る」という文と同じように間違った文です。単なるタイプミスなら良いのですが、複数回このような記述をされているので、アセンブルとリンクの役割を理解されていないと思います。仕組みを把握する前に役割を理解しないと無理があると思います。
機械語(に直されたアセンブリ命令)をどうやって機械語で書いてあるオブジェクトファイルに使って実行ファイルにしたのか凄くきになるのです。
意訳すると「アセンブリ言語で書かれたソース・ファイルから実行可能形式ファイルが作られるまでの過程が凄く気になるのです」でしょうか?
もし、YESの場合、AVRでは微妙にイメージが異なるかもしれません(クロス開発になる)が、単純ですから学習に向いており、かつ、情報も多く価格も安いので進めやすいと思います。
なお、この方向性はどちらかというと組み込み系のプログラムに有用です。
投稿2018/03/17 06:36
総合スコア23272
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/17 07:49
2018/03/17 08:25
2018/03/17 08:49
2018/03/17 08:51
2018/03/17 08:54
2018/03/17 09:12
2018/03/17 09:14
2018/03/17 09:21
2018/03/17 10:12 編集
2018/03/17 09:28
2018/03/17 10:14
2018/03/17 10:35
2018/03/17 12:25
2018/03/19 11:12 編集
0
こんにちは。
これまでの質問を含め、注視させてもらっていました。
今回の質問も収束するかと思ったのですが、質問の補足が追加されてどうもまだまだ閉じられる様子がなかったので。これまで有益な回答が多々されていたところに今更感もあり、瑣末で恐縮ですが、いち回答として受け留めてもらえれば、と。
最初に余計なことですがひとこと書かせてください。もとの回答から新たに発した質問に対する回答をコメント欄で求めるのはお止めになった方がよろしいかと思います。回答者様の多大な負担になります。
本題ですが、マイコンを取ってみてもその種類により、実際にはリンク作業はそのCPUボードのハードウェア構成やメモリマップによってアドレスが変わりますし、例えばジャンプ命令ひとつ取っても絶対/相対アドレッシングについてリンク過程で再計算が行われ、最終的な実行形式ファイルに書き込まれます。
それらを手動でリンクできたとしてもそれをどうCPUボードに載せて実行すると思いますか。PCではなく、組み込みのワンチップマイコンやCPUボードではインテルHEXフォーマットやモトローラSレコードと呼ばれるテキスト形式のファイルにして、CPUボードに転送して書き込んだりします。プログラムはCPUがリセットされて所定のアドレスから自動的に実行されるのに依存して動作します。AVRが載っているボードとしてはArduinoが有名ですが、これとてビルド(コンパイル〜リンク)して出来たイメージをArduinoへシリアル通信で転送して書き込みます。
PCで動くLinuxやWindowsなどのOSでは、ハードディスク等の外部記憶装置に保存されたファイルを読み出し、ファイルに付いているヘッダー情報をもとにOSが実行形式を特定して適切にメモリにロードし、必要ならアドレス情報を書き換えてそのプログラムを実行します。実行ファイルの形式についてはLinuxではELF、WindowsではPE(COFF)がありますので興味があればご自分で調べてみてください。
要はOSやハードウェアが違えば「リンク」や「ロード」して「実行」すると言う基本的な仕組み/概念が同じでも、実現手段である実装で変わってくると言うことです。それがある為、これまで、回答者の皆さんが当質問への回答に苦慮されています。
そう言ったことを理解するには、前提としてこれまで他の回答者様が言われていたように基本的なことを勉強した上で実際に手を動かし、思ったように動かないならば何故動かないのかを自分で考えて、それでもどうしても分からなければこういったteratailのような質問サイトで尋ねるとのようなかたちになるかと思います。※teratailのキャッチコピー「15分調べても分からないことは、質問しよう!」には反しますがw
低レイヤーのものやOSの仕組みに興味がある私としては、carnage0216さんのやりたいことが理解できない訳ではないです。
でも、「膨大なアセンブリプログラムをリンカを使わずに一つにするのに何か月何年かかっても構いません。」と言う目標ひとつを挙げても、本当にやるのであれば極めてマニュアル的で、退屈なわりに神経と時間を使う作業になるのは容易に予想できます。不可能とは言わないまでも、到底お勧めできることではありません。他に優先して勉強した方が良いことがあるでしょう。
そうではなく、これまで勧められてきたような基本的なことを実際に手を動かして理解したあとでは、今の目標とやりたいことも恐らく変わってくると思いますよ。
投稿2018/03/17 05:24
総合スコア9181
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/17 05:26
2018/03/17 05:32
2018/03/17 07:51
0
CPUが動く仕組みを知りたいのならこちらのシンプルなエミュレータでお試しください。
http://www.softantenna.com/wp/webservice/simple-8-bit-assembler-simulator/
http://schweigi.github.io/assembler-simulator/
現代的なシステムは難解過ぎます。
自分でリンクをするモチベーションがわかりません。
一般的には辞書を突き合わせる単純作業です。
リンカについてのいろいろな説明。
https://www.grapecity.com/tools/support/powernews/column/clang/003/page01.htm
http://sandragon.hatenablog.com/entry/2013/08/11/193936
http://p.booklog.jp/book/74354/page/1846900
https://プログラマが知るべき97のこと.com/エッセイ/リンカは魔法のプログラムではない/
http://sa.eei.eng.osaka-u.ac.jp/eeisa003/tani_prog/HOWTOprogC/compile.htm
http://chimolog.co/2017/06/bto-cpu-clock.html
CPUは凄まじい速度で単純処理をします。
Intel Core i7 7740X → 4.30 ~ 4.50Ghz
何か月何年かかっても構いません
大規模なリンクは何世代にも渡る大事業になるでしょう。
投稿2018/03/16 08:38
総合スコア8560
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/16 12:25
2018/03/17 12:59
0
家を建てたいです。
のこぎりの使い方を教えてください
と聞かれているようなw
別に、なにかをするというのはあなたの自由だけど、そのためになにかをするわけでなく、他人に質問丸投げってのはどーにかしたほうがいいんでない?
投稿2018/03/16 05:37
総合スコア87715
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/16 06:17
2018/03/16 06:22
2018/03/16 07:21
2018/03/16 07:35
2018/03/16 07:48
2018/03/16 08:23
0
アセンブラ次第でリンカを使わないで実行ファイルが得られる
・・・ことはありません・・・以下が理解できますか?
元のソース
c
1#include <stdio.h> 2 3int main(void) 4{ 5 printf("Hello Word!\n"); 6 7 return 0; 8} 9ーーーー 10アセンブラソース(元のソースを-Sオプションで出力したもの) 11 .text 12 .file "tst.c" 13 .globl main # -- Begin function main 14 .p2align 4, 0x90 15 .type main,@function 16main: # @main 17 .cfi_startproc 18# BB#0: 19 pushq %rax 20 .cfi_def_cfa_offset 16 21 movl $.Lstr, %edi 22 callq puts 23 xorl %eax, %eax 24 popq %rcx 25 retq 26.Lfunc_end0: 27 .size main, .Lfunc_end0-main 28 .cfi_endproc 29 # -- End function 30 .type .Lstr,@object # @str 31 .section .rodata.str1.1,"aMS",@progbits,1 32.Lstr: 33 .asciz "Hello Word!" 34 .size .Lstr, 12 35 36 37 .ident "clang version 6.0.0 (trunk 319536)" 38 .section ".note.GNU-stack","",@progbits 39ーーーー 40実行ファイル(上のアセンブル結果をリンカを通すと以下の様になります) 4100000000004003c0 <_init>: 42 4003c0: 48 83 ec 08 sub $0x8,%rsp 43 4003c4: 48 8b 05 2d 0c 20 00 mov 0x200c2d(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0> 44 4003cb: 48 85 c0 test %rax,%rax 45 4003ce: 74 05 je 4003d5 <_init+0x15> 46 4003d0: e8 3b 00 00 00 callq 400410 <__gmon_start__@plt> 47 4003d5: 48 83 c4 08 add $0x8,%rsp 48 4003d9: c3 retq 49 50セクション .plt の逆アセンブル: 51 5200000000004003e0 <puts@plt-0x10>: 53 4003e0: ff 35 22 0c 20 00 pushq 0x200c22(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8> 54 4003e6: ff 25 24 0c 20 00 jmpq *0x200c24(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10> 55 4003ec: 0f 1f 40 00 nopl 0x0(%rax) 56 5700000000004003f0 <puts@plt>: 58 4003f0: ff 25 22 0c 20 00 jmpq *0x200c22(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18> 59 4003f6: 68 00 00 00 00 pushq $0x0 60 4003fb: e9 e0 ff ff ff jmpq 4003e0 <_init+0x20> 61 620000000000400400 <__libc_start_main@plt>: 63 400400: ff 25 1a 0c 20 00 jmpq *0x200c1a(%rip) # 601020 <_GLOBAL_OFFSET_TABLE_+0x20> 64 400406: 68 01 00 00 00 pushq $0x1 65 40040b: e9 d0 ff ff ff jmpq 4003e0 <_init+0x20> 66 670000000000400410 <__gmon_start__@plt>: 68 400410: ff 25 12 0c 20 00 jmpq *0x200c12(%rip) # 601028 <_GLOBAL_OFFSET_TABLE_+0x28> 69 400416: 68 02 00 00 00 pushq $0x2 70 40041b: e9 c0 ff ff ff jmpq 4003e0 <_init+0x20> 71 72セクション .text の逆アセンブル: 73 740000000000400420 <set_fast_math>: 75 400420: 0f ae 5c 24 fc stmxcsr -0x4(%rsp) 76 400425: 81 4c 24 fc 40 80 00 orl $0x8040,-0x4(%rsp) 77 40042c: 00 78 40042d: 0f ae 54 24 fc ldmxcsr -0x4(%rsp) 79 400432: c3 retq 80 810000000000400433 <_start>: 82 400433: 31 ed xor %ebp,%ebp 83 400435: 49 89 d1 mov %rdx,%r9 84 400438: 5e pop %rsi 85 400439: 48 89 e2 mov %rsp,%rdx 86 40043c: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 87 400440: 50 push %rax 88 400441: 54 push %rsp 89 400442: 49 c7 c0 a0 05 40 00 mov $0x4005a0,%r8 90 400449: 48 c7 c1 30 05 40 00 mov $0x400530,%rcx 91 400450: 48 c7 c7 20 05 40 00 mov $0x400520,%rdi 92 400457: e8 a4 ff ff ff callq 400400 <__libc_start_main@plt> 93 40045c: f4 hlt 94 40045d: 0f 1f 00 nopl (%rax) 95 960000000000400460 <deregister_tm_clones>: 97 400460: b8 3f 10 60 00 mov $0x60103f,%eax 98 400465: 55 push %rbp 99 400466: 48 2d 38 10 60 00 sub $0x601038,%rax 100 40046c: 48 83 f8 0e cmp $0xe,%rax 101 400470: 48 89 e5 mov %rsp,%rbp 102 400473: 77 02 ja 400477 <deregister_tm_clones+0x17> 103 400475: 5d pop %rbp 104 400476: c3 retq 105 400477: b8 00 00 00 00 mov $0x0,%eax 106 40047c: 48 85 c0 test %rax,%rax 107 40047f: 74 f4 je 400475 <deregister_tm_clones+0x15> 108 400481: 5d pop %rbp 109 400482: bf 38 10 60 00 mov $0x601038,%edi 110 400487: ff e0 jmpq *%rax 111 400489: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 112 1130000000000400490 <register_tm_clones>: 114 400490: b8 38 10 60 00 mov $0x601038,%eax 115 400495: 55 push %rbp 116 400496: 48 2d 38 10 60 00 sub $0x601038,%rax 117 40049c: 48 c1 f8 03 sar $0x3,%rax 118 4004a0: 48 89 e5 mov %rsp,%rbp 119 4004a3: 48 89 c2 mov %rax,%rdx 120 4004a6: 48 c1 ea 3f shr $0x3f,%rdx 121 4004aa: 48 01 d0 add %rdx,%rax 122 4004ad: 48 d1 f8 sar %rax 123 4004b0: 75 02 jne 4004b4 <register_tm_clones+0x24> 124 4004b2: 5d pop %rbp 125 4004b3: c3 retq 126 4004b4: ba 00 00 00 00 mov $0x0,%edx 127 4004b9: 48 85 d2 test %rdx,%rdx 128 4004bc: 74 f4 je 4004b2 <register_tm_clones+0x22> 129 4004be: 5d pop %rbp 130 4004bf: 48 89 c6 mov %rax,%rsi 131 4004c2: bf 38 10 60 00 mov $0x601038,%edi 132 4004c7: ff e2 jmpq *%rdx 133 4004c9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 134 13500000000004004d0 <__do_global_dtors_aux>: 136 4004d0: 80 3d 5d 0b 20 00 00 cmpb $0x0,0x200b5d(%rip) # 601034 <_edata> 137 4004d7: 75 11 jne 4004ea <__do_global_dtors_aux+0x1a> 138 4004d9: 55 push %rbp 139 4004da: 48 89 e5 mov %rsp,%rbp 140 4004dd: e8 7e ff ff ff callq 400460 <deregister_tm_clones> 141 4004e2: 5d pop %rbp 142 4004e3: c6 05 4a 0b 20 00 01 movb $0x1,0x200b4a(%rip) # 601034 <_edata> 143 4004ea: f3 c3 repz retq 144 4004ec: 0f 1f 40 00 nopl 0x0(%rax) 145 14600000000004004f0 <frame_dummy>: 147 4004f0: 48 83 3d 28 09 20 00 cmpq $0x0,0x200928(%rip) # 600e20 <__JCR_END__> 148 4004f7: 00 149 4004f8: 74 1e je 400518 <frame_dummy+0x28> 150 4004fa: b8 00 00 00 00 mov $0x0,%eax 151 4004ff: 48 85 c0 test %rax,%rax 152 400502: 74 14 je 400518 <frame_dummy+0x28> 153 400504: 55 push %rbp 154 400505: bf 20 0e 60 00 mov $0x600e20,%edi 155 40050a: 48 89 e5 mov %rsp,%rbp 156 40050d: ff d0 callq *%rax 157 40050f: 5d pop %rbp 158 400510: e9 7b ff ff ff jmpq 400490 <register_tm_clones> 159 400515: 0f 1f 00 nopl (%rax) 160 400518: e9 73 ff ff ff jmpq 400490 <register_tm_clones> 161 40051d: 0f 1f 00 nopl (%rax) 162 1630000000000400520 <main>: 164 400520: 50 push %rax 165 400521: bf c0 05 40 00 mov $0x4005c0,%edi 166 400526: e8 c5 fe ff ff callq 4003f0 <puts@plt> 167 40052b: 31 c0 xor %eax,%eax 168 40052d: 59 pop %rcx 169 40052e: c3 retq 170 40052f: 90 nop 171 1720000000000400530 <__libc_csu_init>: 173 400530: 41 57 push %r15 174 400532: 41 89 ff mov %edi,%r15d 175 400535: 41 56 push %r14 176 400537: 49 89 f6 mov %rsi,%r14 177 40053a: 41 55 push %r13 178 40053c: 49 89 d5 mov %rdx,%r13 179 40053f: 41 54 push %r12 180 400541: 4c 8d 25 c0 08 20 00 lea 0x2008c0(%rip),%r12 # 600e08 <__frame_dummy_init_array_entry> 181 400548: 55 push %rbp 182 400549: 48 8d 2d c8 08 20 00 lea 0x2008c8(%rip),%rbp # 600e18 <__init_array_end> 183 400550: 53 push %rbx 184 400551: 4c 29 e5 sub %r12,%rbp 185 400554: 31 db xor %ebx,%ebx 186 400556: 48 c1 fd 03 sar $0x3,%rbp 187 40055a: 48 83 ec 08 sub $0x8,%rsp 188 40055e: e8 5d fe ff ff callq 4003c0 <_init> 189 400563: 48 85 ed test %rbp,%rbp 190 400566: 74 1e je 400586 <__libc_csu_init+0x56> 191 400568: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 192 40056f: 00 193 400570: 4c 89 ea mov %r13,%rdx 194 400573: 4c 89 f6 mov %r14,%rsi 195 400576: 44 89 ff mov %r15d,%edi 196 400579: 41 ff 14 dc callq *(%r12,%rbx,8) 197 40057d: 48 83 c3 01 add $0x1,%rbx 198 400581: 48 39 eb cmp %rbp,%rbx 199 400584: 75 ea jne 400570 <__libc_csu_init+0x40> 200 400586: 48 83 c4 08 add $0x8,%rsp 201 40058a: 5b pop %rbx 202 40058b: 5d pop %rbp 203 40058c: 41 5c pop %r12 204 40058e: 41 5d pop %r13 205 400590: 41 5e pop %r14 206 400592: 41 5f pop %r15 207 400594: c3 retq 208 400595: 90 nop 209 400596: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 210 40059d: 00 00 00 211 21200000000004005a0 <__libc_csu_fini>: 213 4005a0: f3 c3 repz retq 214 215セクション .fini の逆アセンブル: 216 21700000000004005a4 <_fini>: 218 4005a4: 48 83 ec 08 sub $0x8,%rsp 219 4005a8: 48 83 c4 08 add $0x8,%rsp 220 4005ac: c3 retq 221
投稿2018/03/17 10:43
編集2018/03/17 10:48総合スコア6851
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/17 13:13
2018/03/17 13:14
2018/03/17 13:15
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。