Отправляет email-рассылки с помощью сервиса Sendsay

Assembler - Просто и Эффективно.

  Все выпуски  

Assembler - Просто и Эффективно. Глава #4


Информационный Канал Subscribe.Ru


Assembler

Глава #4 - Оперативная память.

   Адресация памяти.

Каждая ячейка памяти имеет свой адрес - 32 битное смещение (в байтах) от начала сегмента. Сегмент определяется сегментным регистром (cs, ds, ss, es, fs, gs) и может указываться в командах при работе с памятью. Некоторые команды не поддерживают префикс замены сегмента.
Рассмотрим пример на основе команды mov.

  Пример:
mov eax,fs:[0] - поместить в регистр eax число из сегмента, селектор которого находится в регистре fs, со смещением от начала сегмента - 0.

Т.к eax - 32 битный регистр, то из памяти считывается 32 бита.
Нельзя использовать более одного операнда "память" в команде.
   -------------------------------
Смещение указывается в квадратных скобках, и может быть следующего формата: [Base+Index*{1,2,4,8}+число.] где Base - любой 32 битный регистр общего назначения, а Index - любой 32 битный регистр общего назначения кроме esp. Каждое из слагаемых может отсутствовать.

  Пример:
mov ecx,dword ptr [eax+ecx*4-10] ;поместить в ecx двойное слово по адресу eax+ecx*4-10
mov cx,word ptr [edx+43]
mov byte ptr [ecx+edx],al ;записать в память по адресу ecx+edx значение регистра al

В документации смещение в памяти часто называют указателем (pointer) или адресом.
Разные команды работают с разными сегментами памяти по умолчанию.
Windows устроен так, что вы можете использовать все сегменты как один и тот же (кроме FS, используемый для SEH). Пока не указывайте префиксы замены сегмента, при адресации ячейки памяти обращайте внимание только на смещение.
   -------------------------------

  Обозначение памяти в программе.

Для обозначения строки (массива) байт, слов или двойных слов используются операторы db, dw и dd соответственно.Текстовые строки заключаются в двойные или одинарные кавычки.

  Пример:
AnyLabel db 10 ;Определить 1 байт, равный 10

MsgString db 'Текстовая строка',0 ;определить текстовую строку, с последним байтом равным нолю (ASCIIZ формат. Часто используется функциями Windows. Ноль обозначает конец строки. В документации упоминается как "null-terminated string")

SomeDwords dd 18,30h,'axyz' ;определить массив двойных слов.

TenX db 10 dup ('X'),'YZ' ;определить 10 байт, равных символу "X", при помощи оператора dup и два последних байта "YZ"

UnDefWord dw ? ;определить слово, изначальное значение которого нам неважно.
   -------------------------------
  Типы данных word и dword хранятся в памяти в перевернутом виде. При считывании двойного слова из строки байт MsgString получим значение "скеТ"
Для обозначения меток в программе используют следующую форму записи: AnyLabel:
Ими обычно обозначаются участки программы, на которые передается управление при помощи команд перехода. Метки и названия переменных не могут начинаться с цифры, состоят из любой комбинации английских букв и символов "_", "$", "@", "?". Последние три символа лучше не использовать.

Для получения адреса в памяти метки используется оператор offset.
Чтобы узнать размер массива данных используйте оператор size
Для переопределения типа данных используется оператор ptr.
Оператор $ используется для получения смещения текущего байта.

  Пример:
mov ecx,offset SomeDwords+4 ;поместить в регистр ecx адрес в памяти строки SomeDwords +4.
mov cl,size TenX ;поместить в cl размер массива TenX (12).
mov edx,dword ptr [MsgString] ;поместить в edx двойное слово (4 байта - 4 символа) из строки MsgString.
Т.к edx - 32 битный регистр, а строка MsgString определена как строка байт, то нужно использовать оператор переопределения типа.

Символы - это 8 битные числа. Для определения числового значения символа можно использовать таблицу символов из Windows.
   -------------------------------

  Сегменты в программе.

Данные указываются в сегменте данных, обозначаемым как .data
Соответсвтенно код (команды процессора) надо писать в сегменте кода, т.е после .code
Каждая страница памяти (в Windows для пользовательских программ как правило ее размер 4 кб) может иметь свои атрибуты. Попытка записи в сегмент кода приведет к ошибке программы.
   -------------------------------

  Стэк (Stack)

Стэк - это область оперативной памяти, начало которой находится по адресу ss:esp
Значение регистра esp называется адресом вершины стэка.
Для помещения числа в стэк используется команда push, для извлечения - pop.
При помещении 32 битного числа в стэк (push), происходит следующее:

