この記事は群馬高専アドベントカレンダー2022の22日目の記事になります。
目次
自己紹介
いろんなプログラミング言語に手を出すのと競プロが好きです。
浅くいろんなものに手を出してます。最近は音楽とプラモデルにはまってます。
この頃とても便利な高レベル言語がたくさんあり、アセンブリといった低レベル言語を使う機会はあまりなくなりました。
しかし、弊学J科のマイコンの授業ではアセンブリの読み書きができるようにならなければいけません。
そのうえ学校の実行環境は特殊なソフトとマイコンを使うのであまり手軽ではなく難しいものとなっています。
情報系の学生にとってこのような状況は意外と多いのではないでしょうか
家でもアセンブリを読み書き・実行できると便利だと思いこの記事を書きました。
形式とかアーキテクチャとかについてはまだよく調べられてないので適当ですみません
gcc
ではc言語からアセンブリの生成ができます。
gcc
のほかにもzig cc
やclang
でもできるらしいです。
コンパイルオプションとして-S
を追加します。
標準ではAT&T形式
のアセンブリが生成され、追加でオプションを追加することでAT&T形式
とintel形式
を変えることができるらしいです。
例として、
gcc -S test.c
を実行するとtest.s
が生成されます。
このtest.s
はこのような内容になっています。
そこそこ長いので折りたたみます
test.c
のソースコード
int main() {
return 0;
}
出力結果
.text
.def @feat.00;
.scl 3;
.type 0;
.endef
.globl @feat.00
.set @feat.00, 0
.file "test.c"
.def main;
.scl 2;
.type 32;
.endef
.globl main # -- Begin function main
.p2align 4, 0x90
main: # @main
.seh_proc main
# %bb.0:
pushq %rbp
.seh_pushreg %rbp
subq $48, %rsp
.seh_stackalloc 48
leaq 48(%rsp), %rbp
.seh_setframe %rbp, 48
.seh_endprologue
callq __main
movl $0, -4(%rbp)
xorl %eax, %eax
addq $48, %rsp
popq %rbp
retq
.seh_endproc
# -- End function
.addrsig
objdump
コマンドを使用することで実行ファイルからアセンブリの生成ができます。
-d
オプションを使うことでdisassembleができます。
windowsでもこのコマンドを使用することができますが、
出力されるアセンブリがとても読みにくいため環境があればlinuxがおすすめです。
Linux 5.15.79.1-microsoft-standard-WSL2
での実行例を下にまとめます。
だいぶ長いので折りたたみます
test.c
元のC言語ファイル
int main() {
return 0;
}
コンパイルして実行ファイルにし、それをディスアセンブルする。
gcc test.c
objdump -d ./a.out
出力結果
./a.out: file format elf64-x86-64
Disassembly of section .init:
0000000000001000 <_init>:
1000: f3 0f 1e fa endbr64
1004: 48 83 ec 08 sub $0x8,%rsp
1008: 48 8b 05 d9 2f 00 00 mov 0x2fd9(%rip),%rax # 3fe8 <__gmon_start__@Base>
100f: 48 85 c0 test %rax,%rax
1012: 74 02 je 1016 <_init+0x16>
1014: ff d0 call *%rax
1016: 48 83 c4 08 add $0x8,%rsp
101a: c3 ret
Disassembly of section .plt:
0000000000001020 <.plt>:
1020: ff 35 a2 2f 00 00 push 0x2fa2(%rip) # 3fc8 <_GLOBAL_OFFSET_TABLE_+0x8>
1026: f2 ff 25 a3 2f 00 00 bnd jmp *0x2fa3(%rip) # 3fd0 <_GLOBAL_OFFSET_TABLE_+0x10>
102d: 0f 1f 00 nopl (%rax)
Disassembly of section .plt.got:
0000000000001030 <__cxa_finalize@plt>:
1030: f3 0f 1e fa endbr64
1034: f2 ff 25 bd 2f 00 00 bnd jmp *0x2fbd(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
103b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
Disassembly of section .text:
0000000000001040 <_start>:
1040: f3 0f 1e fa endbr64
1044: 31 ed xor %ebp,%ebp
1046: 49 89 d1 mov %rdx,%r9
1049: 5e pop %rsi
104a: 48 89 e2 mov %rsp,%rdx
104d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1051: 50 push %rax
1052: 54 push %rsp
1053: 45 31 c0 xor %r8d,%r8d
1056: 31 c9 xor %ecx,%ecx
1058: 48 8d 3d ca 00 00 00 lea 0xca(%rip),%rdi # 1129 <main>
105f: ff 15 73 2f 00 00 call *0x2f73(%rip) # 3fd8 <__libc_start_main@GLIBC_2.34>
1065: f4 hlt
1066: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1)
106d: 00 00 00
0000000000001070 <deregister_tm_clones>:
1070: 48 8d 3d 99 2f 00 00 lea 0x2f99(%rip),%rdi # 4010 <__TMC_END__>
1077: 48 8d 05 92 2f 00 00 lea 0x2f92(%rip),%rax # 4010 <__TMC_END__>
107e: 48 39 f8 cmp %rdi,%rax
1081: 74 15 je 1098 <deregister_tm_clones+0x28>
1083: 48 8b 05 56 2f 00 00 mov 0x2f56(%rip),%rax # 3fe0 <_ITM_deregisterTMCloneTable@Base>
108a: 48 85 c0 test %rax,%rax
108d: 74 09 je 1098 <deregister_tm_clones+0x28>
108f: ff e0 jmp *%rax
1091: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
1098: c3 ret
1099: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
00000000000010a0 <register_tm_clones>:
10a0: 48 8d 3d 69 2f 00 00 lea 0x2f69(%rip),%rdi # 4010 <__TMC_END__>
10a7: 48 8d 35 62 2f 00 00 lea 0x2f62(%rip),%rsi # 4010 <__TMC_END__>
10ae: 48 29 fe sub %rdi,%rsi
10b1: 48 89 f0 mov %rsi,%rax
10b4: 48 c1 ee 3f shr $0x3f,%rsi
10b8: 48 c1 f8 03 sar $0x3,%rax
10bc: 48 01 c6 add %rax,%rsi
10bf: 48 d1 fe sar %rsi
10c2: 74 14 je 10d8 <register_tm_clones+0x38>
10c4: 48 8b 05 25 2f 00 00 mov 0x2f25(%rip),%rax # 3ff0 <_ITM_registerTMCloneTable@Base>
10cb: 48 85 c0 test %rax,%rax
10ce: 74 08 je 10d8 <register_tm_clones+0x38>
10d0: ff e0 jmp *%rax
10d2: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
10d8: c3 ret
10d9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
00000000000010e0 <__do_global_dtors_aux>:
10e0: f3 0f 1e fa endbr64
10e4: 80 3d 25 2f 00 00 00 cmpb $0x0,0x2f25(%rip) # 4010 <__TMC_END__>
10eb: 75 2b jne 1118 <__do_global_dtors_aux+0x38>
10ed: 55 push %rbp
10ee: 48 83 3d 02 2f 00 00 cmpq $0x0,0x2f02(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
10f5: 00
10f6: 48 89 e5 mov %rsp,%rbp
10f9: 74 0c je 1107 <__do_global_dtors_aux+0x27>
10fb: 48 8b 3d 06 2f 00 00 mov 0x2f06(%rip),%rdi # 4008 <__dso_handle>
1102: e8 29 ff ff ff call 1030 <__cxa_finalize@plt>
1107: e8 64 ff ff ff call 1070 <deregister_tm_clones>
110c: c6 05 fd 2e 00 00 01 movb $0x1,0x2efd(%rip) # 4010 <__TMC_END__>
1113: 5d pop %rbp
1114: c3 ret
1115: 0f 1f 00 nopl (%rax)
1118: c3 ret
1119: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
0000000000001120 <frame_dummy>:
1120: f3 0f 1e fa endbr64
1124: e9 77 ff ff ff jmp 10a0 <register_tm_clones>
0000000000001129 <main>:
1129: f3 0f 1e fa endbr64
112d: 55 push %rbp
112e: 48 89 e5 mov %rsp,%rbp
1131: b8 00 00 00 00 mov $0x0,%eax
1136: 5d pop %rbp
1137: c3 ret
Disassembly of section .fini:
0000000000001138 <_fini>:
1138: f3 0f 1e fa endbr64
113c: 48 83 ec 08 sub $0x8,%rsp
1140: 48 83 c4 08 add $0x8,%rsp
1144: c3 ret
gcc
ではアセンブリを.s
ファイルとして認識し、
gcc test.s
とするとアセンブリファイルから実行ファイルを生成してくれます。
これもgcc
のほかにもzig cc
やclang
でもできるらしいです。
これは余談なのですが、gcc
では.c
ファイル、.h
ファイルをコンパイルできるのは有名ですが、ほかのファイルを渡した場合どうなるのでしょう。
そもそもgcc
のcc
はC Compilerの略ではなく、Compiler Collectionのcc
らしいです。
そして、公式ホームページによると、
The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, Go, and D, as well as libraries for these languages (libstdc++,...)
と、いろいろな言語をサポートしているようです。(c言語以外で使ったことないですが、、、)
これもそこそこ長いので折りたたみます
適当にフィボナッチ数列のrdi
項目を求めるプログラムtest.s
を書きました。
.intel_syntax noprefix
.globl main
fib:
mov rdx, 0
mov rcx, 1
fib_loop:
mov rsi, 0
add rsi, rdx
add rsi, rcx
mov rdx, rcx
mov rcx, rsi
sub rdi, 1
cmp rdi, 0
jne fib_loop
mov rax, rsi
ret
main:
mov rdi, 5
call fib
ret
gcc test.s
./a.out
を実行すると生成されたa.out
が実行されます。
(windowsならa.exe?)
出力結果は
bash
echo $?
fish
echo $status
powershell
echo $LASTEXITCODE
で見ることができます。
さいごに
アセンブリと仲良くなりましょう!!
次は、「こひむ」さんの「高専プロコン失敗談」です。