Jump Table not found in Assembly code - c

I'm learning Assembly. I wrote the below c program containing switch case, created the object file(gcc -o filename filename.c), then took the object dump. But I didn't find the Labels and jump tables in the object dump.
Can anybody tell me why the jump table is not getting generated ? Like the ones mention here
Link
Code
C file
int main() {
int i = 0;
int n = 9, z = 99 , p = 999;
switch( i )
{
case -1:
n++;
printf("value n=%d",n);
break;
case 0 :
z++;
printf("value z=%d",z);
break;
case 1 :
p++;
printf("value p=%d",p);
break;
case 2 :
p++;
printf("value p=%d",p);
break;
case 3 :
p++;
printf("value p=%d",p);
break;
case 4 :
p++;
printf("value p=%d",p);
break;
case 5 :
p++;
printf("value p=%d",p);
break;
}
printf("Values n=%d z=%d p=%d \n",n,z,p);
return 0;
}
Below is the main section
0804841d <main>:
804841d: 55 push %ebp
804841e: 89 e5 mov %esp,%ebp
8048420: 83 e4 f0 and $0xfffffff0,%esp
8048423: 83 ec 20 sub $0x20,%esp
8048426: c7 44 24 1c 00 00 00 movl $0x0,0x1c(%esp)
804842d: 00
804842e: c7 44 24 10 09 00 00 movl $0x9,0x10(%esp)
8048435: 00
8048436: c7 44 24 14 63 00 00 movl $0x63,0x14(%esp)
804843d: 00
804843e: c7 44 24 18 e7 03 00 movl $0x3e7,0x18(%esp)
8048445: 00
8048446: 8b 44 24 1c mov 0x1c(%esp),%eax
804844a: 83 c0 01 add $0x1,%eax
804844d: 83 f8 06 cmp $0x6,%eax
8048450: 0f 87 cb 00 00 00 ja 8048521 <main+0x104>
8048456: 8b 04 85 1c 86 04 08 mov 0x804861c(,%eax,4),%eax
804845d: ff e0 jmp *%eax
804845f: 83 44 24 10 01 addl $0x1,0x10(%esp)
8048464: 8b 44 24 10 mov 0x10(%esp),%eax
8048468: 89 44 24 04 mov %eax,0x4(%esp)
804846c: c7 04 24 e0 85 04 08 movl $0x80485e0,(%esp)
8048473: e8 78 fe ff ff call 80482f0 <printf#plt>
8048478: e9 a4 00 00 00 jmp 8048521 <main+0x104>
804847d: 83 44 24 14 01 addl $0x1,0x14(%esp)
8048482: 8b 44 24 14 mov 0x14(%esp),%eax
8048486: 89 44 24 04 mov %eax,0x4(%esp)
804848a: c7 04 24 eb 85 04 08 movl $0x80485eb,(%esp)
8048491: e8 5a fe ff ff call 80482f0 <printf#plt>
8048496: e9 86 00 00 00 jmp 8048521 <main+0x104>
804849b: 83 44 24 18 01 addl $0x1,0x18(%esp)
80484a0: 8b 44 24 18 mov 0x18(%esp),%eax
80484a4: 89 44 24 04 mov %eax,0x4(%esp)
80484a8: c7 04 24 f6 85 04 08 movl $0x80485f6,(%esp)
80484af: e8 3c fe ff ff call 80482f0 <printf#plt>
80484b4: eb 6b jmp 8048521 <main+0x104>
80484b6: 83 44 24 18 01 addl $0x1,0x18(%esp)
80484bb: 8b 44 24 18 mov 0x18(%esp),%eax
80484bf: 89 44 24 04 mov %eax,0x4(%esp)
80484c3: c7 04 24 f6 85 04 08 movl $0x80485f6,(%esp)
80484ca: e8 21 fe ff ff call 80482f0 <printf#plt>
80484cf: eb 50 jmp 8048521 <main+0x104>
80484d1: 83 44 24 18 01 addl $0x1,0x18(%esp)
80484d6: 8b 44 24 18 mov 0x18(%esp),%eax
80484da: 89 44 24 04 mov %eax,0x4(%esp)
80484de: c7 04 24 f6 85 04 08 movl $0x80485f6,(%esp)
80484e5: e8 06 fe ff ff call 80482f0 <printf#plt>
80484ea: eb 35 jmp 8048521 <main+0x104>
80484ec: 83 44 24 18 01 addl $0x1,0x18(%esp)
80484f1: 8b 44 24 18 mov 0x18(%esp),%eax
80484f5: 89 44 24 04 mov %eax,0x4(%esp)
80484f9: c7 04 24 f6 85 04 08 movl $0x80485f6,(%esp)
8048500: e8 eb fd ff ff call 80482f0 <printf#plt>
8048505: eb 1a jmp 8048521 <main+0x104>
8048507: 83 44 24 18 01 addl $0x1,0x18(%esp)
804850c: 8b 44 24 18 mov 0x18(%esp),%eax
8048510: 89 44 24 04 mov %eax,0x4(%esp)
8048514: c7 04 24 f6 85 04 08 movl $0x80485f6,(%esp)
804851b: e8 d0 fd ff ff call 80482f0 <printf#plt>
8048520: 90 nop
8048521: 8b 44 24 18 mov 0x18(%esp),%eax
8048525: 89 44 24 0c mov %eax,0xc(%esp)
8048529: 8b 44 24 14 mov 0x14(%esp),%eax
804852d: 89 44 24 08 mov %eax,0x8(%esp)
8048531: 8b 44 24 10 mov 0x10(%esp),%eax
8048535: 89 44 24 04 mov %eax,0x4(%esp)
8048539: c7 04 24 01 86 04 08 movl $0x8048601,(%esp)
8048540: e8 ab fd ff ff call 80482f0 <printf#plt>
8048545: b8 00 00 00 00 mov $0x0,%eax
804854a: c9 leave
804854b: c3 ret
804854c: 66 90 xchg %ax,%ax
804854e: 66 90 xchg %ax,%ax
Below is the .rodata section
Disassembly of section .rodata:
080485d8 <_fp_hw>:
80485d8: 03 00 add (%eax),%eax
...
Can anybody let me know why this is behaving like this?
Thanks in Advance

