14.Testujemy samomodyfikujący się program.
Postanowiłem sprawdzić jak będą działać programy modyfikujące swój kod.
W przypadku nowszych procesorów (Athlon,Duron) anomalii nie było, ale na starym 386SX-LT(Amd) to już nie zawsze program działał jak powinien. Nie wiem czy wszystkie 386 tak działają czy tylko mój więc macie okazję sprawdzić.
W katalogu R5 są pierwsze programy testujące zachowanie się procesora.Jest tam plik bat z komentarzami do odpalenia wszystkich programów.
Program wstawia sobie w środek RET więc powinna wykonać się tylko połowa programu (jeden pasek na ekranie a nie dwa)
Pierwsze wnioski są takie, że po zmianie jakiegoś kodu musi być:
rozkaz hlt,
lub jump (krótki wystarczy)
lub przynajmniej 10 bajtów programu.
Jak wykazały dalsze próby czasem może być mniej jak się przestawi inne wcześniejsze rozkazy.
W katalogu R6 dalsze próby, tu zmieniałem kolejność niektórych rozkazów. Najpierw dałem te działające u mnie a potem te niedziałające, ale warto odpalić je kilka razy bo niektóre raz działają dobrze a raz nie.
Całkiem ciekawe jest że wstawienie sprawdzania czy się kod zmienił w pamięci działa dziwnie -
jak widać w R5CMP.com procesor najwidoczniej porównuje dane w cache-u, gdyż wykonuje program po staremu.
mov dl,[r1] ; pobieramy RET
mov [r2],dl ; wstawiamy w miejsce mov
c: cmp dl,[r2] ;porównujemy czy napewno się zmieniło
jne c
r2: mov di,84 ; a program sobie dalej leci
(...)
r1: ret
Na koniec zrobiłem jeszcze sprawdzenie czy ten zmieniony bajt trafia do pamięci - okazuje się że tak. Programy te są w katalogu R8.
Używałem fasmlite z flatassembler.net oraz dissasamblera ndisasm z nasm.us Para tych programów będzie też bohaterem następnej części.
=============================================================================
15.Piętnastobajtowy rozkaz procesora w dosie (Real-Mode)
Programy na procesorach x86 mogą być maksymalnie 15 bajtowe - niestety nie było przykładu takiego programu więc musiałem sam napisać.
W katalogu opc15 jest max15.com; Odpalamy go w ms-dosie; Pokażą się 2 kolorowe znaczki na ekranie - to znaczy rozkaz ten że działa.
No nie jest tak pięknie, ale po kolei...
Program miał coś wrzucić na ekran jednym rozkazem. Na początek użyłem adresu B8000h bo czemu nie? No niestety program taki zachowywał się dziwnie bo
albo się wieszał albo działał. Po wieku próbach skojarzyłem, że po uruchomieniu fasmlite działają, a po disasm nie, także pod windows powodują zatrzymanie programu oraz pokazują błąd właśnie na tym rozkazie gdzie jest ten adres.
Problematyczny więc był 32bitowy adres - jeśli był większy niź 0000FFFF to były problemy, jak nie był to zawsze było OK.
Rzućcie okiem na wydruk z ndisasm:
00000000 6631DB xor ebx,ebx
00000003 6631FF xor edi,edi
00000006 8EE3 mov fs,bx
00000008 BB00B8 mov bx,0xb800
0000000B 8EC3 mov es,bx
0000000D BB0300 mov bx,0x3
00000010 BF0000 mov di,0x0
00000013 F026676681449F04 lock add dword [dword es:edi+ebx*4+0x4],0x35353131
-31313535
0000001F F026676681849F04 lock add dword [dword es:edi+ebx*4+0x104],0x34343232 - tu OK bo adres 0000xxxx
-01000032323434
0000002E F064676681845F02 lock add dword [dword fs:edi+ebx*2+0xb8002],0x6b4b694f - ten rozkaz powoduje błąd (pod windowsami,pod dosem czasem działał)
-800B004F694B6B
0000003D C3 ret
Okazuje się że w RealMode nie można stosować adresów większych od FFFF bo procesor tego nie przyjmie, ale dlaczego po fasmlite działał (pod dosem)? Wyczytałem że jest coś takiego jak Unreal-mode wtedy można używać dowolny adres większy niż FFFF (nie opiszę co to dokładnie ten Unreal-mode bo sam tego nie rozumiem).Fasmlite widocznie z niego korzysta i dlatego po nim wszystko działało. Za to ndisasm psuł wszystko (ten wymaga cwsdpmi więc wchodził w protected-mode).
Na początku chciałem zrobić program składający się tylko z 2 linijek: tego długiego rozkazu no i oczywiście RET. (Zapomniałem, że do do adresu trzeba
jeszcze dodać segment*16) więc napisałem program mini15.exe generujący kod programu z tak dobranym adresem aby zawsze wyszło b8000 (początek ekranu) i w lewym górnym rogu pojawiły jakieś się znaki. Po jego asemblacji mamy program z 16-bajtowy program. Oczywiście wymaga to zerowych wartości EAX i EBX aby coś wyświetlił oraz UnrealMode akurat bezpośrednio po użyciu fasmlite mamy co potrzeba. Dołożyłem zeruj.com, który zeruje 32 bitowe rejestry - można użyć w razie potrzeby;Wyższe słowa rejestrów nie zawsze zawierają zera (ms-dos jest tylko 16 bitowy ale nigdy nie wiadomo co inne programy tam zostawiają).Programem reg.com można sprawdzić co jest domyślnie w rejestrach po załadowaniu programu *.com - jest to przerobiony yourhelp.com ze strony fysnet.net.
W katalogu opc15 znajduje się:
- max15.com - (ten program zawiera "15-bajtowca" zawsze zadziała, pod win 9x też, no może poza win7)
- mini15.exe - ten program wygeneruje opc15.asm (16 bajtowy program działający na komputerze na którym został wygenerowany)
- po poleceniu fasmlite opc15.asm otrzymamy opc15.com
- reg.com pokazuje zawartość rejestrów
- zeruj.com przydaje się czasem przed odpaleniem opc15.com