私は逆転の基本を学ぼうとしていて、小さなCプログラムを分解しようとしました。私はMacOS10.7.2(64ビット-Intel)で作業しており、gcc4.2.1を使用しています。
#include <stdio.h>
int main() {
char word[20];
scanf("%s",word);
if (strcmp(word,"password")==0)
printf("Correct\n");
else
printf("Fail\n");
}
でコンパイルし、gdbでしばらく作業して、呼び出し(100000e8e)gcc -o test test.c
の後にブレークポイントを設定し、関連するアセンブリコードを取得しました(私が思うに):strcmp
0x0000000100000e40 <main+0>: push %rbp
0x0000000100000e41 <main+1>: mov %rsp,%rbp
0x0000000100000e44 <main+4>: sub $0x30,%rsp
0x0000000100000e48 <main+8>: mov 0x1e9(%rip),%rax # 0x100001038
0x0000000100000e4f <main+15>: mov (%rax),%rax
0x0000000100000e52 <main+18>: mov %rax,-0x8(%rbp)
0x0000000100000e56 <main+22>: lea -0x20(%rbp),%rax
0x0000000100000e5a <main+26>: mov %rax,%rcx
0x0000000100000e5d <main+29>: xor %dl,%dl
0x0000000100000e5f <main+31>: lea 0xda(%rip),%rsi # 0x100000f40
0x0000000100000e66 <main+38>: mov %rsi,%rdi
0x0000000100000e69 <main+41>: mov %rcx,%rsi
0x0000000100000e6c <main+44>: mov %rax,-0x28(%rbp)
0x0000000100000e70 <main+48>: mov %dl,%al
0x0000000100000e72 <main+50>: callq 0x100000eee <dyld_stub_scanf>
0x0000000100000e77 <main+55>: mov -0x28(%rbp),%rcx
0x0000000100000e7b <main+59>: xor %dl,%dl
0x0000000100000e7d <main+61>: lea 0xbf(%rip),%rsi # 0x100000f43
0x0000000100000e84 <main+68>: mov %rcx,%rdi
0x0000000100000e87 <main+71>: mov %dl,%al
0x0000000100000e89 <main+73>: callq 0x100000ef4 <dyld_stub_strcmp>
0x0000000100000e8e <main+78>: mov %eax,%ecx
0x0000000100000e90 <main+80>: cmp $0x0,%ecx
0x0000000100000e93 <main+83>: jne 0x100000ea6 <main+102>
0x0000000100000e95 <main+85>: lea 0xb0(%rip),%rax # 0x100000f4c
0x0000000100000e9c <main+92>: mov %rax,%rdi
0x0000000100000e9f <main+95>: callq 0x100000ee8 <dyld_stub_puts>
0x0000000100000ea4 <main+100>: jmp 0x100000eb5 <main+117>
0x0000000100000ea6 <main+102>: lea 0xa7(%rip),%rax # 0x100000f54
0x0000000100000ead <main+109>: mov %rax,%rdi
0x0000000100000eb0 <main+112>: callq 0x100000ee8 <dyld_stub_puts>
0x0000000100000eb5 <main+117>: mov -0xc(%rbp),%eax
0x0000000100000eb8 <main+120>: mov 0x179(%rip),%rcx # 0x100001038
0x0000000100000ebf <main+127>: mov (%rcx),%rcx
0x0000000100000ec2 <main+130>: mov -0x8(%rbp),%rdx
0x0000000100000ec6 <main+134>: cmp %rdx,%rcx
0x0000000100000ec9 <main+137>: mov %eax,-0x2c(%rbp)
0x0000000100000ecc <main+140>: jne 0x100000ed7 <main+151>
0x0000000100000ece <main+142>: mov -0x2c(%rbp),%eax
0x0000000100000ed1 <main+145>: add $0x30,%rsp
0x0000000100000ed5 <main+149>: pop %rbp
0x0000000100000ed6 <main+150>: retq
0x0000000100000ed7 <main+151>: callq 0x100000edc <dyld_stub___stack_chk_fail>
さて、アセンブラの私の理解によれば、物事は簡単なはずですstrcmp
。100000e89での呼び出しの後、の値%ecx
が保存され、0と比較されます。
それらが等しくない場合(jne
)、ジャンプ(else)があり、そうでない場合は続行する必要があります(if)。
非常によく、間違った入力でも「正しい」となるように変更jne
することを考えました。je
実際、私はしませんでした。問題が何であるかを理解しようとして、操作コードを調べようとすると、奇妙な(私にとって)出力が得られます:
(gdb) x/8x 0x100000e93
0x100000e93 <main+83>: 0x8d481175 0x0000b005 0xc7894800 0x000044e8
0x100000ea3 <main+99>: 0x480feb00 0x00a7058d 0x89480000 0x0033e8c7
0f85
のコードであるべきであるという兆候はありませんjne
。
少し戸惑いました…ジャンプのオペコードをもらえませんか?誰かが私のエラーを説明してもらえますか?