Your jump table is located at address 0x804861c. If you dump this address, I'm pretty sure, you'll find the values 0x804845f, 0x804847d, 0x804849b, etc. since these values correspond to the addresses of the branches of the switch statement.
What happens is that first it is ensured that the value of i (0x1c(%esp))is between 0 and 6 (and jump if above, ja, to last printf) and if it is between, uses its value multiplied by 4 (sizeof addresses on your architecture) as an offset into the jump table (0x804861c(,%eax,4),%eax).
I'm not sure what you're looking for exactly, or what you're trying to achieve, but as #Jens Gustedt pointed out, you should use the -S switch if you want to observe the assembly generated.
Additionally, beware that your code can easily be optimised by the compiler, i.e. as soon as you use the -O switch your assembly will probably shrink down to the last printf and the return statement, since the whole code execution can be predicted and useless parts can be omitted.

Related

Assembly Interpretation - Register confusion

I'm working on an assignment for class where I have to interpret assembly. I know the input to defuse the bomb is 442, but I'm not exactly sure why.
8048c80: 83 ec 2c sub $0x2c,%esp
8048c83: c7 44 24 1c 00 00 00 movl $0x0,0x1c(%esp)
8048c8a: 00
8048c8b: 8d 44 24 1c lea 0x1c(%esp),%eax
8048c8f: 89 44 24 08 mov %eax,0x8(%esp)
8048c93: c7 44 24 04 64 a7 04 movl $0x804a764,0x4(%esp)
8048c9a: 08
8048c9b: 8b 44 24 30 mov 0x30(%esp),%eax
8048c9f: 89 04 24 mov %eax,(%esp)
8048ca2: e8 59 fc ff ff call 8048900 <__isoc99_sscanf#plt>
8048ca7: 83 f8 01 cmp $0x1,%eax
8048caa: 74 05 je 8048cb1 <phase_1+0x31>
8048cac: e8 e4 07 00 00 call 8049495 <explode_bomb>
8048cb1: 81 7c 24 1c ba 01 00 cmpl $0x1ba,0x1c(%esp)
8048cb8: 00
8048cb9: 74 05 je 8048cc0 <phase_1+0x40>
8048cbb: e8 d5 07 00 00 call 8049495 <explode_bomb>
8048cc0: 83 c4 2c add $0x2c,%esp
8048cc3: c3 ret
Sscanf takes two values, "%d" and my inputted value, but I'm not sure where it stores the value or why %eax is 1 or why 0x1c(%esp) has the value. We store 0x0 there at the beginning, and then move 0x30(%esp), %eax, so shouldn't it be 0? Any help understanding this would be very much appreciated.
To be clear, this is x86 in at&t syntax.

Deciphering x86 assembly function

I am currently working on phase 2 of the binary bomb assignment. I'm having trouble deciphering exactly what a certain function does when called. I've been stuck on it for days.
The function is:
0000000000400f2a <func2a>:
400f2a: 85 ff test %edi,%edi
400f2c: 74 1d je 400f4b <func2a+0x21>
400f2e: b9 cd cc cc cc mov $0xcccccccd,%ecx
400f33: 89 f8 mov %edi,%eax
400f35: f7 e1 mul %ecx
400f37: c1 ea 03 shr $0x3,%edx
400f3a: 8d 04 92 lea (%rdx,%rdx,4),%eax
400f3d: 01 c0 add %eax,%eax
400f3f: 29 c7 sub %eax,%edi
400f41: 83 04 be 01 addl $0x1,(%rsi,%rdi,4)
400f45: 89 d7 mov %edx,%edi
400f47: 85 d2 test %edx,%edx
400f49: 75 e8 jne 400f33 <func2a+0x9>
400f4b: f3 c3 repz retq
It gets called in the larger function "phase_2":
0000000000400f4d <phase_2>:
400f4d: 53 push %rbx
400f4e: 48 83 ec 60 sub $0x60,%rsp
400f52: 48 c7 44 24 30 00 00 movq $0x0,0x30(%rsp)
400f59: 00 00
400f5b: 48 c7 44 24 38 00 00 movq $0x0,0x38(%rsp)
400f62: 00 00
400f64: 48 c7 44 24 40 00 00 movq $0x0,0x40(%rsp)
400f6b: 00 00
400f6d: 48 c7 44 24 48 00 00 movq $0x0,0x48(%rsp)
400f74: 00 00
400f76: 48 c7 44 24 50 00 00 movq $0x0,0x50(%rsp)
400f7d: 00 00
400f7f: 48 c7 04 24 00 00 00 movq $0x0,(%rsp)
400f86: 00
400f87: 48 c7 44 24 08 00 00 movq $0x0,0x8(%rsp)
400f8e: 00 00
400f90: 48 c7 44 24 10 00 00 movq $0x0,0x10(%rsp)
400f97: 00 00
400f99: 48 c7 44 24 18 00 00 movq $0x0,0x18(%rsp)
400fa0: 00 00
400fa2: 48 c7 44 24 20 00 00 movq $0x0,0x20(%rsp)
400fa9: 00 00
400fab: 48 8d 4c 24 58 lea 0x58(%rsp),%rcx
400fb0: 48 8d 54 24 5c lea 0x5c(%rsp),%rdx
400fb5: be 9e 26 40 00 mov $0x40269e,%esi
400fba: b8 00 00 00 00 mov $0x0,%eax
400fbf: e8 6c fc ff ff callq 400c30 <__isoc99_sscanf#plt>
400fc4: 83 f8 02 cmp $0x2,%eax
400fc7: 74 05 je 400fce <phase_2+0x81>
400fc9: e8 c1 06 00 00 callq 40168f <explode_bomb>
400fce: 83 7c 24 5c 64 cmpl $0x64,0x5c(%rsp)
400fd3: 76 07 jbe 400fdc <phase_2+0x8f>
400fd5: 83 7c 24 58 64 cmpl $0x64,0x58(%rsp)
400fda: 77 05 ja 400fe1 <phase_2+0x94>
400fdc: e8 ae 06 00 00 callq 40168f <explode_bomb>
400fe1: 48 8d 74 24 30 lea 0x30(%rsp),%rsi
400fe6: 8b 7c 24 5c mov 0x5c(%rsp),%edi
400fea: e8 3b ff ff ff callq 400f2a <func2a>
400fef: 48 89 e6 mov %rsp,%rsi
400ff2: 8b 7c 24 58 mov 0x58(%rsp),%edi
400ff6: e8 2f ff ff ff callq 400f2a <func2a>
400ffb: bb 00 00 00 00 mov $0x0,%ebx
401000: 8b 04 1c mov (%rsp,%rbx,1),%eax
401003: 39 44 1c 30 cmp %eax,0x30(%rsp,%rbx,1)
401007: 74 05 je 40100e <phase_2+0xc1>
401009: e8 81 06 00 00 callq 40168f <explode_bomb>
40100e: 48 83 c3 04 add $0x4,%rbx
401012: 48 83 fb 28 cmp $0x28,%rbx
401016: 75 e8 jne 401000 <phase_2+0xb3>
401018: 48 83 c4 60 add $0x60,%rsp
40101c: 5b pop %rbx
40101d: c3 retq
I completely understand what phase_2 is doing, I just don't understand what func2a is doing and how it affects the values at 0x30(%rsp) and so on. Because of this I always get to the comparison statement at 0x401003, and the bomb eventually explodes there.
My problem is I don't understand how the input (phase solution) is affecting the values at 0x30(%rsp) via func2a.
400f2a: 85 ff test %edi,%edi
400f2c: 74 1d je 400f4b <func2a+0x21>
This is just an early exit for when edi is zero (je is the same as jz).
400f2e: b9 cd cc cc cc mov $0xcccccccd,%ecx
400f33: 89 f8 mov %edi,%eax
400f35: f7 e1 mul %ecx
400f37: c1 ea 03 shr $0x3,%edx
This is a classic optimization trick; it is the integer arithmetic equivalent of dividing by multiplying by the inverse (see here for details); in practice, here it's the same as saying edx = edi / 10;
400f3a: 8d 04 92 lea (%rdx,%rdx,4),%eax
400f3d: 01 c0 add %eax,%eax
Here it is exploiting lea to perform arithmetic (and it's way clearer in Intel syntax, where it is lea eax,[rdx+rdx*4] => eax = edx*5), then sums the result with itself. It all boils down to eax = edx*10.
400f3f: 29 c7 sub %eax,%edi
Then, subtract it back to edi.
So, all in all this is a complicated (but fast) way to compute the last decimal digit of edi; what we have until now is something like:
void func2a(unsigned edi) {
if(edi==0) return;
label1:
edx=edi/10;
edi%=10;
// ...
}
(label1: is there because 400f33 is a jump target later)
Going on:
400f41: 83 04 be 01 addl $0x1,(%rsi,%rdi,4)
Again, this is way clearer to me in Intel syntax - add dword [rsi+rdi*4],byte +0x1. It is a regular increment into an array of 32-bit int (rdi is multiplied by 4); so, we can imagine that rsi points to an array of integers, indexed with the just-calculated last digit of edi.
void func2a(unsigned edi, int rsi[]) {
if(edi==0) return;
label1:
edx=edi/10;
edi%=10;
rsi[edi]++;
}
Then:
400f45: 89 d7 mov %edx,%edi
400f47: 85 d2 test %edx,%edx
400f49: 75 e8 jne 400f33 <func2a+0x9>
Move the result of the division we calculated above to edi, and loop if it's different from zero.
400f4b: f3 c3 repz retq
Return (using an unusual encoding of the instruction that is optimal for certain AMD processors).
So, by rewriting the jumps with a while loop and giving some meaningful names...
// number is edi, digits_count is rsi, as per regular
// x64 SystemV calling convention
void count_digits(unsigned number, int digits_count[]) {
while(number) {
digits_count[number%10]++;
number/=10;
}
}
I.e., this is a function that, given an integer, counts the occurrences of the single decimal digits, by incrementing the corresponding buckets in the digits_count array.
Fun fact: if we give the C code above to gcc (almost any recent version at -O1) we obtain back exactly the assembly you provided.

Manual decompilation of asm snippet

I've been trying to decompile the following asm snippet(that's all I have):
55 push %rbp
48 89 e5 mov %rsp,%rbp
48 81 ec d0 00 00 00 sub $0xd0,%rsp
64 48 8b 04 25 28 00 mov %fs:0x28,%rax
00 00
48 89 45 f8 mov %rax,-0x8(%rbp)
31 c0 xor %eax,%eax
48 c7 85 30 ff ff ff movq $0x0,-0xd0(%rbp)
00 00 00 00
48 8d b5 38 ff ff ff lea -0xc8(%rbp),%rsi
b8 00 00 00 00 mov $0x0,%eax
ba 18 00 00 00 mov $0x18,%edx
48 89 f7 mov %rsi,%rdi
48 89 d1 mov %rdx,%rcx
f3 48 ab rep stos %rax,%es:(%rdi)
48 8b 15 19 06 20 00 mov 0x200619(%rip),%rdx
48 8d 85 30 ff ff ff lea -0xd0(%rbp),%rax
be ce 0f 40 00 mov $0x400fce,%esi
48 89 c7 mov %rax,%rdi
b8 00 00 00 00 mov $0x0,%eax
e8 4e fc ff ff callq 4008a0 <sprintf#plt>
Here is my attempt:
char buf[192] = {0};
sprintf(buf, "hello %s", name);
I've compiled this with gcc 4.8.5, and it gave me:
55 push %rbp
48 89 e5 mov %rsp,%rbp
48 81 ec d0 00 00 00 sub $0xd0,%rsp
64 48 8b 04 25 28 00 mov %fs:0x28,%rax
00 00
48 89 45 f8 mov %rax,-0x8(%rbp)
31 c0 xor %eax,%eax
48 8d b5 30 ff ff ff lea -0xd0(%rbp),%rsi
b8 00 00 00 00 mov $0x0,%eax
ba 18 00 00 00 mov $0x18,%edx
48 89 f7 mov %rsi,%rdi
48 89 d1 mov %rdx,%rcx
f3 48 ab rep stos %rax,%es:(%rdi)
48 8b 15 14 14 20 00 mov 0x201414(%rip),%rdx
48 8d 85 30 ff ff ff lea -0xd0(%rbp),%rax
be 2e 10 40 00 mov $0x40102e,%esi
48 89 c7 mov %rax,%rdi
b8 00 00 00 00 mov $0x0,%eax
e8 cb fb ff ff callq 4008a0 <sprintf#plt>
I'm struggling to figure out why this exists:
movq $0x0,-0xd0(%rbp)
and also the subsequent usage of -0xd0(%rbp) as a pointer for the argument to sprintf. I'm puzzled because the rep stos begin at -0xc8(%rbp) and not -0xd0(%rbp).
This is probably compiler specific, but still I'm curious what could possibly be the original code that produced that asm.
I imagine something like:
char buf[192] = {0, 0, 0, 0, 0, 0, 0, 0};
sprintf(buf + 8, "hello %s", name);
... would give you that output.
The movq instruction you refer to stores 0 (an 8-byte quantity) at the beginning of an array. The -0xc8(%rbp) comes from copying a string to an offset within the array.

Assembly - How To Find How Much Stack Space A Function Allocates For Itself

I'm working with the GDB debugger right now. Question: In the disassembly file, locate the definition of main. How much stack space (decimal number) does this function allocate for itself?
Here is the function:
08048460 <main>:
8048460: 55 push %ebp
8048461: 89 e5 mov %esp,%ebp
8048463: 83 e4 f0 and $0xfffffff0,%esp
8048466: 83 ec 40 sub $0x40,%esp
8048469: b8 db 0f 49 40 mov $0x40490fdb,%eax
804846e: 89 44 24 08 mov %eax,0x8(%esp)
8048472: b8 ec 78 ad e0 mov $0xe0ad78ec,%eax
8048477: 89 44 24 04 mov %eax,0x4(%esp)
804847b: b8 ec 78 ad 60 mov $0x60ad78ec,%eax
8048480: 89 04 24 mov %eax,(%esp)
8048483: e8 bc ff ff ff call 8048444 <fn1>
8048488: d9 5c 24 3c fstps 0x3c(%esp)
804848c: b8 db 0f 49 40 mov $0x40490fdb,%eax
8048491: 89 44 24 08 mov %eax,0x8(%esp)
8048495: b8 ec 78 ad e0 mov $0xe0ad78ec,%eax
804849a: 89 44 24 04 mov %eax,0x4(%esp)
804849e: b8 ec 78 ad 60 mov $0x60ad78ec,%eax
80484a3: 89 04 24 mov %eax,(%esp)
80484a6: e8 a7 ff ff ff call 8048452 <fn2>
80484ab: d9 5c 24 38 fstps 0x38(%esp)
80484af: c7 04 24 e0 85 04 08 movl $0x80485e0,(%esp)
80484b6: e8 c5 fe ff ff call 8048380 <puts#plt>
80484bb: d9 44 24 3c flds 0x3c(%esp)
80484bf: d8 64 24 38 fsubs 0x38(%esp)
80484c3: dd 1c 24 fstpl (%esp)
80484c6: e8 95 fe ff ff call 8048360 <abs#plt>
80484cb: 89 44 24 2c mov %eax,0x2c(%esp)
80484cf: db 44 24 2c fildl 0x2c(%esp)
80484d3: dd 05 20 86 04 08 fldl 0x8048620
80484d9: d9 c9 fxch %st(1)
80484db: da e9 fucompp
80484dd: df e0 fnstsw %ax
80484df: 9e sahf
80484e0: 0f 97 c0 seta %al
80484e3: 84 c0 test %al,%al
80484e5: 74 21 je 8048508 <main+0xa8>
80484e7: d9 44 24 38 flds 0x38(%esp)
80484eb: d9 44 24 3c flds 0x3c(%esp)
80484ef: d9 c9 fxch %st(1)
80484f1: b8 e8 85 04 08 mov $0x80485e8,%eax
80484f6: dd 5c 24 0c fstpl 0xc(%esp)
80484fa: dd 5c 24 04 fstpl 0x4(%esp)
80484fe: 89 04 24 mov %eax,(%esp)
8048501: e8 6a fe ff ff call 8048370 <printf#plt>
8048506: eb 0c jmp 8048514 <main+0xb4>
8048508: c7 04 24 08 86 04 08 movl $0x8048608,(%esp)
804850f: e8 6c fe ff ff call 8048380 <puts#plt>
8048514: b8 00 00 00 00 mov $0x0,%eax
8048519: c9 leave
804851a: c3 ret
804851b: 90 nop
804851c: 90 nop
804851d: 90 nop
804851e: 90 nop
804851f: 90 nop
I don't understand how to determine this. Is the question asking how much stack space the function allocates for itself before it's called or during the process it was being called? Is it asking how many bytes or how many registers in the stack are being taken up by this function?
I'm new to assembly, so is there a certain technique I should use to answer this question?
This line:
8048466: 83 ec 40 sub $0x40,%esp
tells you that the space allocated is 0x40 (64) bytes.
First there's a push ebp, followed by rounding esp down to a 16 byte boundary, then 0x40 is subtracted from esp. This could get further complicated if something like _alloca() was used to dynamically allocate space from the stack.

