汇编语言中的getchar()

汇编语言中的getchar(),c,gcc,assembly,getchar,C,Gcc,Assembly,Getchar,这是一个简单的C程序: #include <stdio.h> int main(){ getchar(); return 0; } 在“main”中,有一个对“getchar”函数的调用。可以看到这个函数的代码(当然是汇编代码)吗 特别是,我会理解“getchar()”背后的键盘中断机制。如果您想要ASM输出,您只需请求gdb加载您的C程序并为您反汇编getchar。 这将给出如下内容(在我的系统上): $gdb/bin/cat (gdb)运行 启动程序:/bin

这是一个简单的C程序:

#include <stdio.h>

int main(){
    getchar();
    return 0;
}
在“main”中,有一个对“getchar”函数的调用。可以看到这个函数的代码(当然是汇编代码)吗


特别是,我会理解“getchar()”背后的键盘中断机制。如果您想要ASM输出,您只需请求
gdb
加载您的C程序并为您反汇编
getchar
。 这将给出如下内容(在我的系统上):

$gdb/bin/cat
(gdb)运行
启动程序:/bin/cat
^C
程序收到信号SIGINT,中断。
0x00007FF7B0C5C0位于../sysdeps/unix/syscall template.S:81处的u read_nocancel()中
(gdb)disas getchar
函数getchar的汇编程序代码转储:
0x00007FF7AA4B30:推送%rbx
0x00007ffff7aa4b31:mov 0x332be0(%rip),%rbx#0x7ffff7dd7718
0x00007FF7AA4B38:mov(%rbx),%eax
0x00007FF7AA4B3A:mov%rbx,%rdi
0x00007FF7AA4B3D:和$0x8000,%eax
0x00007FF7AA4B42:jne 0x7FF7AA4B9E
0x00007FF7AA4B44:mov 0x88(%rbx),%rdx
0x00007FF7AA4B4B4B:mov%fs:0x10,%r8
0x00007FF7AA4B54:cmp 0x8(%rdx),%r8
0x00007FF7AA4B58:je 0x7FF7AA4Bf0
0x00007FF7AA4B5E:mov$0x1,%esi
0x00007ffff7aa4b63:cmpl$0x0,0x336c6a(%rip)#0x7ffff7ddb7d4
0x00007FF7AA4B6A:je 0x7FF7AA4B78
0x00007FF7AA4B6C:锁定cmpxchg%esi,(%rdx)
0x00007FF7AA4B70:jne 0x7FF7AA4C41
0x00007FF7AA4B76:jmp 0x7FF7AA4B81
0x00007FF7AA4B78:cmpxchg%esi,(%rdx)
0x00007FF7AA4B7B:jne 0x7FF7AA4C41
0x00007FF7AA4B81:mov 0x88(%rbx),%rax
0x00007FF7AA4B88:mov 0x88(%rbx),%rdx
0x00007ffff7aa4b8f:mov 0x332b82(%rip),%rdi#0x7ffff7dd7718
0x00007FF7AA4B96:mov%r8,0x8(%rax)
0x00007FF7AA4B9A:添加$0x1,0x4(%rdx)
0x00007FF7AA4B9E:mov 0x8(%rdi),%rax
0x00007FF7AA4BA2:cmp 0x10(%rdi),%rax
0x00007FF7AA4BA6:jae 0x7ffff7aa4bf5
0x00007FF7AA4BA8:lea 0x1(%rax),%rdx
0x00007FF7AA4BAC:mov%rdx,0x8(%rdi)
0x00007FF7AA4BB0:movzbl(%rax),%edx
0x00007FF7AA4BB3:testl$0x8000,(%rbx)
0x00007FF7AA4BB9:jne 0x7FF7AA4BE4
0x00007FF7AA4BBBB:mov 0x88(%rbx),%rsi
0x00007FF7AA4BC2:subl$0x1,0x4(%rsi)
0x00007FF7AA4BC6:jne 0x7FF7AA4BE4
0x00007FF7AA4BC8:movq$0x0,0x8(%rsi)
0x00007ffff7aa4bd0:cmpl$0x0,0x336bfd(%rip)#0x7ffff7ddb7d4
0x00007FF7AA4BD7:je 0x7FF7AA4BE0
0x00007FF7AA4BD9:锁定声明(%rsi)
0x00007FF7AA4BDC:jne 0x7FF7AA4C5C
0x00007FF7AA4BDE:jmp 0x7FF7AA4BE4
0x00007FF7AA4BE0:decl(%rsi)
0x00007FF7AA4BE2:jne 0x7ffff7aa4c5c
0x00007FF7AA4BE4:mov%edx,%eax
0x00007FF7AA4BE6:弹出%rbx
0x00007FF7AA4BE7:retq
0x00007ffff7aa4be8:nopl 0x0(%rax,%rax,1)
0x00007FF7AA4BF0:mov%rbx,%rdi
0x00007FF7AA4BF3:jmp 0x7FF7AA4B9A
0x00007FF7AA4BF5:callq 0x7FF7AA9060
0x00007FF7AA4BFA:mov%eax,%edx
0x00007FF7AA4BFC:jmp 0x7FF7AA4BB3
0x00007FF7AA4BFE:testl$0x8000,(%rbx)
0x00007FF7AA4C04:mov%rax,%rsi
0x00007FF7AA4C07:jne 0x7FF7AA4C39
0x00007FF7AA4C09:mov 0x88(%rbx),%rdx
0x00007FF7AA4C10:mov 0x4(%rdx),%eax
0x00007FF7AA4C13:lea-0x1(%rax),%ecx
0x00007FF7AA4C16:测试%ecx,%ecx
0x00007FF7AA4C18:mov%ecx,0x4(%rdx)
0x00007FF7AA4C1B:jne 0x7FF7AA4C39
0x00007FF7AA4C1D:movq$0x0,0x8(%rdx)
0x00007FF7AA4C25:cmpl$0x0,0x336ba8(%rip)#0x7ffff7ddb7d4
0x00007FF7AA4C2C:je 0x7ffff7aa4c35
0x00007FF7AA4C2E:锁定decl(%rdx)
0x00007FF7AA4C31:jne 0x7FF7AA4C77
0x00007FF7AA4C33:jmp 0x7FF7AA4C39
0x00007FF7AA4C35:decl(%rdx)
0x00007FF7AA4C37:jne 0x7FF7AA4C77
0x00007FF7AA4C39:mov%rsi,%rdi
0x00007FF7AA4C3C:调用0x7ffff7a54d50
汇编程序转储结束。

