/*----------------------------------------------------------------------------*/ Верно, обращение по амперсанду выдаёт адрес переменной в памяти, обращение по имени - значение переменной. Точно так же, если к тебе пришёл адрес переменной, а ты хочешь получить значение из этого адреса - делаешь звёздочку: int foo = 0; // Объявляем переменную типа int с именем foo int* pFoo = &foo; // Объявляем указатель на int с именем pFoo, кладём в него // указатель на foo int bar = *pFoo; // Объявляем переменную типа int с именем bar и кладём в него //значение указателя pFoo В результате bar будет равно 0, то есть изначальному значению foo. То же самое, что и: int foo = 0; int bar = foo; Приведу ещё раз ассемблерную вставку из своего примера: __asm { push eax mov eax,[foo] inc eax mov [foo],eax pop eax } 0. Сохраняем регистр EAX в стек - мало ли, что там было до нашей функции. Вдруг важное?1. Кладём в EAX значение (не адрес!) переменной foo2. Увеличиваем eax на 13. Кладём в переменную foo новое значение То же самое, что и: foo++;или:foo += 1;или:foo = foo + 1; Дальше мы сообщаем в консоль значение foo и адрес foo в памяти. Если посмотреть этот код в отладчике, то увидим мы нечто такое: CPU DisasmAddress Hex dump Command 00023C0F |. 50 |PUSH EAX00023C10 |. A1 5C810200 |MOV EAX,DWORD PTR DS:[foo]00023C15 |. 40 |INC EAX00023C16 |. A3 5C810200 |MOV DWORD PTR DS:[foo],EAX00023C1B |. 58 |POP EAX Наша задача - как-то впихнуть в это место код, который скопирует EAX в какую-нибудь переменную, т.е. в какой-то другой адрес памяти. Вроде этого: CPU DisasmAddress Hex dump Command 00023C0F |. 50 |PUSH EAX00023C10 |. A1 5C810200 |MOV EAX,DWORD PTR DS:[foo]00023C15 |. 40 |INC EAX00023C16 |. A3 5C810200 |MOV DWORD PTR DS:[foo],EAX MOV [0x1234567],EAX00023C1B |. 58 |POP EAX Но просто так взять и записать кусок кода посреди программы мы не можем. Почему? Потому что компилятор - умный. И при компиляции весь код, переводя его в машинные инструкции (колоночка hex dump) кладёт их поближе друг к другу, но что самое важное - все переходы по коду (jmp, je, jne и так далее) осуществляются относительно текущего адреса. Следовательно, если порядок байт нарушить, впихнув лишних, то переходы, которые раньше ссылались на правильно заданные при компиляции места, начнут ссылаться в какую-нибудь далёкую страну, например SEG_FAULT. Приятный момент тут в том, что после компиляции в исполняемый файл код всегда будет лежать по одним и тем же адресам, т.е. адрес инструкции "MOV DWORD PTR DS:[foo],EAX" как был равен 0x00023C16, так там и останется. Нужно как-то впихнуть сюда ещё 5 байт (столько команда MOV и занимает вместе соперандами). Текущий код нельзя расширить, но можно поменять. Тут-то нам напомощь и спешит команда JMP. Стираем текущую команду MOV, вместо неё пихаем JMPна другой адрес, а там делаем так: MOV DWORD PTR DS:[foo],EAXMOV [0x1234567],EAXRET В итоге оригинальный код начинает выглядеть так: CPU DisasmAddress Hex dump Command 00023C0F |. 50 |PUSH EAX00023C10 |. A1 5C810200 |MOV EAX,DWORD PTR DS:[foo]00023C15 |. 40 |INC EAX00023C16 |. A3 5C810200 |JMP 0x123456700023C1B |. 58 |POP EAX Как такое сделать? Вот пример: