LINUX.ORG.RU

Как портировать немного 16-битного кода доса в линукс?


1

4

Для примера, есть немного кода 8086, который охота хоть как-то завести под линуксом на современных машинах.

019C jc   000001B0
019E sar  ax,07
01A1 add  ax,7D60
01A4 add  di,ax
01A6 mov  al,[si]
01A8 dec  byte [si]
01AA cmp  al,es:[di]
01AD jle  01B0
01AF stosb

Само собой, код получен декомпиляцией. В полном варианте более 1500 строк и я замучился разматывать клубок из графа с сотнями переходов. Пока вижу 3 варианта:

1. написать что-то среднее между транслятором и эмулятором в си, т.е. к примеру mov al,[si] транслируется в al=data[si], но во-первых, при таком подходе нужно эмулировать все-все регистры, а во-вторых, при использовании более сложных команд, эмулировать все-все флаги, а их до чертиков и не факт что они испльзуются. Опять же, даже mov может транслироваться сразу в data[di]=al;data[di+1]=ah;, что уже не так тривиально. На лапшу из goto в общем-то все равно, охота запустить «как есть».

2. написать транслятор в inline asm, который подсунуть GCC, в гугле есть варианты сборки ассебмлера с интелевским синтаксисом, но я не очень понимаю что будет с сегментами данных, стеком и прочими вещами, в учебнике к GCC говорят что интелевский синтаксис плохо, а AT&T хорошо, а вот про стек ничего не нашел.

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

IDA генерит граф, местами помечает красным «я тут не смогла», HexRays говорит что 16-битный код не умеет, REC валится на этапе анализа, DCC не очень понятно как использовать.

Какие варианты?

а что за код-то? Неужели написать заново не быстрее будет?

gavlig ★★★
()
Ответ на: комментарий от Harald

а он прерывания дёргает?

Дергает, но в принципе, это дерганье можно вырезать. Вот с таймерами не очень ясно, оно свой обработчик вешает, но думаю вырезать реально и это

nogaemz
() автор топика
Ответ на: комментарий от nogaemz

Может быть проще и дешевле нанять того кто сможет распутать и переписать.И только в случае совсем отчаянья пытаться погружаться в такую дикую безну некрофилии.

GNU-Ubuntu1204LTS ★★★
()
Ответ на: комментарий от ziemin

Если это тонкий намек на портирование под синтаксис AT&T, то вас следует посадить за пропаганду самоубийств

nogaemz
() автор топика

что эта программа хоть делает, если не хочешь запускать ее из dosemu?

dikiy ★★☆☆☆
()
Ответ на: комментарий от ziemin

Если это намек на прерывания, то как я выше написал, вырезать их можно, нужный кусок кода, который я пытаюсь вытащить, работает сам по себе

nogaemz
() автор топика
Ответ на: комментарий от nogaemz

Не томи душу, скажи хоть что там за секретный супер оптимизированный инновационный функционал?

anonymous
()
Ответ на: комментарий от nogaemz

Самая большая проблема в модели памяти. Если все значения сегментов константные, то можно, в принципе, руками все инструкции, в которых сегменты упоминаются, поправить. А если неконстантные, то будет геморрой.

Q3164
()

Второй путь не выглядит чем-то сверхестественным, первый тоже вполне реален. Но лучше найми профессионала.

unC0Rr ★★★★★
()

IDA генерит граф, местами помечает красным «я тут не смогла», HexRays говорит что 16-битный код не умеет, REC валится на этапе анализа, DCC не очень понятно как использовать.
Какие варианты?

Можно еще не просто смотреть на дизасм и гадать что оно делает, а запустить это дело под отладчиком в эмуляторе и проследить работу. И по ходу помечать нужные места. Когда станет понятна логика проще будет восстановить код.

anonymous
()

Правильнее, конечно, отреверсить логику, но если сильно ломает, проще, думаю, идти по первому пути. Можно попробовать реверсить по кускам, патча оригинальный бинарь уже понятым и переписанным кодом.

GAMer ★★★★★
()

берешь питон и питонишь на нем необходимый функционал старой проги. Профит

anonymous
()

Я за первый вариант. Над мелкими оптимизациями вроде соединения двух обращений к массиву в один корпеть смысла нет, компилятор с этим справится. В эмуляции всех регистров тоже страшного ничего нет, union помогает. С флагами нужно повозиться всего один раз, тем более для 16-битного кода на 32-битной машине можно даже проверять их напрямую, не выдумывая хитрых формул.

i-rinat ★★★★★
()

Немного в сторону но может пригодится.

Где-то полгодика назад я загорелся такой идеей - перенести пошаговую стратегию MAX (DOS игра) из бинарников на язык C++ в Linux. Связано это было с тем, что мало того что в DOSBOX игра время от времени тормозила, так где-то после 10 ходов она ещё и вылетала. Видимо программисты-разработчики игры не все ошибки в игре исправили :)

В связи с чем и написал программку, которая «запускает» и дизассембилирует её в C подобный код, стараясь корректно разбить код на функции. Получая приблизительно такой код:

FUNC_INFO_V4(0x10076884, 0x78942246fba1d8bc, 0x20, {0x68, 0x28, 0, ... /* бинарный код функции */ })
{
	FUNC_START_V2(0x10076884, 0x20);
	II(0x10076884, 0x5)   pushd(0x28);                          /* push dword 0x28 */
	II(0x10076889, 0x5)   calld(check_available_stack_size, 0xef4c4); /* call 0x10165d52 */
	II(0x1007688e, 0x1)   pushd(ebx);                           /* push ebx */
	II(0x1007688f, 0x1)   pushd(ecx);                           /* push ecx */
	II(0x10076890, 0x1)   pushd(edx);                           /* push edx */
	II(0x10076891, 0x1)   pushd(esi);                           /* push esi */
	II(0x10076892, 0x1)   pushd(edi);                           /* push edi */
	II(0x10076893, 0x1)   pushd(ebp);                           /* push ebp */
	II(0x10076894, 0x2)   mov(ebp, esp);                        /* mov ebp, esp */
	II(0x10076896, 0x6)   sub(esp, 0xc);                        /* sub esp, 0xc */
	II(0x1007689c, 0x3)   mov(memd_a32(ss, ebp - 0x4), eax);    /* mov [ebp-0x4], eax */
	II(0x1007689f, 0x3)   mov(eax, memd_a32(ss, ebp - 0x4));    /* mov eax, [ebp-0x4] */
	II(0x100768a2, 0x3)   cmp(memd_a32(ds, eax), 0);            /* cmp dword [eax], 0x0 */
	II(0x100768a5, 0x2)   jzd(0x100768b0, 0x9);                 /* jz 0x100768b0 */
	II(0x100768a7, 0x7)   mov(memd_a32(ss, ebp - 0x8), 0);      /* mov dword [ebp-0x8], 0x0 */
	II(0x100768ae, 0x2)   jmpd(0x100768c9, 0x19);               /* jmp 0x100768c9 */
l_0x100768b0:
	II(0x100768b0, 0x5)   mov(ecx, 0xae);                       /* mov ecx, 0xae */
	II(0x100768b5, 0x5)   mov(ebx, 0x101a0018);                 /* mov ebx, 0x101a0018 */ /* "smartptr.h" */
	II(0x100768ba, 0x5)   mov(edx, 0x101a0023);                 /* mov edx, 0x101a0023 */ /* "ptr != 0" */
	II(0x100768bf, 0x2)   xor_(eax, eax);                       /* xor eax, eax */
	II(0x100768c1, 0x5)   calld(assert_, 0xef4cc);              /* call 0x10165d92 */
	II(0x100768c6, 0x3)   mov(memd_a32(ss, ebp - 0x8), eax);    /* mov [ebp-0x8], eax */
l_0x100768c9:
	II(0x100768c9, 0x3)   mov(eax, memd_a32(ss, ebp - 0x4));    /* mov eax, [ebp-0x4] */
	II(0x100768cc, 0x2)   mov(eax, memd_a32(ds, eax));          /* mov eax, [eax] */
	II(0x100768ce, 0x3)   mov(memd_a32(ss, ebp - 0xc), eax);    /* mov [ebp-0xc], eax */
	II(0x100768d1, 0x3)   mov(eax, memd_a32(ss, ebp - 0xc));    /* mov eax, [ebp-0xc] */
	II(0x100768d4, 0x2)   mov(esp, ebp);                        /* mov esp, ebp */
	II(0x100768d6, 0x1)   popd(ebp);                            /* pop ebp */
	II(0x100768d7, 0x1)   popd(edi);                            /* pop edi */
	II(0x100768d8, 0x1)   popd(esi);                            /* pop esi */
	II(0x100768d9, 0x1)   popd(edx);                            /* pop edx */
	II(0x100768da, 0x1)   popd(ecx);                            /* pop ecx */
	II(0x100768db, 0x1)   popd(ebx);                            /* pop ebx */
	II(0x100768dc, 0x1)   retd();                               /* ret  */
}

В общем то в таком виде я и получил более менее работающий код. Где-то 500000 строчек. Тратить время на полноценный графический интерфейс желания у меня не было (на данном этапе это не удобно), т.ч. она запускается в режиме автоматического боя компьютер против компьютера и сохраняет сами картинки игры в png файлы.

Следующий логический шаг перенос всего этого непосредственно в C++ - в процессе.

Да и к чему я это всё пишу - уверен, смогу ваш код портировать под Linux, опыт то получен. Но не бесплатно.

Micky53
()
Ответ на: комментарий от Micky53

Ах да, и ещё. Сам код я могу дать бесплатно, у меня в общем то и так было желание распространять его на правах «общественно достояния». Но т.к. проект до ума ещё не доведён и пока что жёстко заточен под эту игру, я его пока никуда не выкладывал. И думаю самостоятельно (без меня) его будет использовать проблематично.

Micky53
()
Ответ на: комментарий от Micky53

Скажите, а вы бы заплатили за реверсинг-портирование игры? Вот и я бы не стал, я это делаю ради фана игр, а не коммерческой выгоды. В худшем случае, я просто ничего не сделаю.

nogaemz
() автор топика
Ответ на: комментарий от wingrime

В принципе, генератор огромных портянок из goto уже написан, граф вызовов известен, проблема в том, что надо реализовать все команды. Причем надо тщательно разбирать, где у нас word, а где byte, придумать какой-то свой слой работы с сегментами памяти, а вот этого я не умею. По первости кажется что inc можно реализовать 1 строчкой var++, а на самом деле писанины куда больше

nogaemz
() автор топика
Ответ на: комментарий от anonymous

Я не знаю как этот функционал устроен, иначе бы я написал это на нормальном языке сразу, даже питон бы не понадобился

nogaemz
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.