Показать сообщение отдельно
  #1  
Старый 16.12.2012, 20:49
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию Отключить автоPush

Сразу опишу смысл патча.

В стеке проги когда eip = 4B4071 имеем следующее:
esp + 0: arg4 ; аргумент 4 для последующего вызова функции.

Мне же надо сделать так:
esp + 0: arg4
esp + 4: myVal1 // мои параметры
esp + 8: myVal2 // для дальнейшего вызова моей функции через много команд
Естественно, esp переедет на 8 байт вниз.

Делаю патчик:
Код:
void _cdecl ecxfixup()
{
	_asm
	{		
		// here is shadow push ebx
		mov [esp - 8], ebx
		mov ebx, [esp + 4 + 4]	// a4 for next call		
		mov [esp + 4 - 4], ebx		
		mov [esp + 4 + 4], ecx
		mov ebx, [esp + 4]
		mov [esp + 4 - 8], ebx
		mov ebx, [esp - 8]
		mov eax, [eax + 4]
		mov [esp + 4], eax
		lea esp, [esp - 4]
		
		// restore killed commands
		lea     eax, [esi + 54h]
		mov     ecx, esi
		ret
	}
}
...
*((DWORD *)0x4B4071) = 0xE8;  // call
*((DWORD *)0x4B4072) = (DWORD)&ecxfixup - 0x4B4076; 
Как видно, тут мне пришлось все адреса в стеке сдвигать на 4, потому что студия, увидев, что ebx используется внутри кода, взяла и запушила его сама:
Код:
:001A42C0 loc_1A42C0:
:001A42C0 push    ebx
:001A42C1 mov     [esp-8], ebx
:001A42C5 mov     ebx, [esp+8]
:001A42C9 mov     [esp], ebx
:001A42CC mov     [esp+8], ecx
:001A42D0 mov     ebx, [esp+4]
:001A42D4 mov     [esp-4], ebx
:001A42D8 mov     ebx, [esp-8]
:001A42DC mov     eax, [eax+4]
:001A42DF mov     [esp+4], eax
:001A42E3 lea     esp, [esp-4]
:001A42E7 lea     eax, [esi+54h]
:001A42EA mov     ecx, esi
:001A42EC retn
Но я-то ее не просил этого делать. Оно мне только мешает.
Вопрос: как в сях отключить автосохранение регистров при использовании асм-вставок? А то меня уже задолбало славливать баги в каждом третьем патче из-за того, что студия сама запушила регистр.
Самое интересное, что в каких-то случаях она НЕ сохраняет (по закону мерфи, конечно, не сохраняет только тогда, когда сохранять как раз надо).

З.Ы. суть в том, что один интерпретатор одного наркоманского скриптового языка имеет одно "замечательное" свойство: его разработчики забыли сделать обработку случая, когда функция возвращает строку. В этот момент интерпретатор падает с ошибкой. Я это пофиксил, добавив свой обработчик, но оптимизация интерпретатора убивает нужные мне значения, приходящие извне, в самом начале стандартного обработчика, а мой может вызваться только в конце работы стандартного. Спасает только вот такое вот решение.
И сохранять можно только в стеке, т.к. обработчики рекурсивные, рекурсия вызывается между убийством нужных значений и вызовом моего обработчика, следовательно, глобальные переменные не катят (они будут перезаписываться при каждой рекурсии).
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием