gugumaa | 195.113.79.10/10.0.10.* | 11.9.2008 15:26 |
| Co mi v článku chybí:
1) Co je původně mezi 010022AC a 010022B2 - t.j. v oblasti, kterou jsme vyplnili NOPy?
Pokud tam byl nějaký kód - to nikomu nevadí, že jsme ho smazali?
Tady by se hodilo poučit o délce instrukcí, protože podobné kejkle se potom dělají i ve volání WM_COMMAND a i začátečníkovi by mělo být jasné, proč jsou počty NOPů takové, jaké jsou.
2) Co se stalo s kódem od 010022B2?
V článku se píše "na konci souboru, zbytek vyplníme NOPy", čímž bych rozuměl až do konce - tedy i přes 010022B2. Nebo kde vlastně soubor končí?
Souvisí s bodem 1 - ta formulace "na konci souboru, zbytek vyplníme nulami" je prostě ne-li nepřesná, tak úplně blbá a zavádějící.
3) Nepovažuju za rozumné měnit v rutině na 010022A1 naprostou většinu původního obsahu - provedené změny by měly být co nejmenší. Vzhledem k tomu, že od adresy 01004A80 stejně následuje hned PUSH 1F4:PUSH DWORD PTR DS:[1005B30]:CALL, považoval bych za mnohem menčí změnu změnit jen cíl callu na adrese 22AC (případně ho nahradit jumpem na 01004A80), kde by číhal rovnou CALL.
Tady je potřeba vysvětlit, že "mezicallem" se mění obsah zásobníku (místo očekávaných parametrů funkce
LoadMenuW se tam ocitá návratová adresa na 010022B2, proto asi autor volil řešení "nejdřív odskok, a pak pushe", čímž se návratová adresa ocitne pod parametry (za předpokladu, že na zásobníku nejsou předpřipravené ještě jiné parametry pro tuto funkci - zjevně ale ne). Řešení s jumpem by ale zásobník neměnilo a náhradní kód na adrese 01004A80 by byl o dvě instrukce (celých dlouhých 11 bajtů) kratší!
A není snad ani potřeba NOPovat původní kód.
4) U zpracování WM_COMMAND je znovu vidět chybějící poučení o délce instrukcí - proč zrovna 4 NOPy? Proč se zrovna první dvě instrukce stěhují někam jinam?
Odpověď rovnou předestřu - protože nemáme žádný call, přepsáním jehož cíle bychom mohli odskočit, proto hned první instrukci callem nahradíme a odsuneme za call. Protože ale první instrukce má jen 4 bajty (3 + parametr), 5 bajtů (ten aktuálně použitý 1 + 4 parametr), přepsala by se o jeden bajt i část následující instrukce - ta má 5 bajtů. Je tedy nutno ji taky přesunout a zbývající 4 bajty vynopovat.
Nebo - a to bych asi zvolil já - první instrukci nechat, za ní pak pětibajtovou instrukci nahradit pětibajtovým odskokem, a přestěhovat jen druhou instrukci.
Ušetří se tím 4 bajty místa, které pak nemusíme přesouvat!
Pokud si říkáte, že při 4 GB RAM v počítači jsou nějaké 4 bajty zanedbatelné, pak možná. Pokud se ale v něčem rejpu, pak se snažím, aby to nebylo větší, než původní kód, a pokud ano, tak být setsakra opatrný, kam vlastně svoje data cpu. Navíc omezená velikost segmentu zůstává zachována při libovolných velikostí RAMěti!
5) není vysvětleno, proč si schováváme AD před voláním InvalidateRect, i.e., co vlastně schováváme a co po volání Invalidate Rect toto AD potřebuje.
Když už jsou v kódu dvě instrukce oproti komentáři "navíc", hodí se vědět, proč.
6) Proč není použito LOOP?
Nebylo by kratší, než DEC, CMP, JNZ?
|
|