マシンコードの生成におけるアセンブラの使用についての簡単な説明を探しています。
したがって、アセンブリは機械語コードの 1:1 変換であることを知っています。しかし、オブジェクト コードとリンカー、およびそれらがどのように配置されるかについて混乱しています。
複雑な答えは必要ありません シンプルな答えで十分です
マシンコードの生成におけるアセンブラの使用についての簡単な説明を探しています。
したがって、アセンブリは機械語コードの 1:1 変換であることを知っています。しかし、オブジェクト コードとリンカー、およびそれらがどのように配置されるかについて混乱しています。
複雑な答えは必要ありません シンプルな答えで十分です
アセンブラもコンパイラも、ソース ファイルをオブジェクト ファイルに変換します。
オブジェクト ファイルは、最終的な実行可能出力 (リンカーによって生成される) の前の実質的な中間ステップです。
リンカーは、指定されたオブジェクト ファイルとライブラリ (オブジェクト ファイルのパッケージ) を取得し、再配置 (または「修正」) レコードを解決します。
これらの再配置レコードは、コンパイラ/アセンブラがソース コードで使用されている関数または変数のアドレスを認識せず、リンカによって解決できる名前で参照を生成する場合に作成されます。
たとえば、2 つのソース ファイルに分割されたメッセージを画面に出力するプログラムが必要であり、それらを個別にアセンブルしてリンクしたいとします (Linux x86-64 syscall を使用した例) -
main.asm :
bits 64
section .text
extern do_message
global _start
_start:
call do_message
mov rax, 1
int 0x80
メッセージ.asm:
bits 64
section .text
global do_message
do_message:
mov rdi, message
mov rcx, dword -1
xor rax, rax
repnz scasb
sub rdi, message
mov rax, 4
mov rbx, 1
mov rcx, message
mov rdx, rdi
int 0x80
ret
section .data
message: db "hello world",10,0
これらをアセンブルして main.asm のオブジェクト ファイル出力 (例: objdump -d main.o) を見ると、'call do_message' のアドレスが 00 00 00 00 であることがわかりますが、これは無効です。
0000000000000000 <_start>:
0: e8 00 00 00 00 callq 5 <_start+0x5>
5: 48 c7 c0 01 00 00 00 mov $0x1,%rax
c: cd 80 int $0x80
ただし、アドレスの 4 バイトに対して再配置レコードが作成されます。
$ objdump -r main.o
main.o: file format elf64-x86-64
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000001 R_X86_64_PC32 do_message+0xfffffffffffffffc
000000000000000d R_X86_64_32 .data
オフセットは '1' で、型は 'R_X86_64_PC32' で、リンカにこの参照を解決し、解決されたアドレスを指定されたオフセットに入れるように指示します。
最終的なプログラムを 'ld -o program main.o message.o' でリンクすると、再配置はすべて解決され、未解決のものがない場合は、実行可能ファイルが残ります。
実行可能ファイルを「objdump -d」すると、解決されたアドレスが表示されます。
00000000004000f0 <_start>:
4000f0: e8 0b 00 00 00 callq 400100 <do_message>
4000f5: 48 c7 c0 01 00 00 00 mov $0x1,%rax
4000fc: cd 80 int $0x80
関数だけでなく、変数にも同じ種類の再配置が使用されます。libc などの複数の大きなライブラリに対してプログラムをリンクすると、同じプロセスが発生します。libc が外部参照を持つ「main」という関数を定義すると、プログラムの前に libc が開始され、次の場合に「main」関数が呼び出されます。実行可能ファイルを実行します。
簡単な説明:
アセンブリ言語がオブジェクト コードにアセンブルされると、リンカーを使用してオブジェクト コードが、コンピューターが理解して実行できるコマンドの実行可能ファイルに変換されます。生成されたマシン コードは、CPU のコントローラーで解釈できます。