Нашёл я описание этого замечательного языка http://catseye.tc/projects/smith/doc/smith.html и решил что-то не сложное на нём написать. Программа ест 400 метров памяти, работает секунд 10, но всё же находит все простые числа от 2 до 10000. Код (Text): include '%fasminc%\win32ax.inc' section '.text' code readable writeable executable N = 10000 ;до какого числа искать простые(для N=10000 требуется примерно 400Мб памяти) M = $18000000;сколько выделить памяти start: mov ebx,buf ;сюда складывае простые числа mov ebp,2 ;первое проверяемое число mov esi,l1s-1 ;указатель на текущий блок, чтобы знать откуда копировать std l1s: ;esi будет указывать на конец первого цикла(вернее текущей итерации) add esi,l1e-l1s ;если ebp>=N то затираем тело первого цикла NOP'ами cmp ebp,N cmc sbb ecx,ecx mov edi,esi and ecx,l1e-l1b-1 inc ecx mov al,90h rep stosb nop l1b: push ebx ;сохраняем перед началом второго цикла ;копируем всё начиная с метки l1s чтобы первый цикл мог выполниться еще раз add esi,prog_end-l1e lea edi,[esi+l1e-l1s] mov ecx,prog_end-l1s rep movsb add esi,l2s-l1s ;esi будет указывать на начало второго цикла nop l2s: add esi,l2e-l2s ;esi будет указывать на конец второго цикла sub ebx,4 ;если ebx<buf(больше не на что делить) то затираем тело второго цикла NOP'ами cmp ebx,buf sbb ecx,ecx mov edi,esi and ecx,l2e-l2b-1 inc ecx mov al,90h rep stosb nop l2b: ;делим ebp на очередное простое число mov eax,ebp xor edx,edx div dword [ebx] cmp edx,1 ;если разделилось нацело, то затираем тело второго цикла, ;а также, часть первого цикла, которая сохраняет новое простое число sbb ecx,ecx and ecx,l1f-l2c-1 inc ecx lea edi,[esi+l1f-l2e] mov al,90h rep stosb nop l2c: ;копируем всё с метки l2s чтобы еще раз выполнить второй цикл ;+l1e-l1s потому что у нас есть еще одна итерация первого цикла add esi,prog_end-l2e+l1e-l1s lea edi,[esi+l2e-l2s] mov ecx,prog_end-l2s+l1e-l1s rep movsb add esi,l2e-l2s ;esi будет указывать на конец второго цикла nop l2e: ;сохраняем ebp в списке простых чисел ;эта часть бедёт затёрта NOP'ами если ebp не простое pop ebx mov [ebx],ebp add ebx,4 push ebx nop l1f: pop ebx ;востанавливаем ebx inc ebp ;увеличиваем ebp add esi,l1e-l2e ;esi будет указывать на конец первого цикла nop l1e: add esi,l3s-l1e mov ebp,bufe-1 ;сюда будем записывать строку mov byte [ebp],0 l3s: dec ebp mov byte [ebp],' ' add esi,l3e-l3s sub ebx,4 ;если ebx<buf(больше нечего выводить) то затираем тело третьего цикла NOP'ами cmp ebx,buf sbb ecx,ecx mov edi,esi and ecx,l3e-l3b-1 inc ecx mov al,90h rep stosb nop l3b: mov eax,[ebx] ;очередное простое число ;копируем тело третьего цикла, чтобы вывести следующее число add esi,prog_end-l3e lea edi,[esi+l3e-l3s] mov ecx,prog_end-l3s rep movsb add esi,l4s-l3s nop l4s: ;делим eax на 10, цифру записываем в строку(ebp) add esi,l4e-l4s xor edx,edx mov ecx,10 div ecx add edx,'0' dec ebp mov [ebp],dl cmp eax,1 ;если частное 0, то затираем тело 4го цикла sbb ecx,ecx mov edi,esi and ecx,l4e-l4b-1 inc ecx push eax mov al,90h rep stosb pop eax nop l4b: ;копируем тело 4го цикла, чтобы вывести следующию цифру add esi,prog_end-l4e+l3e-l3s lea edi,[esi+l4e-l4s] mov ecx,prog_end-l4s+l3e-l3s rep movsb add esi,l4e-l4s nop l4e: l3e: cld invoke MessageBox,0,ebp,"primes",0 invoke ExitProcess,0 prog_end: rb M ;память для самомодификации проги .data buf rb N*4 ;с начала буфера записываем числа bufe: ;а с конца строку чтобы вывести .end start А теперь предлагаю порешать следующую задачку: 0) секцию кода размещаем первой, метку старт ставим на 401000h(это в целях упрощения сравнения программ) в конце секции резервируем 1Мб(думаю хватит) 1) в начале программы вызываем GetCurrentDirectory, строку кладём в секцию данных(4К для строки наверно хватит) 2) переставляем символы строки в обратном порядке (команд перехода не используем вообще, никаких функций здесь не вызываем, только копирование кода) 3) вызываем MessageBox(чтобы вывести строку с переставленными символами), а после него int3 (этот кусок тоже придётся копировать) Минимизировать нужно расстояние от инструкции int3 до метки с которой началось выполнение программы. Куски кода можно размещать в секции данных и копировать их оттуда, считаем только длину выполненного кода.
Код (Text): include 'win32axp.inc' section '.text' code readable writeable executable start: xor eax, eax mov ebx, dir push eax eax ebx eax invoke GetCurrentDirectory, ebx, ebx mov ecx, eax mov esi, l_from lea edi, [esi+l_to-l_from] rep movsd lea esi, [ebx-dir+l_msg] movsd movsd mov edi, ebx add ebx, eax l_from: dec ebx mov al, [edi] nop nop xchg [ebx], al stosb l_to: .end start rb 0x1000000 section '.data' data readable writeable l_msg: call [MessageBox] int3 nop dir rb 0x4000 Наверняка можно как-то сократить, но оставлю это для других желающих, а то мозг кипит уже..