2016-02-11 3 views
2

Я пытаюсь понять, как переключатель оператор работает в сборке, и я имею следующую программу:переключатель в сборе

int main (int argc, char **argv) 
{ 
    int  x = argc > 1 ? atoi(argv[1]) : 2; 
    int  y; 

    switch (x) { 
     case 0: 
      y = 0; 
      break; 
     case 1: 
      y = 1; 
      break; 
     case 2: 
      y = 2; 
      break; 
     case 3: 
      y = 3; 
      // this case "drops through" 
     case 4: 
      y = 4; 
      break; 
     default: 
      y = -1; 
      break; 
     } 

    return 0; 
} 

В сборке он выглядит:

0x804842f <main+19>  cmpl $0x1,(%eax) 
0x8048432 <main+22>  jle 0x804844a <main+46>                       
0x8048434 <main+24>  mov 0x4(%eax),%eax 
0x8048437 <main+27>  add $0x4,%eax 
0x804843a <main+30>  mov (%eax),%eax 
0x804843c <main+32>  sub $0xc,%esp 
0x804843f <main+35>  push %eax 
0x8048440 <main+36>  call 0x8048310 <[email protected]> 
0x8048445 <main+41>  add $0x10,%esp 
0x8048448 <main+44>  jmp 0x804844f <main+51> 
0x804844a <main+46>  mov $0x2,%eax 
0x804844f <main+51>  mov %eax,-0xc(%ebp) 
0x8048452 <main+54>  cmpl $0x4,-0xc(%ebp) 
0x8048456 <main+58>  ja  0x8048492 <main+118> 
0x8048458 <main+60>  mov -0xc(%ebp),%eax 
0x804845b <main+63>  shl $0x2,%eax 
0x804845e <main+66>  add $0x8048540,%eax  

Мой первый вопрос почему есть ja инструкция в <main+58>, а не jg, так как мы используем целые числа со знаком. И второй вопрос - почему есть сдвиг на 2 бита в <main+63>, а не какое-либо другое значение.

+0

Это выход 'gcc -O0', правильно? В противном случае это оптимизировалось бы на 'return 0'. Намного интереснее смотреть на * оптимизированный * вывод, создавая функцию, которая возвращает значение, основанное на своих аргументах. [gcc 5.3 -O3] (http://goo.gl/YJBj7D) использует стратегию поиска таблиц для записей, отличных от значений по умолчанию, для реализации 'switch'. Так делает clang 3.7.1. Они улучшали бы код, используя нагрузки «movzx», поэтому записи в таблице должны были быть только 1 байт. Они также не могут воспользоваться тем, что 'x == y' для большинства нестандартных записей, что является проблемой. необычный для этого рисунка. –

ответ

7

ja - это трюк, чтобы сложить два подписанных чека в единую проверку без знака. Это эффективно делает if (x > 4 || x < 0), так что пройденные только 0-4, как и ожидалось.

Смещение на 2 бита масштабируется для размера указателя. Вы отключили следующую часть разборки, где я уверен, что вы увидите косвенный прыжок через таблицу. В этой таблице содержатся указатели размером 4 (по вашей архитектуре), поэтому индекс следует масштабировать на 4, что представляет собой сдвиг в 2 бита.

Смежные вопросы