Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #76, АПРЕЛЬ 2005 г.

Низкоуровневый кодинг

Крис Касперски ака мыщъх

Хакер, номер #076, стр. 076-116-2


Стек - это такой способ хранения данных. Что-то среднее между списком и массивом (читайте Кнута, он крут). Команда PUSH кладет новую порцию данных на верхушку стека, а команда POP – снимает ее оттуда. Это позволяет сохранять данные в памяти не заботясь об их абсолютных адресах. Очень удобно! Вызов функции и возврат из нее происходит как раз с помощью этого механизма. Команда CALL func забрасывает в стек адрес следующей за ней команды, а RET стягивает его оттуда. Указатель на текущую вершину стека хранится в регистре ESP, а дно… формально стек ограничен лишь протяженностью адресного пространства, а на самом деле - количеством выделенной ему памяти. Направление роста стека: от больших адресов - к меньшим. Еще говорят, что он растет снизу вверх.

Вернемся к нашим баранам. Поговорим об основных в x86 регистрах. Ты наверняка видел в асм-листингах такие обозначения как EAX, EBX, ECX, EDX, ESI, EDI – это регистры общего назначения. Они могут свободно участвовать в любых математических операциях или операциях обращения к памяти. Их всего семь. Семь 32-разрядных регистров. Четыре первых из них (EAX, EBX, ECX и EDX) допускают обращения к своим 16-разрядным половинкам, хранящим младшее слово - AX, BX, CX и DX. Каждый из них в свою очередь делиться на старший и младший байты - AH/AL, BH/BL, CH/CL и DH/DL. Важно понять, что AL, AX и EAX это не три разных регистра, а разные части одного и того же регистра!

Регистр же, обозначение которого ты вряд ли мог встретить в листинге – это EIP, содержащий указатель на следующую выполняемую команду. Непосредственно он недоступен для модификации, но его можно изменить манипулируя инструкциями перехода (Jxx, CALL etc).

Существуют так же и другие регистры - сегментные, мультимедийные, регистры математического сопроцессора, отладочные регистры. Без хорошего справочника в них легко запутаться и утонуть, и, на первых порах мы их касаться не будем.

Из Си в Асм

Основной ассемблерной командой является MOV (пересылка данных), которую можно уподобить оператору присвоения. c = 0x333 из Си на языке ассемблера записывается примерно как MOV EAX, 333h (обрати внимание на разницу записи шестнадцатеричных чисел!). Можно так же написать MOV EAX, EBX (записать в регистр EAX значение регистра EBX).

Указатели заключаются в квадратные скобки. Сишное a = *b на ассемблере записывается как MOV EAX, [EBX]. При желании, к указателю можно добавить смещение: a = b[0x66] эквивалентно MOV EAX, [EBX + 0x66].

Переменные объявляются директивами DB (переменная в один байт), DW (переменная в одно слово), DD (переменная в двойное слово) и т.д. Знаковость переменных при их объявлении не указывается. Одна и та же переменная в различных участках программы может интерпретироваться и как число со знаком и как число без знака.

Для загрузки переменной в указатель применяется либо команда LEA, либо MOV с директивой offset.

Назад на стр. 076-116-1  Содержание  Вперед на стр. 076-116-3