ポインタを使用するプログラムです。
C
1 1 #include<stdio.h> 2 2 #include<ctype.h> 3 3 4 4 char *test(char *buf){ 5 5 char *p; 6 6 int c; 7 7 p = buf; 8 8 9 9 while((c = *p) != 0){ 10 10 if(islower(c)) 11 11 *p = (char)toupper(c); 12 12 p++; 13 13 } 14 14 return buf; 15 15 } 16 16 17 17 int main(){ 18 18 char s[] = "you will make me happy\n"; 19 19 printf("%s\n", test(s)); 20 20 21 21 return 0; 22 22 } 23 23
コンパイルしたものを書きます。
.file "pointer_arg.c" .text .globl test .type test, @function test: .LFB2: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $32, %rsp movq %rdi, -24(%rbp) movq -24(%rbp), %rax movq %rax, -8(%rbp) jmp .L2 .L4: call __ctype_b_loc@PLT movq (%rax), %rax movl -12(%rbp), %edx movslq %edx, %rdx addq %rdx, %rdx addq %rdx, %rax movzwl (%rax), %eax movzwl %ax, %eax andl $512, %eax testl %eax, %eax je .L3 movl -12(%rbp), %eax movl %eax, %edi call toupper@PLT movl %eax, %edx movq -8(%rbp), %rax movb %dl, (%rax) .L3: addq $1, -8(%rbp) .L2: movq -8(%rbp), %rax movzbl (%rax), %eax movsbl %al, %eax movl %eax, -12(%rbp) cmpl $0, -12(%rbp) jne .L4 movq -24(%rbp), %rax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2: .size test, .-test .globl main .type main, @function main: .LFB3: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $32, %rsp movabsq $7812735413947559801, %rax movq %rax, -32(%rbp) movabsq $7308533390257515808, %rax movq %rax, -24(%rbp) movabsq $2948273595836448, %rax movq %rax, -16(%rbp) leaq -32(%rbp), %rax movq %rax, %rdi call test movq %rax, %rdi call puts@PLT movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE3: .size main, .-main .ident "GCC: (Debian 6.3.0-18) 6.3.0 20170516" .section .note.GNU-stack,"",@progbits
test()に入ったあとなんですが、、、、
-24(%rbp) = buf
-8(%rbp) = p
-12(%rbp) = c
となっています。(間違っていたらご指摘ください。)
call __ctype_b_loc@PLT movq (%rax), %rax movl -12(%rbp), %edx movslq %edx, %rdx addq %rdx, %rdx addq %rdx, %rax movzwl (%rax), %eax movzwl %ax, %eax andl $512, %eax testl %eax, %eax
読めない箇所はここです。
一体何をやっているんでしょうか?
足し算なんてCのプログラム内にはインクリメント以外出てきていません。
なぜ、こんなにadd命令が多いのでしょう?(512なんて知りません。)
__ctype_b_loc@PLTのパラメータはその直前のeaxレジスタ経由でしょうか?
rdiはインクリメントによって変化していないので、eax以外は考えられませんが・・・
PLT経由の関数の呼び出しはシステムコールの時とは違ってパラメータ用のレジスタは決まっていないということですかね・・・・
この関数はislower()に相当するかと思います。
movq (%rax), %rax
わざわざカッコを付けている理由はなんでしょうか?
() ・・・括弧内のレジスタにアドレスが入っていたら、()はC言語で言う所の間接演算子(*)と同じ効果という理解で正しいでしょうか?
この行はなぜ必要なんですか?
testl %eax, %eax
同じレジスタのANDを取ってどうするんでしょうか??
意味がよく分かりません。
どなたか教えてください。
Linux 64bit Debianです。
[追記]
私の本のなかでは、islower()の呼び出しは以下のようになっています。
movl -12(%rbp), %eax
movl %eax, %ecx
movq __imp_islower(%rip), %rax
call *(%rax)
call命令の際のレジスタについているアスタリスクはなんのために付いているのでしょうか?
こちらの方が分かりやすいですね。
[追記2]
最適化-O2でやったコードを載せます。
.file "pointer_arg.c" .text .p2align 4,,15 .globl test .type test, @function test: .LFB15: .cfi_startproc pushq %r13 .cfi_def_cfa_offset 16 .cfi_offset 13, -16 pushq %r12 .cfi_def_cfa_offset 24 .cfi_offset 12, -24 movq %rdi, %r13 pushq %rbp .cfi_def_cfa_offset 32 .cfi_offset 6, -32 pushq %rbx .cfi_def_cfa_offset 40 .cfi_offset 3, -40 subq $8, %rsp .cfi_def_cfa_offset 48 movsbq (%rdi), %rbx testb %bl, %bl je .L10 call __ctype_b_loc@PLT movq %r13, %rbp movq %rax, %r12 .p2align 4,,10 .p2align 3 .L4: movq (%r12), %rax testb $2, 1(%rax,%rbx,2) je .L3 call __ctype_toupper_loc@PLT movq (%rax), %rax movl (%rax,%rbx,4), %eax movb %al, 0(%rbp) .L3: addq $1, %rbp movsbq 0(%rbp), %rbx testb %bl, %bl jne .L4 .L10: addq $8, %rsp .cfi_def_cfa_offset 40 movq %r13, %rax popq %rbx .cfi_def_cfa_offset 32 popq %rbp .cfi_def_cfa_offset 24 popq %r12 .cfi_def_cfa_offset 16 popq %r13 .cfi_def_cfa_offset 8 ret .cfi_endproc .LFE15: .size test, .-test .section .text.startup,"ax",@progbits .p2align 4,,15 .globl main .type main, @function main: .LFB16: .cfi_startproc subq $40, %rsp .cfi_def_cfa_offset 48 movabsq $7812735413947559801, %rax movq %rax, (%rsp) movabsq $7308533390257515808, %rax movq %rsp, %rdi movq %rax, 8(%rsp) movabsq $2948273595836448, %rax movq %rax, 16(%rsp) call test movq %rax, %rdi call puts@PLT xorl %eax, %eax addq $40, %rsp .cfi_def_cfa_offset 8 ret .cfi_endproc .LFE16: .size main, .-main .ident "GCC: (Debian 6.3.0-18) 6.3.0 20170516" .section .note.GNU-stack,"",@progbits
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/07/11 00:57
2017/07/11 01:16
2017/07/11 01:45 編集
2017/07/11 01:58
2017/07/11 03:49 編集
2017/07/11 02:24
2017/07/11 02:32
2017/07/11 02:56
2017/07/11 03:00 編集
2017/07/11 03:49 編集
2017/07/11 03:08
2017/07/11 03:50 編集
2017/07/11 03:31
2017/07/11 03:41
2017/07/11 03:51 編集
2017/07/11 03:54 編集
2017/07/11 03:56
2017/07/11 03:58
2017/07/11 04:03 編集
2017/07/11 04:06
2017/07/11 04:59
2017/07/11 05:05
2017/07/11 05:14
2017/07/11 05:20
2017/07/11 05:21 編集
2017/07/11 05:30
2017/07/11 05:45 編集
2017/07/11 05:44