Ссылки на структуры и классы
Поскольку структуры и классы играют значительную роль в Windows-разработках, потратим некоторое время на обсуждение проблем доступа к соответствующей памяти. Хотя со структурами и классами удобно иметь дело на языках высокого уровня, на уровне языка ассемблера они, вообще говоря, не существуют. На языках высокого уровня структура и класс — это просто краткие способы указывать смещения в "блобе" памяти.
"Блоб" (Binary Large Object — BLOB). Во-первых, этим термином разработчики баз данных обозначают любой произвольный битовый блок, который следует сохранить в БД, например картинку или звуковой файл. Существенно, что BLOB является объектом, который не может быть интерпретирован средствами СУБД. Во-вторых, употребляется в значении глагола (to blob) и в этом случае переводится как "послать огромный e-mail", обычно в ответ на нанесенное серьезное оскорбление. Часто используется в качестве умеренной угрозы. Например: "If that program crashes again, I'm going to BLOB the core dump to you" (Если эта программа опять "грохнется", я тебе вышлю дамп ядра по мэйлу). См. Файл Жаргона (The Jargon File). -Ред.
Компиляторы, в основном, размещают память для пользовательских структур и классов так, как указано в спецификациях. Иногда компилятор дополняет поля заполнителями, чтобы сохранять их на естественных границах памяти, которые для CPU x86 кратны 4 или 8 байтам.
Ссылки на структуры и классы обозначаются регистром и смещением памяти. В структуре Mystruct, приведенной ниже, комментарии справа показывают смещение каждого элемента от начала структуры. За определением MyStruct расположены различные способы доступа к полям структуры.
typedef struct tag_MyStruct
{
DWORD dwFirst ; // 0-байтное смещение
char szBuff[ 256 ] ; // 4-байтное смещение
int iVal ; // 260-байтное смещение
} MyStruct , * PMyStruct ;
void FillStruct ( PMyStruct pSt )
{
char szName[] = "Pam\n" ;
_asm
{
MOV EAX , pSt // Поместить pSt в EAX.
Ниже используются прямые
// смещения на языке ассемблера, чтобы показать,
// на что они похожи в дизассемблере.
// Встроенный ассемблер позволяет применять
// нормальные ссылки формата <struct>.<field>.
// С-код: pSt->dwFirst = 23 ;
MOV DWORD PTR [EAX] , 17h.
// С-код: pSt->iVal = 0x33 ;
MOV DWORD PTR [EAX + 0104h] , 0x33
// С-код: strcpy ( pSt->szBuff , szName ) ;
LEA ECX , szName // Поместить szName в стек.
PUSH ECX .
LEA ECX , [EAX + 4] //. Получить доступ к полю szBuff.
PUSH ECX
CALL strcpy
ADD ESP ,8 // strcpy есть _cdecl функция.
// С-код: pSt->szBuff[ 1 ] = 'A' ;
MOV BYTE PTR [EAX + 5] , 41h
// С-код: printf ( pSt->szBuff ) ;
MOV EAX , pSt // Получить pSt обратно. EAX был разрушен
// при обращении к strcpy.
LEA ECX , [EAX + 4]
PUSH ECX
CALL DWORD PTR [printf]
ADD ESP , 4 // printf есть _cdecl-функция.
}
}