アセンブリメモ -ループ-

前回に続いてループ処理を見ていく.

#include <stdio.h>

int main(){
   int i;
   for (i=0; i<10; i++){
      printf("%d\n", i);
   }
   return 0;
}
   0x080483fb <+0>:  lea    0x4(%esp),%ecx
   0x080483ff <+4>:  and    $0xfffffff0,%esp
   0x08048402 <+7>:  pushl  -0x4(%ecx)
   0x08048405 <+10>: push   %ebp
   0x08048406 <+11>: mov    %esp,%ebp
   0x08048408 <+13>: push   %ecx
   0x08048409 <+14>: sub    $0x14,%esp
   0x0804840c <+17>: movl   $0x0,-0xc(%ebp)
   0x08048413 <+24>: jmp    0x804842c <main+49>
   0x08048415 <+26>: sub    $0x8,%esp
   0x08048418 <+29>: pushl  -0xc(%ebp)
   0x0804841b <+32>: push   $0x80484d0
   0x08048420 <+37>: call   0x80482d0 <printf@plt>
   0x08048425 <+42>: add    $0x10,%esp
   0x08048428 <+45>: addl   $0x1,-0xc(%ebp)
   0x0804842c <+49>: cmpl   $0x9,-0xc(%ebp)
   0x08048430 <+53>: jle    0x8048415 <main+26>
   0x08048432 <+55>: mov    $0x0,%eax
   0x08048437 <+60>: mov    -0x4(%ebp),%ecx
   0x0804843a <+63>: leave  
   0x0804843b <+64>: lea    -0x4(%ecx),%esp
   0x0804843e <+67>: ret    

f:id:yagamikou:20150924021650p:plain

0x08048413にてjmp命令で0x804842cに飛ばされる.
0x804842cではcmp命令で0x9と変数iを比較され, jle命令で9より小さい場合, printfの処理へと移る.

ではbreakが入った場合どうなるか.

#include <stdio.h>

int main(){
   int i;
   for (i=0; i<10; i++){
      if (i == 5){
         break;
      }
      printf("%d\n", i);
   }
   return 0;
}
   0x080483fb <+0>:  lea    0x4(%esp),%ecx
   0x080483ff <+4>:  and    $0xfffffff0,%esp
   0x08048402 <+7>:  pushl  -0x4(%ecx)
   0x08048405 <+10>: push   %ebp
   0x08048406 <+11>: mov    %esp,%ebp
   0x08048408 <+13>: push   %ecx
   0x08048409 <+14>: sub    $0x14,%esp
   0x0804840c <+17>: movl   $0x0,-0xc(%ebp)
   0x08048413 <+24>: jmp    0x8048434 <main+57>
   0x08048415 <+26>: cmpl   $0x5,-0xc(%ebp)
   0x08048419 <+30>: jne    0x804841d <main+34>
   0x0804841b <+32>: jmp    0x804843a <main+63>
   0x0804841d <+34>: sub    $0x8,%esp
   0x08048420 <+37>: pushl  -0xc(%ebp)
   0x08048423 <+40>: push   $0x80484e0
   0x08048428 <+45>: call   0x80482d0 <printf@plt>
   0x0804842d <+50>: add    $0x10,%esp
   0x08048430 <+53>: addl   $0x1,-0xc(%ebp)
   0x08048434 <+57>: cmpl   $0x9,-0xc(%ebp)
   0x08048438 <+61>: jle    0x8048415 <main+26>
   0x0804843a <+63>: mov    $0x0,%eax
   0x0804843f <+68>: mov    -0x4(%ebp),%ecx
   0x08048442 <+71>: leave  
   0x08048443 <+72>: lea    -0x4(%ecx),%esp
   0x08048446 <+75>: ret    

f:id:yagamikou:20150924021705p:plain

breakのif文が0x08048415にあることが分かる.
条件式を満たさなければjne命令で0x804841dへと飛び, 満たしていればjmpで0x804843aへと飛ぶ.

ちなみにwhile文もfor文と同じようなアセンブラコードになる.

#include <stdio.h>

int main(){
   int i=0;
   while(i<=10){
      printf("%d\n", i);
      i++;
   }
   return 0;
}
   0x080483fb <+0>:  lea    0x4(%esp),%ecx
   0x080483ff <+4>:  and    $0xfffffff0,%esp
   0x08048402 <+7>:  pushl  -0x4(%ecx)
   0x08048405 <+10>: push   %ebp
   0x08048406 <+11>: mov    %esp,%ebp
   0x08048408 <+13>: push   %ecx
   0x08048409 <+14>: sub    $0x14,%esp
   0x0804840c <+17>: movl   $0x0,-0xc(%ebp)
   0x08048413 <+24>: jmp    0x804842c <main+49>
   0x08048415 <+26>: sub    $0x8,%esp
   0x08048418 <+29>: pushl  -0xc(%ebp)
   0x0804841b <+32>: push   $0x80484d0
   0x08048420 <+37>: call   0x80482d0 <printf@plt>
   0x08048425 <+42>: add    $0x10,%esp
   0x08048428 <+45>: addl   $0x1,-0xc(%ebp)
   0x0804842c <+49>: cmpl   $0xa,-0xc(%ebp)
   0x08048430 <+53>: jle    0x8048415 <main+26>
   0x08048432 <+55>: mov    $0x0,%eax
   0x08048437 <+60>: mov    -0x4(%ebp),%ecx
   0x0804843a <+63>: leave  
   0x0804843b <+64>: lea    -0x4(%ecx),%esp
   0x0804843e <+67>: ret