您也可以直接查看getchar是如何实现的,但是这将为您提供C代码(有时可能是神秘的)。

如果您想要ASM输出,您只需请求
gdb
加载您的C程序并为您反汇编
getchar
。 这将给出如下内容(在我的系统上):

$gdb/bin/cat
(gdb)运行
启动程序:/bin/cat
^C
程序收到信号SIGINT,中断。
0x00007FF7B0C5C0位于../sysdeps/unix/syscall template.S:81处的u read_nocancel()中
(gdb)disas getchar
函数getchar的汇编程序代码转储:
0x00007FF7AA4B30:推送%rbx
0x00007ffff7aa4b31:mov 0x332be0(%rip),%rbx#0x7ffff7dd7718
0x00007FF7AA4B38:mov(%rbx),%eax
0x00007FF7AA4B3A:mov%rbx,%rdi
0x00007FF7AA4B3D:和$0x8000,%eax
0x00007FF7AA4B42:jne 0x7FF7AA4B9E
0x00007FF7AA4B44:mov 0x88(%rbx),%rdx
0x00007FF7AA4B4B4B:mov%fs:0x10,%r8
0x00007FF7AA4B54:cmp 0x8(%rdx),%r8
0x00007FF7AA4B58:je 0x7FF7AA4Bf0
0x00007FF7AA4B5E:mov$0x1,%esi
0x00007ffff7aa4b63:cmpl$0x0,0x336c6a(%rip)#0x7ffff7ddb7d4
0x00007FF7AA4B6A:je 0x7FF7AA4B78
0x00007FF7AA4B6C:锁定cmpxchg%esi,(%rdx)
0x00007FF7AA4B70:jne 0x7FF7AA4C41
0x00007FF7AA4B76:jmp 0x7FF7AA4B81
0x00007FF7AA4B78:cmpxchg%esi,(%rdx)
0x00007FF7AA4B7B:jne 0x7FF7AA4C41
0x00007FF7AA4B81:mov 0x88(%rbx),%rax
0x00007FF7AA4B88:mov 0x88(%rbx),%rdx
0x00007ffff7aa4b8f:mov 0x332b82(%rip),%rdi#0x7ffff7dd7718
0x00007FF7AA4B96:mov%r8,0x8(%rax)
0x00007FF7AA4B9A:添加$0x1,0x4(%rdx)
    .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
$ 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.
$ gcc -o prog prog.c
$ gdb prog
...
(gdb) r
^C
(gdb) disas getchar
/* Copyright (C) 1993-2015 Free Software Foundation, Inc.
2  This file is part of the GNU C Library.
3 
4  The GNU C Library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8 
9  The GNU C Library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with the GNU C Library; if not, see
16  <http://www.gnu.org/licenses/>.
17 
18  As a special exception, if you link the code in this file with
19  files compiled with a GNU compiler to produce an executable,
20  that does not cause the resulting executable to be covered by
21  the GNU Lesser General Public License. This exception does not
22  however invalidate any other reasons why the executable file
23  might be covered by the GNU Lesser General Public License.
24  This exception applies to code released by its copyright holders
25  in files containing the exception. */
26 
27 #include "libioP.h"
28 #include "stdio.h"
29 
30 #undef getchar
31 
32 int
33 getchar (void)
34 {
35  int result;
36  _IO_acquire_lock (_IO_stdin);
37  result = _IO_getc_unlocked (_IO_stdin);
38  _IO_release_lock (_IO_stdin);
39  return result;
40 }
41 
42 #if defined weak_alias && !defined _IO_MTSAFE_IO
43 #undef getchar_unlocked
44 weak_alias (getchar, getchar_unlocked)
45 #endif