Я разобрал предоставленные вами байты и получил следующий код:
(__TEXT,__text) section
f:
00000000 movb 0x08(%esp),%cl
00000004 xorl %eax,%eax
00000006 testb $0xe0,%cl
00000009 jne 0x00000011
0000000b movl 0x04(%esp),%eax
0000000f shll %cl,%eax
00000011 retl $0x0008
Что, безусловно, сложнее, чем исходный код, предоставленный автором. Он проверяет, например, что второй операнд не слишком большой, чего нет в коде, который вы показывали вообще (см. «Правка 2» ниже для более полного анализа). Вот простая stdcall
функция, которая добавляет два аргумента вместе и возвращает результат:
mov 4(%esp), %eax
add 8(%esp), %eax
ret $8
Сборка, которая дает мне этот вывод:
(__TEXT,__text) section
00000000 8b 44 24 04 03 44 24 08 c2 08 00
Я надеюсь, что эти байты делают то, что вы от них хотите!
Редактировать: Возможно, более полезно, я просто сделал то же самое в C:
__attribute__((__stdcall__))
int f(int a, int b)
{
return a + b;
}
Скомпилированный с -Oz
и -fomit-frame-pointer
он генерирует точно такой же код (ну, в любом случае, функционально эквивалентный):
$ gcc -arch i386 -fomit-frame-pointer -Oz -c -o example.o example.c
$ otool -tv example.o
example.o:
(__TEXT,__text) section
_f:
00000000 movl 0x08(%esp),%eax
00000004 addl 0x04(%esp),%eax
00000008 retl $0x0008
Вывод машинного кода:
$ otool -t example.o
example.o:
(__TEXT,__text) section
00000000 8b 44 24 08 03 44 24 04 c2 08 00
Конечно, лучше, чем рукописный код сборки!
Редактировать 2:
@ Emtucifor спросил в комментариях ниже, что произойдет, если будет предпринята попытка сдвига 32 бит или более. Разобранный код в верхней части этого ответа (для байтов, представленных в исходном вопросе) может быть представлен следующим кодом более высокого уровня:
unsigned int shift_left(unsigned int a, unsigned char b)
{
if (b > 32)
return 0;
else
return a << b;
}
Из этой логики довольно легко увидеть, что если вы передадите значение больше 32 в качестве второго параметра функции сдвига, вы просто получите 0
обратно.