can some help understand this objdump of c [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
08048544 <compare_password>:
8048544: 55 push %ebp
8048545: 89 e5 mov %esp,%ebp
8048547: 83 ec 38 sub $0x38,%esp
804854a: 8b 45 0c mov 0xc(%ebp),%eax
804854d: 89 45 d4 mov %eax,-0x2c(%ebp)
8048550: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048556: 89 45 f4 mov %eax,-0xc(%ebp)
8048559: 31 c0 xor %eax,%eax
804855b: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%ebp)
8048562: c7 45 e0 00 00 00 00 movl $0x0,-0x20(%ebp)
8048569: eb 22 jmp 804858d <compare_password+0x49>
804856b: 8b 45 e0 mov -0x20(%ebp),%eax
804856e: 03 45 d4 add -0x2c(%ebp),%eax
8048571: 0f b6 10 movzbl (%eax),%edx
8048574: 8b 45 e0 mov -0x20(%ebp),%eax
8048577: 05 44 a1 04 08 add $0x804a144,%eax
804857c: 0f b6 00 movzbl (%eax),%eax
804857f: 31 c2 xor %eax,%edx
8048581: 8d 45 ea lea -0x16(%ebp),%eax
8048584: 03 45 e0 add -0x20(%ebp),%eax
8048587: 88 10 mov %dl,(%eax)
8048589: 83 45 e0 01 addl $0x1,-0x20(%ebp)
804858d: 83 7d e0 09 cmpl $0x9,-0x20(%ebp)
8048591: 7e d8 jle 804856b <compare_password+0x27>
8048593: c7 45 e0 00 00 00 00 movl $0x0,-0x20(%ebp)
804859a: eb 2c jmp 80485c8 <compare_password+0x84>
804859c: 8b 55 08 mov 0x8(%ebp),%edx
804859f: 89 d0 mov %edx,%eax
80485a1: c1 e0 02 shl $0x2,%eax
80485a4: 01 d0 add %edx,%eax
80485a6: 01 c0 add %eax,%eax
80485a8: 03 45 e0 add -0x20(%ebp),%eax
80485ab: 05 e0 a0 04 08 add $0x804a0e0,%eax
80485b0: 0f b6 10 movzbl (%eax),%edx
80485b3: 8d 45 ea lea -0x16(%ebp),%eax
80485b6: 03 45 e0 add -0x20(%ebp),%eax
80485b9: 0f b6 00 movzbl (%eax),%eax
80485bc: 38 c2 cmp %al,%dl
80485be: 75 04 jne 80485c4 <compare_password+0x80>
80485c0: 83 45 e4 01 addl $0x1,-0x1c(%ebp)
80485c4: 83 45 e0 01 addl $0x1,-0x20(%ebp)
80485c8: 83 7d e0 09 cmpl $0x9,-0x20(%ebp)
80485cc: 7e ce jle 804859c <compare_password+0x58>
80485ce: 83 7d e4 08 cmpl $0x8,-0x1c(%ebp)
80485d2: 7e 07 jle 80485db <compare_password+0x97>
80485d4: b8 01 00 00 00 mov $0x1,%eax
80485d9: eb 05 jmp 80485e0 <compare_password+0x9c>
80485db: b8 00 00 00 00 mov $0x0,%eax
80485e0: 8b 55 f4 mov -0xc(%ebp),%edx
80485e3: 65 33 15 14 00 00 00 xor %gs:0x14,%edx
80485ea: 74 05 je 80485f1 <compare_password+0xad>
80485ec: e8 2f fe ff ff call 8048420 <__stack_chk_fail#plt>
80485f1: c9 leave
80485f2: c3 ret
080485f3 <main>:
80485f3: 55 push %ebp
80485f4: 89 e5 mov %esp,%ebp
80485f6: 83 e4 f0 and $0xfffffff0,%esp
80485f9: 83 ec 30 sub $0x30,%esp
80485fc: 65 a1 14 00 00 00 mov %gs:0x14,%eax
8048602: 89 44 24 2c mov %eax,0x2c(%esp)
8048606: 31 c0 xor %eax,%eax
8048608: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
804860f: 00
8048610: 8d 44 24 10 lea 0x10(%esp),%eax
8048614: 89 04 24 mov %eax,(%esp)
8048617: e8 f4 fd ff ff call 8048410 <gettimeofday#plt>
804861c: 8b 54 24 10 mov 0x10(%esp),%edx
8048620: 8b 44 24 14 mov 0x14(%esp),%eax
8048624: 0f af c2 imul %edx,%eax
8048627: 89 04 24 mov %eax,(%esp)
804862a: e8 21 fe ff ff call 8048450 <srand#plt>
804862f: e8 3c fe ff ff call 8048470 <rand#plt>
8048634: 89 44 24 18 mov %eax,0x18(%esp)
8048638: 8b 4c 24 18 mov 0x18(%esp),%ecx
804863c: ba 67 66 66 66 mov $0x66666667,%edx
8048641: 89 c8 mov %ecx,%eax
8048643: f7 ea imul %edx
8048645: c1 fa 02 sar $0x2,%edx
8048648: 89 c8 mov %ecx,%eax
804864a: c1 f8 1f sar $0x1f,%eax
804864d: 29 c2 sub %eax,%edx
804864f: 89 d0 mov %edx,%eax
8048651: c1 e0 02 shl $0x2,%eax
8048654: 01 d0 add %edx,%eax
8048656: 01 c0 add %eax,%eax
8048658: 89 ca mov %ecx,%edx
804865a: 29 c2 sub %eax,%edx
804865c: 89 d0 mov %edx,%eax
804865e: 89 44 24 18 mov %eax,0x18(%esp)
8048662: 8b 54 24 18 mov 0x18(%esp),%edx
8048666: 89 d0 mov %edx,%eax
8048668: c1 e0 02 shl $0x2,%eax
804866b: 01 d0 add %edx,%eax
804866d: 01 c0 add %eax,%eax
804866f: 8d 90 60 a0 04 08 lea 0x804a060(%eax),%edx
8048675: b8 c0 87 04 08 mov $0x80487c0,%eax
804867a: 89 54 24 04 mov %edx,0x4(%esp)
804867e: 89 04 24 mov %eax,(%esp)
8048681: e8 7a fd ff ff call 8048400 <printf#plt>
8048686: b8 da 87 04 08 mov $0x80487da,%eax
804868b: 8d 54 24 22 lea 0x22(%esp),%edx
804868f: 89 54 24 04 mov %edx,0x4(%esp)
8048693: 89 04 24 mov %eax,(%esp)
8048696: e8 e5 fd ff ff call 8048480 <__isoc99_scanf#plt>
804869b: 8d 44 24 22 lea 0x22(%esp),%eax
804869f: 89 44 24 04 mov %eax,0x4(%esp)
80486a3: 8b 44 24 18 mov 0x18(%esp),%eax
80486a7: 89 04 24 mov %eax,(%esp)
80486aa: e8 95 fe ff ff call 8048544 <compare_password>
80486af: 89 44 24 1c mov %eax,0x1c(%esp)
80486b3: 83 7c 24 1c 01 cmpl $0x1,0x1c(%esp)
80486b8: 75 0e jne 80486c8 <main+0xd5>
80486ba: c7 04 24 dd 87 04 08 movl $0x80487dd,(%esp)
80486c1: e8 6a fd ff ff call 8048430 <puts#plt>
80486c6: eb 0c jmp 80486d4 <main+0xe1>
80486c8: c7 04 24 f2 87 04 08 movl $0x80487f2,(%esp)
80486cf: e8 5c fd ff ff call 8048430 <puts#plt>
80486d4: 8b 54 24 2c mov 0x2c(%esp),%edx
80486d8: 65 33 15 14 00 00 00 xor %gs:0x14,%edx
80486df: 74 05 je 80486e6 <main+0xf3>
80486e1: e8 3a fd ff ff call 8048420 <__stack_chk_fail#plt>
80486e6: c9 leave
80486e7: c3 ret
80486e8: 90 nop
80486e9: 90 nop
80486ea: 90 nop
80486eb: 90 nop
80486ec: 90 nop
80486ed: 90 nop
80486ee: 90 nop
80486ef: 90 nop
Ok, learning assembly code from scratch will take some time and effort, but there's no harm in getting the basics.
Each line of this output contains three parts:
The offset in the file where that piece of code is (in hex)
The bytes that make up that piece of code (each in hex, again)
The assembly language form of that code (basically reverse-translated from the bytes).
You can generally read the flow of the program through the last column. Instructions like JMPs will refer to other locations, which may or may not be nearby in the code. They may be presented in a labelled form like:
jmp 804858d <compare_password+0x49>
That says, jump to offset 0x804858d, so you can find that value in the first column. The label says that this is offset 0x49 after compare_password.
If you don't know what most of the instructions do, well, they mostly move, combine and compare individual words of memory and register. Even when you learn what each code does, understanding what it does in the context of this particular program can be hard. And you generally need to know the location of other important pieces of data when the program will be running to know what the effect will be.
There are lots of resources for learning computer programming at the level of debugging, assembly language and dissassembly, but I will leave it to others to refer you. If you really want to learn, a good way is to write your own simple program in C, and compile it to assembly. Then compare the C and assembly output side-by-side, figuring out how the C statements have been translated into instructions.

Resources