这是一个简单的C程序:

#include <stdio.h>

int main(){
    getchar();
    return 0;
}

这是gcc命令“gcc prog.c-S”的输出:
    .file   "prog.c"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    call getchar
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Debian 4.8.2-1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

在“main”中有一个对“getchar”函数的调用。可以看到这个函数的代码(当然是在汇编中)吗?
特别是,我会理解“getchar()”后面的键盘中断机制。

最佳答案

如果您想要一个ASM输出,您可以简单地要求gdb加载您的C程序并为您反汇编getchar
在我的系统中,这样会得到如下结果:

$ gdb /bin/cat
(gdb) run
Starting program: /bin/cat
^C
Program received signal SIGINT, Interrupt.
0x00007ffff7b0c5c0 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:81
(gdb) disas getchar
Dump of assembler code for function getchar:
   0x00007ffff7aa4b30 <+0>:     push   %rbx
   0x00007ffff7aa4b31 <+1>:     mov    0x332be0(%rip),%rbx        # 0x7ffff7dd7718 <stdin>
   0x00007ffff7aa4b38 <+8>:     mov    (%rbx),%eax
   0x00007ffff7aa4b3a <+10>:    mov    %rbx,%rdi
   0x00007ffff7aa4b3d <+13>:    and    $0x8000,%eax
   0x00007ffff7aa4b42 <+18>:    jne    0x7ffff7aa4b9e <getchar+110>
   0x00007ffff7aa4b44 <+20>:    mov    0x88(%rbx),%rdx
   0x00007ffff7aa4b4b <+27>:    mov    %fs:0x10,%r8
   0x00007ffff7aa4b54 <+36>:    cmp    0x8(%rdx),%r8
   0x00007ffff7aa4b58 <+40>:    je     0x7ffff7aa4bf0 <getchar+192>
   0x00007ffff7aa4b5e <+46>:    mov    $0x1,%esi
   0x00007ffff7aa4b63 <+51>:    cmpl   $0x0,0x336c6a(%rip)        # 0x7ffff7ddb7d4 <__libc_multiple_threads>
   0x00007ffff7aa4b6a <+58>:    je     0x7ffff7aa4b78 <getchar+72>
   0x00007ffff7aa4b6c <+60>:    lock cmpxchg %esi,(%rdx)
   0x00007ffff7aa4b70 <+64>:    jne    0x7ffff7aa4c41 <_L_lock_30>
   0x00007ffff7aa4b76 <+70>:    jmp    0x7ffff7aa4b81 <getchar+81>
   0x00007ffff7aa4b78 <+72>:    cmpxchg %esi,(%rdx)
   0x00007ffff7aa4b7b <+75>:    jne    0x7ffff7aa4c41 <_L_lock_30>
   0x00007ffff7aa4b81 <+81>:    mov    0x88(%rbx),%rax
   0x00007ffff7aa4b88 <+88>:    mov    0x88(%rbx),%rdx
   0x00007ffff7aa4b8f <+95>:    mov    0x332b82(%rip),%rdi        # 0x7ffff7dd7718 <stdin>
   0x00007ffff7aa4b96 <+102>:   mov    %r8,0x8(%rax)
   0x00007ffff7aa4b9a <+106>:   addl   $0x1,0x4(%rdx)
   0x00007ffff7aa4b9e <+110>:   mov    0x8(%rdi),%rax
   0x00007ffff7aa4ba2 <+114>:   cmp    0x10(%rdi),%rax
   0x00007ffff7aa4ba6 <+118>:   jae    0x7ffff7aa4bf5 <getchar+197>
   0x00007ffff7aa4ba8 <+120>:   lea    0x1(%rax),%rdx
   0x00007ffff7aa4bac <+124>:   mov    %rdx,0x8(%rdi)
   0x00007ffff7aa4bb0 <+128>:   movzbl (%rax),%edx
   0x00007ffff7aa4bb3 <+131>:   testl  $0x8000,(%rbx)
   0x00007ffff7aa4bb9 <+137>:   jne    0x7ffff7aa4be4 <getchar+180>
   0x00007ffff7aa4bbb <+139>:   mov    0x88(%rbx),%rsi
   0x00007ffff7aa4bc2 <+146>:   subl   $0x1,0x4(%rsi)
   0x00007ffff7aa4bc6 <+150>:   jne    0x7ffff7aa4be4 <getchar+180>
   0x00007ffff7aa4bc8 <+152>:   movq   $0x0,0x8(%rsi)
   0x00007ffff7aa4bd0 <+160>:   cmpl   $0x0,0x336bfd(%rip)        # 0x7ffff7ddb7d4 <__libc_multiple_threads>
   0x00007ffff7aa4bd7 <+167>:   je     0x7ffff7aa4be0 <getchar+176>
   0x00007ffff7aa4bd9 <+169>:   lock decl (%rsi)
   0x00007ffff7aa4bdc <+172>:   jne    0x7ffff7aa4c5c <_L_unlock_79>
   0x00007ffff7aa4bde <+174>:   jmp    0x7ffff7aa4be4 <getchar+180>
   0x00007ffff7aa4be0 <+176>:   decl   (%rsi)
   0x00007ffff7aa4be2 <+178>:   jne    0x7ffff7aa4c5c <_L_unlock_79>
   0x00007ffff7aa4be4 <+180>:   mov    %edx,%eax
   0x00007ffff7aa4be6 <+182>:   pop    %rbx
   0x00007ffff7aa4be7 <+183>:   retq
   0x00007ffff7aa4be8 <+184>:   nopl   0x0(%rax,%rax,1)
   0x00007ffff7aa4bf0 <+192>:   mov    %rbx,%rdi
   0x00007ffff7aa4bf3 <+195>:   jmp    0x7ffff7aa4b9a <getchar+106>
   0x00007ffff7aa4bf5 <+197>:   callq  0x7ffff7aa9060 <__GI___uflow>
   0x00007ffff7aa4bfa <+202>:   mov    %eax,%edx
   0x00007ffff7aa4bfc <+204>:   jmp    0x7ffff7aa4bb3 <getchar+131>
   0x00007ffff7aa4bfe <+206>:   testl  $0x8000,(%rbx)
   0x00007ffff7aa4c04 <+212>:   mov    %rax,%rsi
   0x00007ffff7aa4c07 <+215>:   jne    0x7ffff7aa4c39 <getchar+265>
   0x00007ffff7aa4c09 <+217>:   mov    0x88(%rbx),%rdx
   0x00007ffff7aa4c10 <+224>:   mov    0x4(%rdx),%eax
   0x00007ffff7aa4c13 <+227>:   lea    -0x1(%rax),%ecx
   0x00007ffff7aa4c16 <+230>:   test   %ecx,%ecx
   0x00007ffff7aa4c18 <+232>:   mov    %ecx,0x4(%rdx)
   0x00007ffff7aa4c1b <+235>:   jne    0x7ffff7aa4c39 <getchar+265>
   0x00007ffff7aa4c1d <+237>:   movq   $0x0,0x8(%rdx)
   0x00007ffff7aa4c25 <+245>:   cmpl   $0x0,0x336ba8(%rip)        # 0x7ffff7ddb7d4 <__libc_multiple_threads>
   0x00007ffff7aa4c2c <+252>:   je     0x7ffff7aa4c35 <getchar+261>
   0x00007ffff7aa4c2e <+254>:   lock decl (%rdx)
   0x00007ffff7aa4c31 <+257>:   jne    0x7ffff7aa4c77 <_L_unlock_150>
   0x00007ffff7aa4c33 <+259>:   jmp    0x7ffff7aa4c39 <getchar+265>
   0x00007ffff7aa4c35 <+261>:   decl   (%rdx)
   0x00007ffff7aa4c37 <+263>:   jne    0x7ffff7aa4c77 <_L_unlock_150>
   0x00007ffff7aa4c39 <+265>:   mov    %rsi,%rdi
   0x00007ffff7aa4c3c <+268>:   callq  0x7ffff7a54d50 <_Unwind_Resume>
End of assembler dump.

您还可以直接查看the source of your libc来了解getchar是如何实现的,但是这将给您(有时可能是神秘的)C代码。

关于c - 汇编语言中的getchar(),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28908038/

10-13 07:27