1)уменьшение значения регистра esp на 4 ( размер dword'а).
2)запись числа по адресу ss:esp
Таким образом стэк "растет" вниз, от больших адресов памяти к меньшим.

  Пример:
push eax ;поместить значение регистра eax в стэк
В стэк желательно помещать только 32 битные значения.
pop ecx ;извлечь из стэка число в регистр ecx
Команда pop ecx работает следующим образом:
mov ecx,dword ptr ss:[esp]
add esp,4

После выполнения этих команд (или команды pop ecx) значение ячейки памяти по адресу [esp-4] не изменится, но считается недействительным т.к. следующая команда push, другие команды работы со стэком, или возникшее прерывание перезапишут это значение, а также другие, с еще меньшим смещением.
   -------------------------------

Строчкой .model flat,stdcall задается модель памяти (flat для программ под Windows), и алгоритм работы макроса вызова процедур (stdcall для функций Windows).
   -------------------------------
.386   ;используем команды 386 процессора
   ;все последующие процессоры их также поддерживают.
 .model flat,stdcall    ;программа под Windows (см выше).
MAX_COMPUTERNAME_LENGTH equ 15
UNLEN equ 256
extrn GetComputerNameA:proc   ;используемые внешние функции
extrn GetUserNameA:proc
extrn MessageBoxA:proc
extrn ExitProcess:proc
 .data       ;сегмент данных
MTitle db 'Computer / User name',0  ;ASCIIZ строка - заголовок сообщения
CompNameSize dd MAX_COMPUTERNAME_LENGTH+1
UserNameSize dd UNLEN+1
MBuffer db MAX_COMPUTERNAME_LENGTH+UNLEN+1+3 dup (?)  ;неопределенный массив.
  ;В нем будет формироваться строка с именем компьютера и пользователя
 .code  ;сегмент кода
start: ;метка начала программы
;функция GetComputerNameA возвращает имя компьютера по адресу из первого параметра,
  ;и количество символов в имени по адресу из второго параметра.
 call GetComputerNameA,offset MBuffer,offset CompNameSize
 mov eax,offset MBuffer   ;eax= адресу массива MBuffer
  ;(в котором уже находится имя компьютера)
 add eax,dword ptr [CompNameSize] ;добавим к eax количество символов в
  ;имени компьютера. Получим адрес конца текстовай строки.
 mov dword ptr [eax],'X / ' ;добавим к концу строки 4 символа (X для теста).
 add eax,3    ;прибавим к смещению конца строки 3
  ;(по адресу eax будет символ X)
 call GetUserNameA,eax,offset UserNameSize ;передадим в качестве адреса 
  ;для возврата имени пользователя конец строки, по которому
  ;находится символ X, он будет перезаписан)
 call MessageBoxA,0,offset MBuffer,offset MTitle,0 ;отобразим строку,
  ;состоящую из имени компьютера, разделителя и имени пользователя.
 call ExitProcess,0  ;вызовем функцию завершения программы.
  ;если этого не сделать, выполнение пойдет дальше 
  ;и Windows выведет сообщение об ошибке.
ends    ;конец сегментов (можно и не писать)
end start   ;конец программы, точка входа

   -------------------------------
Загрузите программу отладчиком. Если вы используете SoftIce (Symbol Loader из меню пуск), то для того чтобы показать / спрятать окошко с данными введите команду wd. Для отображения данных используйте команды db,dw и dd.
Как только вы увидите инструкции программы, найдите смещение массива MBuffer в памяти (из операндов инструкций), и отобразите его содержимое в окне с данными. По ходу выполнения программы (по нажатию клавиши F10), вы увидите, как содержимое массива будет меняться.
   -------------------------------

 Содержание дальнейших выпусков зависит от вас. Будут разъясняться те темы, которые непонятны большинству читателей. Сайт рассылки: asm32.nm.ru. Присылайте свои вопросы и предложения по адресу: asm32@nm.ru .
   -------------------------------


Автор рассылки Владимир Пронин. Любое коммерческое использование материалов рассылки без ведома и прямого согласия автора запрещено.
Письма присланные автору рассылки могут быть опубликованы целиком или частично без предварительного уведомления. Если вы не хотите, чтобы ваше письмо было опубликовано укажите это в начале письма.


Subscribe.Ru
Поддержка подписчиков
Другие рассылки этой тематики
Другие рассылки этого автора
Подписан адрес:
Код этой рассылки: comp.soft.prog.asm32
Архив рассылки
Отписаться Вебом Почтой
Вспомнить пароль

В избранное