Ассемблер NASM для процессоров с архитектурой IA-32. Адресация. Флаги. Вызов внешних подпрограмм (1110584), страница 2
Текст из файла (страница 2)
CF=1 (установлен), если операция привела к переносу из старшегобита при сложении или к займу для старшего бита при вычитании, иначе сброшен. Для 8-, 16-, 324разрядных операций этот бит устанавливается при переносе из битов 7, 15 и 31 соответственно.Для беззнаковых операций флаг сигнализирует о переполнении. Значение этого флага может бытьизменено непосредственно при помощи инструкций: CLC — сбросить CF в 0, STC — установитьCF в 1, CMC — инвертировать CF.
Также используется в операциях сдвига.PF (parity) — флаг четности. PF=1 (установлен), если младшие восемь бит операнда содержатчетное число единиц (проверка на четность) иначе сброшен. На этот флаг влияют только младшиевосемь бит независимо от длины операнда.AF (auxiliary; adjust) — флаг вспомогательного переноса. Используется для упрощениясложения и вычитания упакованных двоично-десятичных чисел. Независимо от длины операнда (8,16 или 32 бит) флаг AF установлен, если операция привела к займу из бита 3 при вычитании илипереносу из бита 3 при сложении, иначе он сброшен.ZF (zero) — флаг нулевого результата. ZF=1 (установлен), если все биты результата равнынулю, иначе сброшен.SF (sign) — флаг знака.
SF=1 (установлен), если установлен старший бит результата, иначе онсброшен. Для 8-, 16- и 32-разрядных операций этот флаг отражает состояние 7, 15 и 31 битасоответственно. Для знаковых чисел старший бит отражает знак числа: 0 — неотрицательное, 1 —отрицательное.OF (overflow) — флаг переполнения. OF=1 (установлен), если получен результат за пределамидопустимого диапазона значений.
То есть если операция привела к переносу (займу) в знаковый(самый старший) бит результата, но не привела к переносу (займу) из самого старшего бита, илинаоборот. Для операций над числами со знаком сигнализирует о переполнении.Флаг направленияDF (direction) — флаг направления. Управляет направлением обработки строк данных,поведением цепочных инструкций (MOVS, CMPS, SCAS, LODS, STOS): DF=0 — от младшихадресов к старшим, DF=1 — от старших адресов к младшим (для специальных строковых команд).Когда флаг сброшен, при выполнении цепочечной команды происходит автоинкремент адресовисточника и приемника. Когда флаг установлен — автодекремент. Флаг можно непосредственноустановить при помощи инструкции STD и сбросить при помощи CLD.Системные флаги и поле IOPLСистемные флаги (флаги управления) и поле IOPL влияют на процесс исполнения задачи, ипоэтому не должны изменяться прикладной программой. Назначение этих флагов описано ниже.Эти флаги меняют режим работы процессора.TF (trap) — флаг ловушки, флаг трассировки.
Используется отладчиком для выполненияпрограммы по шагам. Установка флага TF переводит процессор в пошаговый режим для отладки.Процессор автоматически генерирует исключение #1 после каждой команды, что позволяетпроверить программу на исполнение каждой команды. Когда флаг TF сброшен, то ловушка поисключению #1 возникает в точках адресов останова, загружаемых в регистры отладки DR0–DR3.IF (interrupt enable) — флаг разрешения прерываний.
Установка флага (IF=1) позволяетпроцессору воспринимать запросы внешних маскируемых прерываний. Снятие этого битазапрещает такие прерывания. Флаг не влияет на обработку, как немаскируемых внешнихпрерываний, так и исключений.IOPL (I/O privilege level field) — уровень привилегий ввода-вывода. Это двухбитное полеиспользуется в защищенном режиме. Биты IOPL показывают наивысшее значение текущегоуровня привилегий (CPL), позволяющее выполнять команды ввода-вывода, не приводя кисключению #13 или обращению к битовой карте разрешения ввода-вывода. Это поле показываеттакже наивысшее значение CPL, которое позволяет изменять бит IF с помощью команд STI илиCLI, а также при выборке нового значения из стека в регистр EFLAGS.
Это поле может бытьизменено инструкциями POPF или IRET только если текущий уровень привилегий задачи равен 0.NT (nested task) — флаг вложенной задачи. Если при переключении задач происходит вложение5задач, то этот флаг устанавливается в 1. Совместно с полем «Связь TSS» в сегменте состояниязадачи обеспечивает корректное вложение задач.RF (resume) — флаг возобновления. Временно приостанавливает обработку исключенийотладки (т. е. возвращает к нормальному исполнению программы) так, что исполнение командыможет быть повторено после обработки исключения для отладки, не вызывая немедленнообработку другого исключения для отладки.VM (virtual 8086-mode) — режим виртуального микропроцессора 8086. Бит обеспечивает длязадачи функционирование в режиме виртуального МП 8086.
Бит VM может быть установлен толькодвумя способами: при восстановлении флагов из стека по инструкции IRET на нулевом уровнепривилегий и переключением на задачу, в TSS которой в образе EFLAGS бит VM выставлен.AC (alignment check) — флаг контроля выравнивания. Разрешает контроль выравнивания длятекущей задачи. Контроль выравнивания производится, если CR0.AM=1 и EFLAGS.AC=1 иCR0.PE=1 и CPL=3. Контроль выравнивания требует, чтобы при обращениях к памяти двойноеслово обязательно должно начинаться с адреса, кратного 4, а 16-битное слово — с адреса, кратного2, иначе генерируется нарушение контроля выравнивания (исключение #17).VIF (virtual interrupt) — виртуальный флаг прерывания.
Виртуальный образ флага IF,используется совместно с флагом VIP. Процессор распознает VIF, если CR4.VME=1 илиCR4.PVI=1 (разрешено расширение виртуального режима) и IOPL<3.VIP (virtual interrupt pending) — виртуальный флаг задержки прерывания. Системное ПОустанавливает этот флаг, если требуется отложить обработку прерывания. Используется совместнос VIF. Процессор читает этот флаг, но никогда не изменяет его. Флаг распознается, еслиCR4.VME=1 или CR4.PVI=1 (разрешено расширение виртуального режима) и IOPL<3.ID (identification) — флаг поддержки CPUID.
Если программа может изменить этот флаг (т. е.процессор хранит то значение, которое программа запишет в этот флаг), то процессорподдерживает инструкцию CPUID. Инструкцию CPUID поддерживают не только Pentium и P6, но инекоторые модели i486.Адресация. Обращение по ссылке и по значениюВ языках высокого уровня при объявлении простой переменной обращение к ней ведется позначению.
Кроме того, существует специальный тип данных — указатель, который содержит адресячейки памяти, и в случае его использования обращение будет происходить по ссылке.На языке ассемблера ситуация иная — прямое обращение к имени переменной являетсяобращением к адресу этой переменной в памяти. Для обращения к значению ячейки по какому-либоадресу на диалекте NASM (и многих других) используются квадратные скобки. Ниже представленпример программы, которая выводит адрес и значение переменной:extern ExitProcess%include "io.inc"section .text use32..start:push dword x; печать адреса переменной xcall outicall outlnadd [x],dword 256; изменение значения xpush dword [x] ; печать значения переменной xcall outipush dword 0call ExitProcesssection .datax dw 2566Адресация. Эффективный адресДля большинства вычислительных систем эффективный адрес (“effective address”, EA) — адрес,по которому происходит обращение к памяти; численно совпадает с виртуальным адресом.Вычисление EA выполняется следующим образом:база + ( индекс * коэффициент ) + смещениеГде:☼ в качестве базы может выступать любой РОН;☼ индексом может быть любой РОН, кроме ESP;☼ коэффициент масштабирования может принимать численное значение 1, 2, 4 или 8;☼ смещение задается константой.Примечание: можно встретить и более полную форму вычисления эффективного адреса —перед базой указан сегмент, представленный одним из сегментных регистров; дляприкладных задач (вроде практических работ) сегмент не учитывают.База, индекс и смещение могут использоваться в различных комбинациях — некоторые изкомпонентов могут равняться нулю.
Коэффициент масштабирования может использоваться тольковместе с индексом.Ниже показан пример вычисления адреса ebx+esi*2+2 на языке ассемблера:mov eax,ebxmov edi,esiimul edi,2add eax,ediadd eax,2;;;;;eaxediedieaxeax:=:=:=:=:=ebxesiedieaxeax(копируем адрес базы для вычислений)(копируем текущий индекс для вычислений)* 2+ edi+ 2Однако записывать такое количество инструкций зачастую неудобно, поэтому для вычисленияEA была добавлена специальная инструкция LEA (“load effective address”).
Приведенный вышепример можно записать с использованием одной команды LEA:lea eax,[ebx+esi*2+2]На диалекте NASM инструкция MOV может использоваться точно так же как и LEA (однакоLEA в некоторых случаях эффективнее), то есть допустим следующий код:mov eax,[ebx+esi*2+2]7Адресация. Описание массивовИнициализированные статические массивы на диалекте NASM записываются так же, как ипростые переменные, например:array db 1,1,2,3,5,8,13,21array_length equ $-array; массив из N элементов; количество элементов массиваНеинициализированные статические массивы описываются как и неинициализированныепеременные:buffer resb 64wordvar resw 2; выделить 64 байта; выделить 2 словаДля динамического выделения памяти необходимо выполнить системный вызов.
Такойпривилегией обладают лишь функции ОС. Для работы с динамической памятью в Windowsиспользуются следующие внешние подпрограммы.GlobalAlloc(<флаги>, <кол-во>) — запрос к Windows на выделение указанногоколичества байтов памяти; флаги указывают различные параметры выделения памяти.GlobalFree(<указатель>) — запрос к Windows для пометки области памяти, на которуюссылается указатель, как свободной.Примечание: на сайте MSDN расположена полная документация функций GlobalAlloc иGlobalFree.Доступ к массивам данных может быть организован с помощью обычных циклов (инструкцияloop или только условные переходы), однако наиболее эффективным является использованиеэффективных адресов ячеек массива и итерация по ним.Отладчик программ на языке ассемблераДля отладки программ, написанных на языке ассемблера рекомендуется использоватьбесплатный отладчик OllyDbg 2.0.
Документация по отладчику на русском языке:☼ cracklab.ru;☼ habrahabr.ru.8.