这是一个简单的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/