Итак, для начала необходимо создать подпрограммы инструкций, таких как "+"," >" и т.д.
Оператор ">" что означает сдвиг ленты в право:
Оператор "<" что означает сдвиг ленты в лево:I_Plus proc i:DWORD mov eax, i ; копируем в eax значение i inc eax ; увеличиваем его на 1 ret I_Plus endp
Оператор "+" что означает увеличение текущей ячейки на 1:I_Minus proc i:DWORD mov eax, i ; копируем в eax i dec eax ; уменьшаем eax на 1 ret I_Minus endp
Оператор "-" что означает уменьшени текущий ячейки на 1:Arr_Plus proc arr_i:DWORD mov eax, arr_i ; скопировать ядрес ячейки в eax inc BYTE ptr [eax] ; увеличить ячейку на 1 ret Arr_Plus endp
Оператор "." что означает запись значения ячейки в какоето место:Arr_Minus proc arr_i:DWORD mov eax, arr_i ; копируем в eax адрес текущей ячейки dec BYTE ptr [eax] ; уменьшаем на 1 ret Arr_Minus endp
Оператор "," что означает запись значения откудато в текущую ячейку:Putchar_Arr_i proc uses eax ebx arr_i:DWORD, out_addr:DWORD mov eax, DWORD PTR [arr_i] ; помещаем в eax адрес текущей ячейки mov al, BYTE PTR [eax] ; помещаем в al значение ячейки mov ebx, out_addr ; помещаем в ebx адрес места куда пишем mov BYTE PTR [ebx], al ; записываем значение ячейки ret Putchar_Arr_i endp
Оператор "[" что есть начало цикла:Getchar_Arr_i proc uses eax ebx arr_i:DWORD, inn_addr:DWORD mov eax, arr_i ; копируем в eax адрес текущей ячейки mov bl, BYTE PTR [inn_addr] ; в bl копируем значение из источника mov BYTE PTR [eax], bl ; в текущую ячейку копируем значение bl ret Getchar_Arr_i endp
Оператор "]" что есть конец цикла:While_Start proc uses eax ebx ecx arr_i:DWORD, buf_arr:DWORD mov eax, buf_arr ; копируем в eax адрес счетчика mov ebx, arr_i ; в ebx копируем адрес текущей ячейки mov ecx, -1h ; сделаем почти бесконечный цикл .if BYTE PTR [eax] != 0h ; проверяем, в счетчике у на 0? jmp while_sover ; если 0 то цикл завершен .endif search_end: .if BYTE PTR [ebx] == D_WSTOP ; если нашли закрытие цикла jmp while_sover ; выходим .endif inc ebx ; иначе двигаемся по ленте loop search_end ; повторяем пока не найдем символа закрытия цикла while_sover: ret While_Start endp
Основное тело программы:While_End proc uses eax ebx ecx arr_i:DWORD, buf_arr:DWORD mov eax, buf_arr ; копируем в eax адрес счетчика mov ebx, arr_i ; в ebx копируем адрес текущей ячейки mov ecx, -1h ; сделаем почти бесконечный цикл .if BYTE PTR [eax] == 0h ; проверяем, в счетчике у нас 0? jmp while_eover ; если 0 то цикл завершен .endif search_start: .if BYTE PTR [ebx] == D_WSTART ; если нашли открытие цикла jmp while_eover ; выходим .endif dec ebx ; иначе двигаемся по ленте в лево loop search_start ; повторяем пока не найдем символа открытия цикла while_eover: mov edi, ebx ; меняем указатель на текущую оперциюю ret While_End endp
В принципе вот и все, достаточно не сложно. Такую простоенькую машину можно использовать для скрытия например другова алгоритма, например расчета серийника или некого алгоритма.VM_Body proc vm_code:DWORD, out_addr:DWORD pusha ; сохраним все регистры(пусть будут) mov edi, vm_code ; в edi у нас будет указатель на текущую инструкцию mov ecx, -1 ; делаем опять почти бесконнечный цикл mov eax, offset buf ; в eax у нас буфер mov ebx, out_addr ; в ebx место куда будет выводится результат add edi, 4h ; сместим указатель на начала данных(сделано для получения размера) start_parse: .if BYTE PTR [edi] == D_PLUS_I ; Если встретили ">" invoke I_Plus, eax ; вызвали обработку ">" jmp nextiter ; обработка следующего символа .endif .if BYTE PTR [edi] == D_MINUS_I ; Если встретили "<" invoke I_Minus, eax ; вызвали обработку "<" jmp nextiter ; обработка следующего символа .endif .if BYTE PTR [edi] == D_ARR_PLUS ; Если встретили "+" invoke Arr_Plus, eax ; вызвали обработку "+" jmp nextiter ; обработка следующего символа .endif .if BYTE PTR [edi] == D_ARR_MINUS ; Если встретили "-" invoke Arr_Minus, eax ; вызвали обработку "-" jmp nextiter ; обработка следующего символа .endif .if BYTE PTR [edi] == D_PUT ; Если встретили "." invoke Putchar_Arr_i, eax, ebx ; вызвали обработку "." inc ebx ; переключились на следующий символ jmp nextiter ; обработка следующего символа .endif .if BYTE PTR [edi] == D_GET ; Если встретили "," invoke Getchar_Arr_i, eax, ebx ; вызвали обработку "," jmp nextiter ; обработка следующего символа .endif .if BYTE PTR [edi] == D_WSTART ; Если встретили "[" invoke While_Start, edi, eax ; вызвали обработку "[" jmp nextiter ; обработка следующего символа .endif .if BYTE PTR [edi] == D_WSTOP ; Если встретили "]" invoke While_End, edi, eax ; вызвали обработку "]" jmp nextiter ; обработка следующего символа .endif nextiter: inc edi ; переходим на следующую команду .if edi >= offset output ; обнаружили конец P кода jmp goout ; завершаем программу .endif loop start_parse ; обрабатываем след символ goout: popa ; востанавливаем регистры ret VM_Body endp
Комментариев нет:
Отправить комментарий