7. 言語基礎(1)— コンパイル結果のアセンブリを読む
7.1. この章で学ぶこと
前章リスト-1(
language_basics_minimal.mojo)のコンパイル結果が、スタック上で何をしているか定数畳み込み、
List構築、文字列オブジェクト、引数テーブル、後片付けパターンの流れ
前章では、言語基礎の最小サンプル(リスト-1)を示しました。
この章では、そのコンパイル結果(リスト-2)を手がかりに、main() の機械語を段階的に追います。
このコードをコンパイルすると、実際には機械語へ変換されます。
language_basics_minimal.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <language_basics_minimal::main()>:
; def main():
0: 48 81 ec 08 03 00 00 subq $776, %rsp # imm = 0x308
; var n: Int = 42
7: 48 c7 84 24 e8 00 00 00 2a 00 00 00 movq $42, 232(%rsp)
; var doubled = n * 2
13: 48 c7 84 24 f0 00 00 00 54 00 00 00 movq $84, 240(%rsp)
; var xs: List[Int] = [1, 2, 3]
1f: 48 c7 84 24 10 01 00 00 01 00 00 00 movq $1, 272(%rsp)
2b: 48 c7 84 24 18 01 00 00 02 00 00 00 movq $2, 280(%rsp)
37: 48 c7 84 24 20 01 00 00 03 00 00 00 movq $3, 288(%rsp)
43: 48 8d 84 24 10 01 00 00 leaq 272(%rsp), %rax
4b: 48 89 84 24 28 01 00 00 movq %rax, 296(%rsp)
53: 48 8d 84 24 18 01 00 00 leaq 280(%rsp), %rax
5b: 48 89 84 24 30 01 00 00 movq %rax, 304(%rsp)
63: 48 8d 84 24 20 01 00 00 leaq 288(%rsp), %rax
6b: 48 89 84 24 38 01 00 00 movq %rax, 312(%rsp)
73: be 03 00 00 00 movl $3, %esi
78: 48 8d bc 24 28 01 00 00 leaq 296(%rsp), %rdi
80: 90 nop
81: 48 89 bc 24 b8 02 00 00 movq %rdi, 696(%rsp)
89: 48 c7 84 24 c0 02 00 00 03 00 00 00 movq $3, 704(%rsp)
95: 90 nop
96: 48 89 bc 24 c8 02 00 00 movq %rdi, 712(%rsp)
9e: 48 c7 84 24 d0 02 00 00 03 00 00 00 movq $3, 720(%rsp)
aa: 48 8d 94 24 f8 00 00 00 leaq 248(%rsp), %rdx
b2: e8 00 00 00 00 callq 0xb7 <language_basics_minimal::main()+0xb7>
; var xs: List[Int] = [1, 2, 3]
b7: 48 8d bc 24 47 01 00 00 leaq 327(%rsp), %rdi
bf: e8 00 00 00 00 callq 0xc4 <language_basics_minimal::main()+0xc4>
; var label = String("count")
c4: 48 c7 84 24 50 01 00 00 05 00 00 00 movq $5, 336(%rsp)
d0: 48 8d 84 24 48 01 00 00 leaq 328(%rsp), %rax
d8: 48 89 84 24 90 00 00 00 movq %rax, 144(%rsp)
e0: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0xe7 <language_basics_minimal::main()+0xe7>
e7: 48 89 84 24 60 01 00 00 movq %rax, 352(%rsp)
ef: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0xf6 <language_basics_minimal::main()+0xf6>
f6: 48 89 84 24 68 01 00 00 movq %rax, 360(%rsp)
fe: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x105 <language_basics_minimal::main()+0x105>
105: 48 89 84 24 48 01 00 00 movq %rax, 328(%rsp)
10d: 48 8d 84 24 48 01 00 00 leaq 328(%rsp), %rax
115: 48 83 c0 10 addq $16, %rax
119: 48 89 84 24 98 00 00 00 movq %rax, 152(%rsp)
121: 48 b8 00 00 00 00 00 00 00 20 movabsq $2305843009213693952, %rax # imm = 0x2000000000000000
12b: 48 89 84 24 58 01 00 00 movq %rax, 344(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
133: 48 c7 84 24 78 01 00 00 02 00 00 00 movq $2, 376(%rsp)
13f: 48 8d 84 24 70 01 00 00 leaq 368(%rsp), %rax
147: 48 89 84 24 a0 00 00 00 movq %rax, 160(%rsp)
14f: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x156 <language_basics_minimal::main()+0x156>
156: 48 89 84 24 88 01 00 00 movq %rax, 392(%rsp)
15e: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x165 <language_basics_minimal::main()+0x165>
165: 48 89 84 24 90 01 00 00 movq %rax, 400(%rsp)
16d: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x174 <language_basics_minimal::main()+0x174>
174: 48 89 84 24 70 01 00 00 movq %rax, 368(%rsp)
17c: 48 b8 00 00 00 00 00 00 00 20 movabsq $2305843009213693952, %rax # imm = 0x2000000000000000
186: 48 89 84 24 80 01 00 00 movq %rax, 384(%rsp)
18e: 48 c7 84 24 a0 01 00 00 05 00 00 00 movq $5, 416(%rsp)
19a: 48 8d 84 24 98 01 00 00 leaq 408(%rsp), %rax
1a2: 48 89 84 24 a8 00 00 00 movq %rax, 168(%rsp)
1aa: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x1b1 <language_basics_minimal::main()+0x1b1>
1b1: 48 89 84 24 b0 01 00 00 movq %rax, 432(%rsp)
1b9: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x1c0 <language_basics_minimal::main()+0x1c0>
1c0: 48 89 84 24 b8 01 00 00 movq %rax, 440(%rsp)
1c8: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x1cf <language_basics_minimal::main()+0x1cf>
1cf: 48 89 84 24 98 01 00 00 movq %rax, 408(%rsp)
1d7: 48 8d 84 24 98 01 00 00 leaq 408(%rsp), %rax
1df: 48 83 c0 10 addq $16, %rax
1e3: 48 89 84 24 b0 00 00 00 movq %rax, 176(%rsp)
1eb: 48 b8 00 00 00 00 00 00 00 20 movabsq $2305843009213693952, %rax # imm = 0x2000000000000000
1f5: 48 89 84 24 a8 01 00 00 movq %rax, 424(%rsp)
1fd: 48 c7 84 24 c8 01 00 00 01 00 00 00 movq $1, 456(%rsp)
209: 48 8d 84 24 c0 01 00 00 leaq 448(%rsp), %rax
211: 48 89 84 24 b8 00 00 00 movq %rax, 184(%rsp)
219: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x220 <language_basics_minimal::main()+0x220>
220: 48 89 84 24 d8 01 00 00 movq %rax, 472(%rsp)
228: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x22f <language_basics_minimal::main()+0x22f>
22f: 48 89 84 24 e0 01 00 00 movq %rax, 480(%rsp)
237: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x23e <language_basics_minimal::main()+0x23e>
23e: 48 89 84 24 c0 01 00 00 movq %rax, 448(%rsp)
246: 48 8d 84 24 c0 01 00 00 leaq 448(%rsp), %rax
24e: 48 83 c0 10 addq $16, %rax
252: 48 89 84 24 c0 00 00 00 movq %rax, 192(%rsp)
25a: 48 b8 00 00 00 00 00 00 00 20 movabsq $2305843009213693952, %rax # imm = 0x2000000000000000
264: 48 89 84 24 d0 01 00 00 movq %rax, 464(%rsp)
26c: 48 c7 84 24 f0 01 00 00 01 00 00 00 movq $1, 496(%rsp)
278: 48 8d 84 24 e8 01 00 00 leaq 488(%rsp), %rax
280: 48 89 84 24 c8 00 00 00 movq %rax, 200(%rsp)
288: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x28f <language_basics_minimal::main()+0x28f>
28f: 48 89 84 24 00 02 00 00 movq %rax, 512(%rsp)
297: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x29e <language_basics_minimal::main()+0x29e>
29e: 48 89 84 24 08 02 00 00 movq %rax, 520(%rsp)
2a6: 48 8d 05 00 00 00 00 leaq (%rip), %rax # 0x2ad <language_basics_minimal::main()+0x2ad>
2ad: 48 89 84 24 e8 01 00 00 movq %rax, 488(%rsp)
2b5: 48 8d 84 24 e8 01 00 00 leaq 488(%rsp), %rax
2bd: 48 83 c0 10 addq $16, %rax
2c1: 48 89 84 24 d0 00 00 00 movq %rax, 208(%rsp)
2c9: 48 b8 00 00 00 00 00 00 00 20 movabsq $2305843009213693952, %rax # imm = 0x2000000000000000
2d3: 48 89 84 24 f8 01 00 00 movq %rax, 504(%rsp)
2db: 90 nop
2dc: 48 8b 84 24 00 01 00 00 movq 256(%rsp), %rax
2e4: 48 89 84 24 d8 00 00 00 movq %rax, 216(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
2ec: 48 8d bc 24 f8 00 00 00 leaq 248(%rsp), %rdi
2f4: e8 00 00 00 00 callq 0x2f9 <language_basics_minimal::main()+0x2f9>
2f9: 48 8b 94 24 d8 00 00 00 movq 216(%rsp), %rdx
301: 48 89 94 24 10 02 00 00 movq %rdx, 528(%rsp)
309: 48 8b b4 24 e8 00 00 00 movq 232(%rsp), %rsi
311: 48 8b 8c 24 f0 00 00 00 movq 240(%rsp), %rcx
319: 48 8d 3d 00 00 00 00 leaq (%rip), %rdi # 0x320 <language_basics_minimal::main()+0x320>
320: 48 89 e0 movq %rsp, %rax
323: 48 89 84 24 e0 00 00 00 movq %rax, 224(%rsp)
32b: 48 89 78 20 movq %rdi, 32(%rax)
32f: 48 8d 3d 00 00 00 00 leaq (%rip), %rdi # 0x336 <language_basics_minimal::main()+0x336>
336: 48 89 78 10 movq %rdi, 16(%rax)
33a: 48 89 50 08 movq %rdx, 8(%rax)
33e: 48 8d 94 24 e8 01 00 00 leaq 488(%rsp), %rdx
346: 48 89 10 movq %rdx, (%rax)
349: 48 c7 40 38 01 00 00 00 movq $1, 56(%rax)
351: c7 40 30 00 00 00 00 movl $0, 48(%rax)
358: 48 c7 40 28 01 00 00 00 movq $1, 40(%rax)
360: 48 c7 40 18 01 00 00 00 movq $1, 24(%rax)
368: 48 8d bc 24 70 01 00 00 leaq 368(%rsp), %rdi
370: 48 8d 94 24 98 01 00 00 leaq 408(%rsp), %rdx
378: 4c 8d 84 24 c0 01 00 00 leaq 448(%rsp), %r8
380: 4c 8d 8c 24 48 01 00 00 leaq 328(%rsp), %r9
388: e8 00 00 00 00 callq 0x38d <language_basics_minimal::main()+0x38d>
38d: 48 b8 00 00 00 00 00 00 00 40 movabsq $4611686018427387904, %rax # imm = 0x4000000000000000
397: 48 23 84 24 80 01 00 00 andq 384(%rsp), %rax
39f: 48 83 f8 00 cmpq $0, %rax
3a3: 0f 84 b2 00 00 00 je 0x45b <language_basics_minimal::main()+0x45b>
3a9: 48 8b 84 24 a0 00 00 00 movq 160(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
3b1: 48 8b 00 movq (%rax), %rax
3b4: 90 nop
3b5: 48 89 84 24 d8 02 00 00 movq %rax, 728(%rsp)
3bd: 48 c7 84 24 e0 02 00 00 08 00 00 00 movq $8, 736(%rsp)
3c9: 48 83 c0 f8 addq $-8, %rax
3cd: 48 89 84 24 88 00 00 00 movq %rax, 136(%rsp)
3d5: 48 89 84 24 18 02 00 00 movq %rax, 536(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
3dd: 48 89 84 24 20 02 00 00 movq %rax, 544(%rsp)
3e5: 90 nop
3e6: 48 8b 8c 24 88 00 00 00 movq 136(%rsp), %rcx
3ee: 48 c7 84 24 e8 02 00 00 01 00 00 00 movq $1, 744(%rsp)
3fa: 48 89 8c 24 28 02 00 00 movq %rcx, 552(%rsp)
402: 48 89 8c 24 30 02 00 00 movq %rcx, 560(%rsp)
40a: 48 c7 c0 ff ff ff ff movq $-1, %rax
411: f0 lock
412: 48 0f c1 01 xaddq %rax, (%rcx)
416: 48 89 84 24 f0 02 00 00 movq %rax, 752(%rsp)
41e: 48 89 84 24 80 00 00 00 movq %rax, 128(%rsp)
426: 48 8b 84 24 80 00 00 00 movq 128(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
42e: 48 83 f8 01 cmpq $1, %rax
432: 75 23 jne 0x457 <language_basics_minimal::main()+0x457>
434: eb 00 jmp 0x436 <language_basics_minimal::main()+0x436>
436: 48 8b bc 24 88 00 00 00 movq 136(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
43e: 90 nop
43f: 48 89 bc 24 f8 02 00 00 movq %rdi, 760(%rsp)
447: 90 nop
448: 48 89 bc 24 00 03 00 00 movq %rdi, 768(%rsp)
450: e8 00 00 00 00 callq 0x455 <language_basics_minimal::main()+0x455>
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
455: eb 02 jmp 0x459 <language_basics_minimal::main()+0x459>
457: eb 00 jmp 0x459 <language_basics_minimal::main()+0x459>
459: eb 02 jmp 0x45d <language_basics_minimal::main()+0x45d>
45b: eb 00 jmp 0x45d <language_basics_minimal::main()+0x45d>
45d: 48 8b 8c 24 b0 00 00 00 movq 176(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
465: 48 b8 00 00 00 00 00 00 00 40 movabsq $4611686018427387904, %rax # imm = 0x4000000000000000
46f: 48 23 01 andq (%rcx), %rax
472: 48 83 f8 00 cmpq $0, %rax
476: 0f 84 a3 00 00 00 je 0x51f <language_basics_minimal::main()+0x51f>
47c: 48 8b 84 24 a8 00 00 00 movq 168(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
484: 48 8b 00 movq (%rax), %rax
487: 90 nop
488: 48 89 84 24 d8 02 00 00 movq %rax, 728(%rsp)
490: 48 c7 84 24 e0 02 00 00 08 00 00 00 movq $8, 736(%rsp)
49c: 48 83 c0 f8 addq $-8, %rax
4a0: 48 89 44 24 78 movq %rax, 120(%rsp)
4a5: 48 89 84 24 38 02 00 00 movq %rax, 568(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
4ad: 48 89 84 24 40 02 00 00 movq %rax, 576(%rsp)
4b5: 90 nop
4b6: 48 8b 4c 24 78 movq 120(%rsp), %rcx
4bb: 48 c7 84 24 e8 02 00 00 01 00 00 00 movq $1, 744(%rsp)
4c7: 48 89 8c 24 48 02 00 00 movq %rcx, 584(%rsp)
4cf: 48 89 8c 24 50 02 00 00 movq %rcx, 592(%rsp)
4d7: 48 c7 c0 ff ff ff ff movq $-1, %rax
4de: f0 lock
4df: 48 0f c1 01 xaddq %rax, (%rcx)
4e3: 48 89 84 24 f0 02 00 00 movq %rax, 752(%rsp)
4eb: 48 89 44 24 70 movq %rax, 112(%rsp)
4f0: 48 8b 44 24 70 movq 112(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
4f5: 48 83 f8 01 cmpq $1, %rax
4f9: 75 20 jne 0x51b <language_basics_minimal::main()+0x51b>
4fb: eb 00 jmp 0x4fd <language_basics_minimal::main()+0x4fd>
4fd: 48 8b 7c 24 78 movq 120(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
502: 90 nop
503: 48 89 bc 24 f8 02 00 00 movq %rdi, 760(%rsp)
50b: 90 nop
50c: 48 89 bc 24 00 03 00 00 movq %rdi, 768(%rsp)
514: e8 00 00 00 00 callq 0x519 <language_basics_minimal::main()+0x519>
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
519: eb 02 jmp 0x51d <language_basics_minimal::main()+0x51d>
51b: eb 00 jmp 0x51d <language_basics_minimal::main()+0x51d>
51d: eb 02 jmp 0x521 <language_basics_minimal::main()+0x521>
51f: eb 00 jmp 0x521 <language_basics_minimal::main()+0x521>
521: 48 8b 8c 24 c0 00 00 00 movq 192(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
529: 48 b8 00 00 00 00 00 00 00 40 movabsq $4611686018427387904, %rax # imm = 0x4000000000000000
533: 48 23 01 andq (%rcx), %rax
536: 48 83 f8 00 cmpq $0, %rax
53a: 0f 84 a3 00 00 00 je 0x5e3 <language_basics_minimal::main()+0x5e3>
540: 48 8b 84 24 b8 00 00 00 movq 184(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
548: 48 8b 00 movq (%rax), %rax
54b: 90 nop
54c: 48 89 84 24 d8 02 00 00 movq %rax, 728(%rsp)
554: 48 c7 84 24 e0 02 00 00 08 00 00 00 movq $8, 736(%rsp)
560: 48 83 c0 f8 addq $-8, %rax
564: 48 89 44 24 68 movq %rax, 104(%rsp)
569: 48 89 84 24 58 02 00 00 movq %rax, 600(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
571: 48 89 84 24 60 02 00 00 movq %rax, 608(%rsp)
579: 90 nop
57a: 48 8b 4c 24 68 movq 104(%rsp), %rcx
57f: 48 c7 84 24 e8 02 00 00 01 00 00 00 movq $1, 744(%rsp)
58b: 48 89 8c 24 68 02 00 00 movq %rcx, 616(%rsp)
593: 48 89 8c 24 70 02 00 00 movq %rcx, 624(%rsp)
59b: 48 c7 c0 ff ff ff ff movq $-1, %rax
5a2: f0 lock
5a3: 48 0f c1 01 xaddq %rax, (%rcx)
5a7: 48 89 84 24 f0 02 00 00 movq %rax, 752(%rsp)
5af: 48 89 44 24 60 movq %rax, 96(%rsp)
5b4: 48 8b 44 24 60 movq 96(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
5b9: 48 83 f8 01 cmpq $1, %rax
5bd: 75 20 jne 0x5df <language_basics_minimal::main()+0x5df>
5bf: eb 00 jmp 0x5c1 <language_basics_minimal::main()+0x5c1>
5c1: 48 8b 7c 24 68 movq 104(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
5c6: 90 nop
5c7: 48 89 bc 24 f8 02 00 00 movq %rdi, 760(%rsp)
5cf: 90 nop
5d0: 48 89 bc 24 00 03 00 00 movq %rdi, 768(%rsp)
5d8: e8 00 00 00 00 callq 0x5dd <language_basics_minimal::main()+0x5dd>
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
5dd: eb 02 jmp 0x5e1 <language_basics_minimal::main()+0x5e1>
5df: eb 00 jmp 0x5e1 <language_basics_minimal::main()+0x5e1>
5e1: eb 02 jmp 0x5e5 <language_basics_minimal::main()+0x5e5>
5e3: eb 00 jmp 0x5e5 <language_basics_minimal::main()+0x5e5>
5e5: 48 8b 8c 24 98 00 00 00 movq 152(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
5ed: 48 b8 00 00 00 00 00 00 00 40 movabsq $4611686018427387904, %rax # imm = 0x4000000000000000
5f7: 48 23 01 andq (%rcx), %rax
5fa: 48 83 f8 00 cmpq $0, %rax
5fe: 0f 84 a3 00 00 00 je 0x6a7 <language_basics_minimal::main()+0x6a7>
604: 48 8b 84 24 90 00 00 00 movq 144(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
60c: 48 8b 00 movq (%rax), %rax
60f: 90 nop
610: 48 89 84 24 d8 02 00 00 movq %rax, 728(%rsp)
618: 48 c7 84 24 e0 02 00 00 08 00 00 00 movq $8, 736(%rsp)
624: 48 83 c0 f8 addq $-8, %rax
628: 48 89 44 24 58 movq %rax, 88(%rsp)
62d: 48 89 84 24 78 02 00 00 movq %rax, 632(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
635: 48 89 84 24 80 02 00 00 movq %rax, 640(%rsp)
63d: 90 nop
63e: 48 8b 4c 24 58 movq 88(%rsp), %rcx
643: 48 c7 84 24 e8 02 00 00 01 00 00 00 movq $1, 744(%rsp)
64f: 48 89 8c 24 88 02 00 00 movq %rcx, 648(%rsp)
657: 48 89 8c 24 90 02 00 00 movq %rcx, 656(%rsp)
65f: 48 c7 c0 ff ff ff ff movq $-1, %rax
666: f0 lock
667: 48 0f c1 01 xaddq %rax, (%rcx)
66b: 48 89 84 24 f0 02 00 00 movq %rax, 752(%rsp)
673: 48 89 44 24 50 movq %rax, 80(%rsp)
678: 48 8b 44 24 50 movq 80(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
67d: 48 83 f8 01 cmpq $1, %rax
681: 75 20 jne 0x6a3 <language_basics_minimal::main()+0x6a3>
683: eb 00 jmp 0x685 <language_basics_minimal::main()+0x685>
685: 48 8b 7c 24 58 movq 88(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
68a: 90 nop
68b: 48 89 bc 24 f8 02 00 00 movq %rdi, 760(%rsp)
693: 90 nop
694: 48 89 bc 24 00 03 00 00 movq %rdi, 768(%rsp)
69c: e8 00 00 00 00 callq 0x6a1 <language_basics_minimal::main()+0x6a1>
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
6a1: eb 02 jmp 0x6a5 <language_basics_minimal::main()+0x6a5>
6a3: eb 00 jmp 0x6a5 <language_basics_minimal::main()+0x6a5>
6a5: eb 02 jmp 0x6a9 <language_basics_minimal::main()+0x6a9>
6a7: eb 00 jmp 0x6a9 <language_basics_minimal::main()+0x6a9>
6a9: 48 8b 8c 24 d0 00 00 00 movq 208(%rsp), %rcx
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
6b1: 48 b8 00 00 00 00 00 00 00 40 movabsq $4611686018427387904, %rax # imm = 0x4000000000000000
6bb: 48 23 01 andq (%rcx), %rax
6be: 48 83 f8 00 cmpq $0, %rax
6c2: 0f 84 a3 00 00 00 je 0x76b <language_basics_minimal::main()+0x76b>
6c8: 48 8b 84 24 c8 00 00 00 movq 200(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
6d0: 48 8b 00 movq (%rax), %rax
6d3: 90 nop
6d4: 48 89 84 24 d8 02 00 00 movq %rax, 728(%rsp)
6dc: 48 c7 84 24 e0 02 00 00 08 00 00 00 movq $8, 736(%rsp)
6e8: 48 83 c0 f8 addq $-8, %rax
6ec: 48 89 44 24 48 movq %rax, 72(%rsp)
6f1: 48 89 84 24 98 02 00 00 movq %rax, 664(%rsp)
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
6f9: 48 89 84 24 a0 02 00 00 movq %rax, 672(%rsp)
701: 90 nop
702: 48 8b 4c 24 48 movq 72(%rsp), %rcx
707: 48 c7 84 24 e8 02 00 00 01 00 00 00 movq $1, 744(%rsp)
713: 48 89 8c 24 a8 02 00 00 movq %rcx, 680(%rsp)
71b: 48 89 8c 24 b0 02 00 00 movq %rcx, 688(%rsp)
723: 48 c7 c0 ff ff ff ff movq $-1, %rax
72a: f0 lock
72b: 48 0f c1 01 xaddq %rax, (%rcx)
72f: 48 89 84 24 f0 02 00 00 movq %rax, 752(%rsp)
737: 48 89 44 24 40 movq %rax, 64(%rsp)
73c: 48 8b 44 24 40 movq 64(%rsp), %rax
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
741: 48 83 f8 01 cmpq $1, %rax
745: 75 20 jne 0x767 <language_basics_minimal::main()+0x767>
747: eb 00 jmp 0x749 <language_basics_minimal::main()+0x749>
749: 48 8b 7c 24 48 movq 72(%rsp), %rdi
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
74e: 90 nop
74f: 48 89 bc 24 f8 02 00 00 movq %rdi, 760(%rsp)
757: 90 nop
758: 48 89 bc 24 00 03 00 00 movq %rdi, 768(%rsp)
760: e8 00 00 00 00 callq 0x765 <language_basics_minimal::main()+0x765>
; print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs))
765: eb 02 jmp 0x769 <language_basics_minimal::main()+0x769>
767: eb 00 jmp 0x769 <language_basics_minimal::main()+0x769>
769: eb 02 jmp 0x76d <language_basics_minimal::main()+0x76d>
76b: eb 00 jmp 0x76d <language_basics_minimal::main()+0x76d>
; def main():
76d: 48 81 c4 08 03 00 00 addq $776, %rsp # imm = 0x308
774: c3 retq
775: 66 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:(%rax,%rax)
リスト-2: language_basics_minimal.asm
7.2. リスト-2 を段階的に読む
全体を段階的に解説します。オフセットや命令列は、手元の objdump 結果と Mojo / LLVM の版によってわずかに変わり得ますが、リスト-2 のダンプを前提に読み進めてください。ニモニックは5 章 と同様に AT&T 記法です。
7.2.1. 関数プロローグ
0: subq $776, %rsp
スタックに 776 バイトを確保します。5 章 の 136 バイトより大きいのは、複数の変数・文字列オブジェクト・引数用テーブルを すべてスタック上に載せるためです。
7.2.2. ① 変数の初期化(コンパイル時定数の最適化)
; var n: Int = 42
7: movq $42, 232(%rsp)
; var doubled = n * 2
13: movq $84, 240(%rsp)
注目点は、n * 2 の計算が コンパイル時に完了 しています。42 * 2 = 84 がそのまま即値として埋め込まれており、実行時に乗算命令は一切発生しません。Mojo コンパイラ(LLVM)の 定数畳み込み最適化です。
7.2.3. ② List[Int] = [1, 2, 3] の構築
; 要素をスタックに配置
1f: movq $1, 272(%rsp)
2b: movq $2, 280(%rsp)
37: movq $3, 288(%rsp)
まず 3 つの整数をスタック上に並べます。
; 各要素へのポインタのテーブル
43: leaq 272(%rsp), %rax
4b: movq %rax, 296(%rsp) ; &xs[0]
53: leaq 280(%rsp), %rax
5b: movq %rax, 304(%rsp) ; &xs[1]
63: leaq 288(%rsp), %rax
6b: movq %rax, 312(%rsp) ; &xs[2]
要素アドレスのテーブルを組み立てます。Mojo の List は、内部で 要素を指すポインタ列を持つ形としてコードが生成されます。
73: movl $3, %esi ; 要素数 = 3
78: leaq 296(%rsp), %rdi ; ポインタテーブルの先頭
; メタデータを 2 箇所にコピー(後で説明)
81: movq %rdi, 696(%rsp)
89: movq $3, 704(%rsp)
96: movq %rdi, 712(%rsp)
9e: movq $3, 720(%rsp)
aa: leaq 248(%rsp), %rdx ; List 本体の格納先
b2: callq ... ; List 構築関数の呼び出し
7.2.4. ③ List 構築後の後処理
b7: leaq 327(%rsp), %rdi
bf: callq ... ; 内部初期化(アロケータ等)
List の内部状態を整える 追加の呼び出しです。
7.2.5. ④ String("count") の構築
5 章 の Hello, Mojo と同型です。
文字列オブジェクトは データポインタ・長さ・タグビット・関数ポインタ 2 本 というワード列でスタック上に現れます。
"count" 以降の "n="・" sum=" なども、同じレイアウトで繰り返し構築されます。
7.2.6. ⑤ print() の引数構築(もっとも複雑な部分)
print(String("n="), n, String(" sum="), doubled, String(" "), label, String("="), len(xs)) の 8 引数のために、広いアドレス範囲で準備が続きます。
133〜2db 付近では、次の文字列リテラルが ほぼ同じ手順で構築されます。
アドレス範囲(目安) |
構築している文字列 |
長さ |
|---|---|---|
|
|
2 |
|
|
5 |
|
|
1 |
|
|
1 |
各オブジェクトは、第④と同様のレイアウト(データポインタ・長さ・タグ・関数ポインタ 2 本)で並びます。
; len(xs) の取得
2dc: movq 256(%rsp), %rax
2e4: movq %rax, 216(%rsp) ; len(xs) の結果を保存
ここでは、直前の処理で取得した len(xs) の結果がスタック上の 256(%rsp) に格納されており、それを別の場所へコピーしています。
7.2.7. ⑥ print() 本体の呼び出し
x86-64 のレジスタ引数(rdi〜r9 の 6 本)だけでは 8 引数を渡しきれないため、スタック上に引数テーブルを組み立ててから呼び出す経路が現れます。
368: leaq 368(%rsp), %rdi ; String("n=")
370: leaq 408(%rsp), %rdx ; String(" sum=")
378: leaq 448(%rsp), %r8 ; String(" ")
380: leaq 328(%rsp), %r9 ; label = String("count")
388: callq ... ; print() 本体
7.2.8. ⑦ エラーチェックとデストラクタ処理(5 回繰り返し)
print() のあと、スタック上に作った文字列オブジェクトごとに、第1部第2章と同型の 後片付けパターンが繰り返されます(リスト上は次のような区間に現れます)。
38d〜45b…String("n=")45d〜51f…String(" sum=")521〜5e3…String(" ")5e5〜6a7…String("count")6a9〜76b…String("=")
各ブロックは、おおむね次の骨格です。
; ① エラーフラグチェック
movabsq $0x4000000000000000, %rax
andq (フラグ保存場所), %rax
cmpq $0, %rax
je → エラーなし → スキップ
; ② エラーあり → refcount をアトミックにデクリメント
movq $-1, %rax
lock xaddq %rax, (%rcx)
; ③ 旧 refcount が 1 か(最後の参照か)
cmpq $1, %rax
jne → 他に参照あり → スキップ
; ④ 最後の参照 → 解放/デストラクタ
movq ..., %rdi
callq ...
; ⑤ ランディングパッド(4 つの jmp)
; eb 02 / eb 00 / eb 02 / eb 00
同じ形が 5 回分 繰り返されるため、コードが非常に長くなります。
7.2.9. 関数エピローグ
76d: addq $776, %rsp ; スタック解放
774: retq ; 呼び出し元へ戻る
775: nopw %cs:(%rax,%rax) ; アライメント用パディング
末尾の nopw は、次の関数の先頭を 16 バイト境界に合わせるためのパディングです。今回は 11 バイトと長くなっていますが、これは必要なパディング量が多かったためです。
7.2.10. 全体の流れ(まとめ)
スタック確保(776 バイト)
↓
n = 42, doubled = 84 を配置(定数はコンパイル時に畳み込み済み)
↓
List[Int]{1,2,3} をスタック上に構築
↓
String("count") をスタック上に構築
↓
print 用の文字列リテラルを構築("n=", " sum=", " ", "=")
↓
len(xs) を取得
↓
引数テーブルを組み立てて print() 呼び出し
【後片付け × 5 回】各 String について:エラーチェック → refcount デクリメント → 必要なら解放
↓
スタック解放・return
5 章 の Hello, Mojo と比べると、同じ「文字列を組み立てる → 後片付けする」パターンが、引数の数だけ機械的に繰り返される点が大きな違いです。Mojo が 文字列リテラルを含む引数ごとに独立したオブジェクトとして扱い、それぞれ参照カウントで管理する様子が、ダンプから追いやすくなっています。