2016-11-11 5 views
-2

Мне нужно перестроить инструкцию switch в C из сборки. Когда я компилирую с использованием флага -S, чтобы получить код сборки из C i, это неверно. Любое понимание того, что я делаю неправильно?Обратное проектирование оператора switch в C с узла x86

Заранее благодарен!

Это сборка

.file "switch_prob-soln.c" 
.text 
.globl switch_prob 
.type switch_prob, @function 
switch_prob: 
.LFB0: 
.cfi_startproc 
subq $50, %rsi 
cmpq $5, %rsi 
ja .L2 
jmp *.L7(,%rsi,8) 
.section .rodata 
.align 8 
.align 4 
.L7: 
.quad .L3 
.quad .L2 
.quad .L3 
.quad .L4 
.quad .L5 
.quad .L6 
.text 
.L3: 
leaq 0(,%rdi,4), %rax 
ret 
.L4: 
movq %rdi, %rax 
sarq $2, %rax 
ret 
.L5: 
leaq (%rdi,%rdi,2), %rdi 
.L6: 
imulq %rdi, %rdi 
.L2: 
leaq 10(%rdi), %rax 
ret 
.cfi_endproc 
.LFE0: 
.size switch_prob, .-switch_prob 
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3" 
.section .note.GNU-stack,"",@progbits 

это CI написал

long switch_prob(long x, long n){ 
    long result = x; 
    switch(n){ 

     case 50: 
     case 51: 
     result + 4; 
     break; 

     case 52: 
     result >> 2; 
     break; 

     case 53: 
     result + result + 2; 

     merge: 
     result * result 
     break; 

     default: 
     result * 10; 
     break; 
    } 
    return result; 
    } 
+3

Помимо того, что 'длинный результат - х;' это ничего не значит, и ни один из ваших вычислений не имеют каких-либо побочных эффектов, вы также имеют функцию, определенную внутри функции, которая не является C. – jxh

+0

* «... это неверно». * Как? Вы не объяснили, что представляет собой настоящая проблема. – user694733

+0

Вы должны скомпилировать свой код C как 'gcc -Wall -S -O -fverbose-asm', и вам нужно улучшить код, пока не получите никаких предупреждений. Обратите внимание: 'result * 10;' (от 4-й до последней строки) не имеет наблюдаемого побочного эффекта, поэтому его можно оптимизировать и удалить. Возможно, вы имеете в виду «return result * 10;» вместо этого, но это только предположение. –

ответ

0

Просто следуя логике кода сборки, я что-то вроде угадывания:

int switch_prob(int x, int n) { 
    int result = x; 

    switch (n - 50) { 

     case 0: 
     case 2: 
      result += 4; 
      break; 

     case 3: 
      result >>= 2; 
      break; 

     case 4: 
      result += 2; 

     case 5: 
      result *= result; 
      break; 

     default: 
      result += 10; 
    } 

    return result; 
} 

Один из способов проверить ваше решение - написать программу драйвера, например:

test.c

#include <stdio.h> 

int switch_prob(int x, int n); 


int main() { 

    printf("%d\n", switch_prob(1, 54)); 

    return 0; 
} 

А затем скомпилировать код сборки, если она совместима с вашей системой, с драйвером:

gcc -Wall test.c switch_prob-soln.s 

Затем отредактируйте файл test.c изменения аргументов до switch_prob(), чтобы проверить, сохраняются ли ваши предположения. Я предполагаю, что таблицу переходов говорит нам о случаях:

.quad .L3 # case 0: addition (LEA) 
.quad .L2 # default: (no case 1:) addition (LEA) 
.quad .L3 # case 2: is case 0: again 
.quad .L4 # case 3: right shift (SAR) 
.quad .L5 # case 4: addition (LEA) 
.quad .L6 # case 5: multiplication (IMUL) 
+0

Это было полезно, спасибо! Я обязательно попробую это сделать –

+0

один последний вопрос, я знаю, что lea может использоваться для операций, как это было здесь, но я также читал, что это по существу способ переместить что-то из одного индекса в другой, например, в массив, или я это неправильно интерпретирую? (извините, я очень новичок в сборке, и логичный прыжок из OO мне тяжело). –