Инструкция К Программеру P3000
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Мануал по flat assembler (FASM): Не компилится, ругается на mov dx, hello format pe64 mov ax, cs mov ds, ax mov dx, hello mov ah, 9h int 21h Разработчик Flat assembler'a Tomasz Grysztar в одном из блогов сообщил о разработке новой неофициальной версии флэт асма. Вскоре через. Доброго времени суток. Есть программа, собственно вот что она делает: 'На экране инициализировать 2 локальных окна. Каждое окно со.
Со временем задачи стали нерешаемыми из-за ужасно медленной скорости. Уже давно хочу перейти на FASM, но понятных по нему статей так и не. У меня есть задание 'Упорядочить по убыванию элементы каждого столбцу матрицы' Числа произвольные. Если кому не сложно будет помочь.
Мультиязычное руководство по эксплуатации. P300 deh-p3000 deh-p200 pdf.
Всем добрый день! Подскажите, почему не работает массив в Flat Assembler? Org 100h jmp start massiv dw 1, 3, 5, 7, 5 start. FASM написан на самом себе, обладает небольшими размерами и очень высокой скоростью компиляции, имеет богатый и емкий макро-синтаксис, позволяющий автоматизировать множество рутинных задач. Поддерживаются как объектные форматы, так и форматы исполняемых файлов. Это позволяет в большинстве случаев обойтись без линкера. В остальных случаях нужно использовать сторонние линкеры, поскольку линкер вместе с FASM не распространяется.
Помимо базового набора инструкций процессора x86 и сопроцессора FASM поддерживает наборы инструкций MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, SSE4a, AVX и 3DNow!, а также EM64T и AMD64 (включая AMD SVM и Intel SMX). FASM ― это быстрый компилятор языка ассемблер, который выполняет несколько проходов компиляции для оптимизации генерируемого машинного кода.
FASM способен работать в следующих операционных системах:. DOS, расширенные DOS. Windows 9X, NT, XP, Vista, Seven. Основанные на Linux — напрямую, через системные вызовы. FreeBSD.
Другие, основанные на libc (UNIX-подобные). MenuetOS, KolibriOS — не поставляется в стандартном пакете FASM, поставляется вместе с этими операционными системами. Версии для разных операционных систем предназначены для использования из системной командной строки и не отличаются поведением. Этот документ описывает также IDE версию, разработанную для операционной системы Windows, которая использует графический интерфейс взамен консольного и обладает встроенным текстовым редактором. С точки зрения компиляции она обладает в точности такой же функциональностью как и все консольные версии, и дальнейшие части (начиная с 1.2) этого документа являются общими для всех версий компилятора. Исполняемый файл IDE версии называется fasmw.exe, в то время как консольная версия называется fasm.exe. Все версии требуют для своей работы 32-битного процессора архитектуры x86 (как минимум 80386), хотя могут также генерировать программы и для 16-битных процессоров.
Консольная версия компилятора требует для работы любую Win32 совместимую операционную систему, в то время как версия с графическим интерфейсом требует Win32 GUI операционную систему версии 4.0 и выше, так что компилятор будет работать на любой системе начиная с Windows 95 и выше. Исходные коды программ-примеров поставляемые с этой версией компилятора для успешной компиляции требуют, чтобы переменная окружения INCLUDE хранила полный путь к папке include, которая является частью пакета. Если такая переменная уже существует в вашей системе и содержит пути используемые другой программой, достаточно добавить к ней новый путь (разные пути разделяются точкой с запятой). Если вы не хотите определять такую переменную в системе, или не знаете как это сделать, то для IDE версии вы можете установить её редактированием файла fasmw.ini в папке с исполняемым файлом компилятора (этот файл создаётся компилятором fasmw.exe при запуске, но может также быть создан вручную). В этом случае вам необходимо добавить значение Include в секцию Environment. Например, если вы распаковали файлы FASM'а в папку c: fasmw, вы должны добавить следующие строки в файл c: fasmw fasmw.ini.
Для того, чтобы начать работать с FASM'ом, просто запустите файл fasmw.exe, или перетащите иконку исходного файла на ярлык программы fasmw.exe в проводнике. Также вы можете открывать новые исходные файлы с помощью команды Open в меню File, или перетаскивая файлы в окно редактора. В редакторе могут быть открыты несколько файлов одновременно, каждый из них представляется закладкой в нижней части окна редактора. Выбрать файл для редактирования можно щёлкнув левой кнопкой мыши на соответствующей закладке. По умолчанию компилятор работает с редактируемым в данный момент файлом, но вы можете принудить его работать с конкретным файлом щёлкнув на соответствующей закладке правой кнопкой мыши и выбрав в контекстном меню пункт Assign.
Одновременно к компилятору может быть привязан только один файл. Когда ваш исходный файл готов, вы можете выполнить компиляцию выбрав команду Compile из меню Run. Если компиляция пройдет успешно, компилятор отобразит окно результатов компиляции; иначе он выведет информацию о произошедших ошибках. Окно результатов компиляции содержит информацию о количестве проходов, длительности компиляции и количестве байт записанных в результирующий файл.
Оно также содержит текстовое поле называемое Display, в котором отображаются все сообщения от директив display в исходном коде (см. Сводка ошибок содержит как минимум сообщение об ошибке и текстовое поле Display, того же назначения. Если ошибка связана с конкретной строкой исходного кода, сводка содержит также текстовое поле Instruction, которое содержит препроцессированную форму инструкции вызвавшей ошибку если ошибка произошла после стадии препроцессора (иначе поле пустое) и список Source, который показывает расположение всех строк исходного кода связанных с этой ошибкой, если вы выберете строку из этого списка, она одновременно выбрана в окне редактора (если соответствующий файл не открыт, он будет автоматически загружен). Команда Run также выполняет компиляцию, и в случае успешного её завершения запускает скомпилированную программу в том случае, если она относится к одному из форматов, запускаемых в среде Windows, иначе выводится сообщение о том, что такой тип файла не может быть запущен. Если при компиляции возникают ошибки, выводится сводка по ошибкам, как для команды Compile. Если компилятору не хватает памяти, вы можете увеличить используемый её объём, открыв окно Compiler Setup из меню Options.
В нем вы можете указать объём памяти в килобайтах который компилятор должен использовать и также задать приоритет потока компилятора. Для запуска FASMа из командной строки вам понадобится ввести два параметра: первый - это путь к файлу с кодом, второй - путь к файлу-адресату информации. Если второй параметр не задан, название файла вывода будет создано автоматически. После показа короткой информации о названии программы и её версии, компилятор считает информацию из файла с кодом и скомпилирует её.
После успешной компиляции FASM запишет сгенерированный код в файл-адресат и выведет краткую информацию о завершенном процессе; в противном случае он выведет информацию о первой ошибке. Исходник должен быть текстовым файлом и может быть создан в любом текстовом редакторе. Обрыв строки допускается и в стандарте DOS, и в стандарте Unix, табуляции обрабатываются как пробелы.
В командную строку вы также можете включить опцию ' -m', за которой должно следовать число, указывающее, сколько килобайт памяти может быть максимально задействовано FASM'ом. В случае DOS-версии эта опция ограничивает лишь использование расширенной памяти. Опция ' -p' со следующим за ним числом может быть использована для того, чтобы ограничить количество проходов, которое будет делать ассемблер. Если код не может быть создан заданным числом проходов, ассемблирование прекратится с сообщением об ошибке. Максимальное значение этой опции равно 65536, а значение по умолчанию равно 100.
Не существует опций, оказывающих воздействие на выходные данные компилятора, вся необходимая FASM'у информация должна содержаться в исходном коде. Например, для установки формата файла-адресата используется директива ' format' в начале кода. По умолчанию, если в исходнике нет директивы 'format', flat assembler направляет сгенерированный код на вывод, создавая таким образом простой двоичный файл. По умолчанию он создает 16-битный код, но вы всегда можете переключить его в 32-битный или 16-битный режим, используя директивы 'use32' или 'use16'. Выбор некоторых форматов файла-адресата автоматически переключает компилятор в 32-битный режим. Подробнее читайте о форматах, которые можете выбрать, в 2.4. Весь сгенерированный код в файле-адресате всегда идет в том же порядке, что и написанный в исходнике.
Информация, изложенная ниже, предназначена главным образом программистам, которые прежде использовали другие компиляторы ассемблера. Если вы новичок, читайте учебники по программированию на ассемблере. Flat assembler по умолчанию использует Intel-синтаксис ассемблерных инструкций, однако вы можете переделать их, используя возможности препроцессора (макросы и символьные константы). Он также имеет собственный набор директив - инструкций для компилятора.
Все символы, определенные внутри кода, чувствительны к регистру. Чтобы описать данные или зарезервировать для них место, используйте одну из директив, перечисленных в таблице 1.3.
За директивой описания данных должно следовать одно или несколько числовых значений, разделенных запятыми. Эти выражения определяют значения для простейших элементов данных, размер которых зависит от того, какая директива используется. Например 'db 1,2,3' описывает три байта со значениями 1, 2 и 3 соответственно.
Директивы 'du' и 'db' также поддерживают сроки любой длины, заключенные в кавычки, которые будут конвертированы в последовательность байтов, если использована директива 'db', или в последовательность слов с нулевым верхним байтом, если использована директива 'du'. Например, 'db 'abc' определяет три байта со значениями 61, 62 и 63. Директива 'dp' или её синоним 'df' допускают, чтобы значения состояли из двух числовых выражений, разделенных двоеточием, где первое значение - это верхнее слово, а второе - это нижнее двойное слово значения дальнего указателя.
Также 'dd' допускает такие указатели, состоящие из двух слов, разделенных двоеточием, и 'dt' допускает слово и четверное слово, разделенные двоеточием, четверное слово запоминается первым. Директива 'dt' с одним параметром допускает только значения с плавающей точкой и создает данные в FPU-формате двойной расширенной точности. Все вышеперечисленные директивы поддерживают использование специального оператора 'dup' для создания копий данных значений. Количество дубликатов должно стоять перед этим оператором, а их значение должно стоять после - это может быть даже цепь значений, разделенных запятыми, но эта цепь должна быть заключена в скобки, например 'db 5 dup (1,2)' определяет пять копий данной последовательности из двух байтов. 'file' - это специальная директива и её синтаксис может быть различным. Эта директива включает цепь байтов из файла.
В качестве параметра за ней должно идти в кавычках имя файла, далее, опционально, двоеточие и числовое выражение, указывающее начало цепочки байтов, далее, также опционально, запятая и числовое выражение, определяющее количество байтов в этой цепочке (если этот параметр не определен, то будут включены все данные до конца файла). Например, 'file 'data.bin' включит весь файл как двоичные данные, а 'file 'data.bin':10h,4' включит только четыре байта, начиная со смещения 10h. За директивой резервирования данных должно следовать одно числовое выражение, значение которого определяет количество резервируемых ячеек установленного размера. Все директивы описания данных также поддерживают значение '?' , которое значит, что этой ячейке не должно быть присвоено какое-то значение.
Эффект от этой директивы такой же, как от директивы резервирования данных. Неинициализированные данные не могут быть включены в файл вывода, и, таким образом, их значения всегда будут считаться неизвестными.
Таблица 1.3 Директивы данных. В числовых выражениях вместо чисел вы также можете использовать константы и метки. Чтобы назначить их, используйте специальные директивы. Каждая метка может быть определена только однажды и она будет доступна из любой части кода (даже перед местом, где она была определена).
Константа может быть переопределена много раз, но в этом случае она будет доступна только после присвоения значения и всегда будет равна значению из последнего определения перед местом, в котором она использована. Если константа определена лишь однажды, она, так же как и метка, доступна из любой части кода. Определение константы состоит из имени константы, знака '=' и числового выражения, которое после вычисления становится значением константы. Это значение всегда вычисляется в то же время, что и определение константы.
Например, с помощью директивы 'count = 17' вы можете определить константу 'count' и после использовать её в инструкциях ассемблера, таких как 'mov cx,count' - которая превратится в 'mov cx,17' во время процесса компиляции. Существуют разные способы определения меток. Простейший из них - двоеточие после названия метки. За этой директивой на той же строке даже может следовать другая инструкция. Она определяет метку, значение которой равно смещению точки, в которой она определена. Этот метод обычно используется, чтобы пометить места в коде. Другой способ - это следование за именем метки (без двоеточия) какой-нибудь директивы описания данных.
Метке присваивается значение адреса начала определенных в директиве данных и запоминается компилятором как метка для данных с размером ячейки, заданной директивой из таблицы 1.3. Метка может быть обработана как константа со значением, равным смещению помеченного кода или данных. Например, если вы определяете данные, используя помеченную директиву 'char db 224', для того, чтобы поместить адрес начала этих данных в регистр BX, вам нужно использовать инструкцию 'mov bx,char', а для того, чтобы поместить в регистр DL значение байта, на который ссылается 'char', нужно использовать 'mov dl,char' (или 'mov dl,ptr char').
Если вы попытаетесь ассемблировать 'mov ax,char', FASM выдаст ошибку, так как он сравнивает размеры операндов, которые должны быть равны. Вы можете принудительно проассемблировать эту инструкцию, изменяя размер операнда: 'mov ax, word char', но помните, что эта инструкция прочитает два байта, начинающихся с адреса 'char', тогда как он был определен как один байт. Последний и самый гибкий способ задания меток - это использование директивы 'label'.
За этой директивой должно следовать имя метки, далее, опционально, размер оператора (может предваряться двоеточием), и далее, также опционально, оператор 'at' и числовое выражение, определяющее адрес, на который данная метка должна ссылаться. Например, 'label wchar word at char' определяет новую метку для 16-битных данных по адресу 'char'.
Теперь инструкция 'mov ax,wchar' после компиляции будет выглядеть так же, как 'mov ax,word char'. Если адрес не указан, директива 'label' будет ссылаться на текущий адрес. Таким образом, 'mov wchar,57568' скопирует два байта, тогда как 'mov char,224' скопирует один байт на тот же адрес. Метка, имя которой начинается с точки, обрабатывается как локальная, и её имя прикрепляется к имени последней глобальной метки (с названием, начинающемся с чего угодно, кроме точки) для создания полного имени этой метки.
Так, вы можете использовать короткое имя (начинающееся с точки) где угодно перед следующей глобальной меткой, а в других местах вам придется пользоваться полным именем. Метки, начинающиеся с двух точек - исключения.
Они имеют свойства глобальных, но не создают новый префикс для локальных меток. '@@' обозначает анонимную метку, вы можете определить её множество раз. Символ '@b' (или эквивалент '@r') ссылается на ближайшую предшествующую анонимную метку, а символ '@f' ссылается на ближайшую после неё анонимною метку.
Эти специальные символы нечувствительны к регистру. В предыдущих примерах все числовые выражения были обычными числами, константами или метками.
Но они могут быть более сложными, использовать арифметические или логические операторы для вычисления во время компиляции. Все эти операторы с их значениями приоритета перечислены в таблице 1.4. Операции с высшим приоритетом выполняются первыми, однако вы, конечно, можете изменить такой образ действий, заключив некоторые части выражения в скобочки. '+', '-', '.' и '/' - это стандартные арифметические операции, 'mod' вычисляет остаток от деления нацело.
'and', 'or', 'xor', 'shl', 'shr' и 'not' совершают те же логические операции, что и инструкции ассемблера с такими же названиями. 'rva' характерна только для формата вывода PE и производит превращение адреса в RVA. Числа в выражениях по умолчанию обрабатываются как десятичные, двоичные числа должны иметь 'b' в конце, восьмеричные числа должны заканчиваться на букву 'o', шестнадцатеричные цифры должны начинаться символами '0x' (как в языке C), или символом '$' (как в языке Pascal) или должны заканчиваться буквой 'h'. Также заключенная в кавычки строка при включении в выражение будет конвертирована в число - первый символ станет минимальным значащим байтом числа.
Числовые выражения, используемые как значения адреса, могут также содержать любой из общих регистров, используемых для адресации, они могут быть сложены или умножены на подходящие значения так, как это позволено в инструкциях архитектуры x86. Также есть несколько специальных символов, которые могут быть использованы в числовом выражении. Первое - это '$', которое всегда равно значению текущего смещения, тогда как '$$' равно базовому адресу текущего диапазона адресов. Следующий символ - '%' - это номер текущего повтора в частях кода, которые повторяются, благодаря использованию некоторых специальных директив (смотрите 2.2).
Также существует символ '%t', который всегда равен текущей отметке времени. Любое численное выражение также может состоять из одного значения с плавающей точкой (flat assembler не может производить во время компиляции операции с плавающей точкой) в научной записи. Для распознания компилятором, эти значения должны содержать в конце букву 'f', либо включать в себя по крайней мере один символ '.' Так, '1.0', '1E0' и '1f' определяют одно и то же значение с плавающей точкой, когда как просто '1' определяет целочисленное значение. Операнд любого перехода или инструкция вызова может предваряться не только операторами размера, но также одним из операторов, определяющих тип перехода: 'near' или 'far'.

Например, если ассемблер в 16-битном режиме, инструкция 'jmp dword 0' станет далеким переходом, а если ассемблер в 32-битном режиме, она станет близким переходом. Чтобы заставить эту инструкцию обрабатываться по-разному, используйте формы 'jmp near dword 0' или 'jmp far dword 0'. Если операнд близкого перехода это немедленное значение, ассемблер, если возможно, сгенерирует кратчайший вариант этой инструкции перехода (но не будет создавать 32-битную инструкцию в 16-битном режиме или 16-битную инструкцию в 32-битном режиме, если оператор размера точно её не определит). Заданием оператора размера вы можете заставить ассемблер всегда генерировать длинный вариант (например, 'jmp word 0' в 16-битном режиме или ' jmp dword 0' в 32-битном режиме) или всегда создавать короткий вариант и завершаться с ошибкой, когда это невозможно (например ' jmp byte 0'). Если инструкция использует некоторую адресацию в памяти, по умолчанию будет генерироваться кратчайшая 8-битная форма, если значение адреса попадает в нужный диапазон, но он может быть изменен с помощью операторов 'word' и 'dword' перед адресом в квадратных скобках (или после оператора 'ptr'). Такое размещение оператора размера также может быть использовано для установки размера адреса, отличного от размера, установленного в данном режиме по умолчанию.
Инструкции ' adc', ' add', ' and', ' cmp', ' or', ' sbb', ' sub' и ' xor' с первым 16-ти или 32-битным операндом по умолчанию генерируются в укороченной 8-битной форме, если второй операнд - это непосредственное значение, применимое для предписанных 8-битных значений. Она также может быть изменена операторами ' word' и ' dword' перед такими значениями. Сходные правила применимы к инструкции ' imul' с непосредственным значениям в качестве последнего операнда. Непосредственное значение как операнд для инструкции 'push' без оператора размера, по умолчанию обрабатывается как слово, если ассемблер 16-битном режиме, и как двойное слово, если FASM в 32-битном режиме. Короткая 8-битная форма используется по возможности, операторы размера 'word' и 'dword' могут заставить инструкцию 'push' быть сгенерированной в более длинной форме.
Мнемоники 'pushw' и 'pushd' указывают ассемблеру сгенерировать 16-битный или 32-битный код без принуждения его использовать длинную форму инструкции. В этом параграфе вы найдете всю информацию о синтаксисе и назначении инструкций ассемблера. Если вам нужно больше технической информации, смотрите Intel Architecture Software Developer's Manual. Инструкции ассемблера состоят из мнемоника (имени инструкции) и нескольких операндов (от нуля до трех). Если операндов два или три, то обычно первым идет адресат, а вторым источник. Операндом может быть регистр, память или непосредственное значение (подробнее о синтаксисе операндов смотрите в 1.2). После описания каждой инструкции ниже будут примеры разных комбинаций операндов, если, конечно, она содержит операнды.
Некоторые инструкции работают как префиксы и могут быть перед другой инструкцией на той же строке. На одной строке может несколько префиксов. Каждое имя сегментного регистра это тоже мнемоник инструкции-префикса, хотя рекомендуется использовать замещение сегмента внутри квадратных скобок вместо этих префиксов. 'mov' переносит байт, слово или двойное слово из операнда-источника в операнд-адресат. Этот мнемоник может передавать данные между регистрами общего назначения, из этих регистров в память, обратно, но не может перемещать данные из памяти в память. Он также может передавать непосредственное значение в регистр общего назначения или в память, сегментный регистр в регистр общего назначения или в память, регистр общего назначения в сегментный регистр или в память, контрольный или отладочный регистр в регистр общего назначения и назад.
'mov' может быть ассемблирована только если размер операнда-источника и размер операнда-адресата совпадают. Ниже приведены примеры каждой из перечисленных комбинаций. 1 2 xchg ax, bx; обмен содержимым регистров общего назначения АХ и ВХ xchg al, char ; обмен содержимым регистра общего назначения AL и ячейки памяти. 'push' уменьшает значение указателя стекового фрейма (регистр ESP), потом переводит операнд на верх стека, на который указывает ESP. Операндом может быть память, регистр общего назначения, сегментный регистр или непосредственное значение размером в слово или двойное слово. Если операнд - это непосредственное значение и его размер не определен, то в 16-битном режиме по умолчанию он обрабатывается как слово, а в 32-битном режиме как двойное слово.
Мнемоники 'pushw' и 'pushd' - это варианты этой инструкции, которые сохраняют соответственно слова и двойные слова. Если на одной строке содержится несколько операндов (разделенных пробелами, а не запятыми), компилятор проассемблирует цепь инструкций 'push' с этими операндами. Вот примеры с одиночными операндами. 1 2 3 4 push ax; сохранить содержимое регистра общего назначения АХ в стеке push es; сохранить содержимое сегментного регистра в стеке pushw bx ; сохранить содержимое ячейки памяти в стеке push 1000h; поместить в стек непосредственное значение. Инструкция 'pusha' сохраняет в стек содержимое восьми регистров общего назначения.
У неё нет операндов. Существует две версии этой инструкции: 16-битная и 32-битная. Ассемблер автоматически генерирует версию, соответствующую текущему режиму, но, используя мнемоники 'pushaw' или 'pushad',это можно изменить для того, чтобы всегда получать, соответственно, 16- или 32-битную версию. 16-битная версия этой инструкции сохраняет регистры общего назначения в таком порядке: AX, CX, DX, BX, значение регистра SP перед тем, как был сохранен AX, далее BP, SI и DI. 32-битная версия сохраняет эквивалентные 32-битные регистры в том же порядке. 'pop' переводит слово или двойное слово из текущей верхушки стека в операнд-адресат и после уменьшает ESP на указатель на новую верхушку стека. Операндом может служить память, регистр общего назначения или сегментный регистр.
Мнемоники 'popw' и 'popd' - это варианты этой инструкции, восстанавливающие соответственно слова и двойные слова. Если на одной строке содержится несколько операндов, разделенных пробелами, компилятор ассемблирует цепочку инструкций с этими операндами. Инструкции преобразования типов конвертируют байты в слова, слова в двойные слова и двойные слова в четверные слова. Эти преобразования можно совершить, используя знаковое или нулевое расширение. Знаковое расширение заполняют дополнительные биты большего операнда значением бита знака меньшего операнда, нулевое расширение просто забивает их нулями. 'cwd' и 'cdq' удваивают размер регистра AX или EAX соответственно и сохраняет дополнительные биты в регистр DX или EDX.
Преобразование делается, используя знаковое расширение. Эти инструкции не имеют операндов. 'cbw' растягивает знак байта AL по регистру AX, а 'cwde' растягивает знак слова AX на EAX. Эти инструкции также не имеют операндов. 'movsx' преобразует байт в слово или в двойное слово и слово в двойное слово, используя знаковое расширение. 'movzx' делает то же самое, но используя нулевое расширение.
Операндом-источником может быть регистр общего назначения или память, тогда как операндом-адресатом должен быть регистр общего назначения. 1 2 3 4 5 add ax, bx; прибавляет регистр к регистру add axsi ; прибавляет память к регистру add di , al; прибавляет регистр к памяти add al, 48; прибавляет непосредственное значение к регистру add char , 48; прибавляет непосредственное значение к памяти. 'adc' суммирует операнды, прибавляет единицу, если стоит CF и заменяет адресат результатом. Правила для операндов такие же как с инструкцией 'add'. 'add' со следующими за ней несколькими инструкциями 'adc' может быть использована для сложения чисел длиннее, чем 32 бита.
'inc' прибавляет к операнду единицу, он не может изменить CF. Операндом может быть регистр общего назначения или память, размером он может быть в байт, слово или двойное слово. 1 2 inc ax; прибавляет единицу к регистру inc byte bx ; увеличивает единицу к памяти.
'sub' вычитает операнд-источник от операнда адресата и заменяет адресат результатом. Если требуется отрицательный перенос, устанавливается CF. Правила для операндов такие же, как с инструкцией 'add'.
'sbb' вычитает источник из адресата, отнимает единицу, если установлен CF и заменяет адресат результатом. Правила для операндов такие же, как с инструкцией 'add'. 'sub' со следующими за ней несколькими инструкциями 'sbb' может быть использована для вычитания чисел длиннее, чем 32 бита. 'dec' вычитает из операнда единицу, не может изменить CF. Правила для операнда такие же, как с инструкцией 'inc'.
'cmp' вычитает операнд-источник из оператора-адресата. Эта инструкция может устанавливать флаги, как и 'sub', но не вносит изменения в операнды. Правила для операндов такие же, как с инструкцией 'sub'.
'neg' отнимает от нуля целочисленный операнд с знаком. Эффект от этой инструкции - это смена знака операнда с положительного на отрицательный или с отрицательного на положительный. Правила для операндов такие же, как с инструкцией 'inc'. 'xadd' меняет местами операнд-адресат и операнд-источник, потом загружает сумму двух значений в операнд-адресат. Правила для операндов такие же, как с инструкцией 'add'.
Все вышеперечисленные инструкции изменяют флаги SF, ZF, PF и OF. SF всегда принимает значение, равное биту знака результата, ZF устанавливается, если результат равен нулю, PF устанавливается, если восемь битов нижнего разряда содержат четное число единиц, OF устанавливается, если результат слишком большой для положительного числа или слишком маленький для отрицательного (исключая бит знака) для того, чтобы уместиться в операнде-адресате.
'mul' выполняет беззнаковое перемножение операнда и аккумулятора. Если операнд - байт, процессор умножает его на содержимое AL и возвращает 16-битный результат в AH и AL. Если операнд - слово, процессор умножает его на содержимое AX и возвращает 32-битный результат в DX и AX.
Если же операнд - это двойное слово, процессор умножает его на содержимое EAX и возвращает 64-битный результат в EDX и EAX. 'mul'устанавливает CF и OF, если верхняя половина результата ненулевая, иначе они очищаются. Правила для операндов такие же, как с инструкцией 'inc'. 'imul' выполняет знаковое перемножение операндов.
У этой инструкции есть три вариации. Первая имеет один операнд и работает так же, как инструкция 'mul'. Вторая имеет два операнда, и здесь операнд-адресат умножается на операнд-источник и результат заменяет операнд-адресат. Этим операндом может быть регистр общего назначения, память или непосредственное значение.
Третья форма инструкции имеет три операнда, операндом-адресатом должен быть регистр общего назначения, длиной в слово или в двойное слово, операндом-источником может быть регистр общего назначения или память, третьим операндом должно быть непосредственное значение. Источник умножается на непосредственное значение и результат помещается в регистр-адресат. Все три формы вычисляют результат размером в два раза больше размера операндов и ставят CF и OF, если верхняя часть результата ненулевая, но вторая и третья формы усекают результат до размера операндов. Так, их можно использовать для беззнаковых операндов, потому что нижняя половина результата одна и та же для знаковых и беззнаковых операндов.
Ниже вы видите примеры всех трех форм. 1 2 3 4 5 6 7 imul bl; умножение аккумулятора на регистр imul word si ; умножение аккумулятора на память imul bx, cx; умножение регистра на регистр imul bxsi ; умножение регистра на память imul bx, 10; умножение регистра на непосредственное значение imul ax, bx, 10; регистр, умноженный на непосредственное значение, в регистр imul axsi , 10; память, умноженная на непосредственное значение, в регистр. 'div' производит беззнаковое деление аккумулятора на операнд.
Делимое (аккумулятор) размером в два раза больше делителя (операнда), частное и остаток такого же размера, как и делитель. Если делитель - байт, делимое берется из регистра AX, частное сохраняется в AL, а остаток - в AH.
Если делитель - слово, верхняя половина делимого берется из DX, а нижняя - из AX, частное сохраняется в AX, а остаток - в DX. Если делитель - двойное слово, верхняя половина делимого берется из EDX, а нижняя - из EAX, частное сохраняется в EAX, а остаток - в EDX.
Правила для операндов такие же, как с инструкцией 'mul'. 'idiv' выполняет знаковое деление аккумулятора на операнд. Инструкция использует те же регистры, что и 'div', правила для для операнда тоже такие же. Десятичная арифметика представлена в виде соединения двоичных арифметических инструкций (описанных в предыдущем параграфе) с десятичными арифметическими инструкциями. Десятичные арифметические инструкции используются для того, чтобы приспособить результаты предыдущей двоичной арифметической операции для создания допустимого упакованного или неупакованного десятичного результата (BCD-числа), или приспособить входные данные для последующей двоичной арифметической операции так, чтобы эта операция также давала допустимый упакованный или неупакованный десятичный результат. 'daa' прилаживает результат сложения двух допустимых сжатых десятичных числа к AL.
'daa' всегда должна следовать за суммированием двух пар сжатых десятичных цифр (один знак в каждой половине байта), чтобы получить как результат пару допустимых сжатых десятичных символов. Если потребуется перенос, будет установлен флаг переноса. У этой инструкции нет операндов.
'das' прилаживает результат вычитания двух допустимых сжатых десятичных числа к AL. 'das' всегда должна следовать за вычитанием одной пары сжатых десятичных цифр (один знак в каждой половине байта) из другой, чтобы получить как результат пару допустимых сжатых десятичных символов. Если потребуется отрицательный перенос, будет установлен флаг переноса. У этой инструкции нет операндов. 'aaa' изменяет содержимое регистра AL на допустимое несжатое десятичное число и обнуляет верхние четыре бита. 'aaa' всегда должна следовать за сложением двух несжатых десятичных операндов в AL. Если необходим перенос, устанавливается флаг переноса и увеличивается на единицу AH.
У этой инструкции нет операндов. 'aas' изменяет содержимое регистра AL на допустимое несжатое десятичное число и обнуляет верхние четыре бита. 'aas' всегда должна следовать за вычитанием одного несжатого десятичного операнда из другого в AL. Если необходим перенос, устанавливется флаг переноса и уменьшается на единицу AH.
У этой инструкции нет операндов. 'aam' корректирует результат умножения двух допустимых несжатых десятичных чисел. Для создания правильного десятичного результата инструкция должна всегда следовать за умножением двух десятичных чисел. Цифра верхнего регистра передается в AH, а нижнего - в AL.
Обобщенная версия этой инструкции делает возможной подгонку содержимого AX для создания двух несжатых цифр с любым основанием. Стандартная версия этой инструкции не имеет операндов, у обобщенной версии есть один операнд - непосредственное значение, определяющее основание создаваемых чисел.
'aad' модифицирует делимое в AH и AL, чтобы подготовится к делению двух допустимых несжатых десятичных операндов так, чтобы частное стало допустимым несжатым десятичным числом. AH должен содержать цифру верхнего регистра, а AL - цифру нижнего регистра. Эта инструкция корректирует значение и помещает результат в AL, тогда как AH будет содержать ноль. Обобщенная версия этой инструкции делает возможной подгонку двух несжатых цифр с любым основанием. Правила для операнда такие же, как с инструкцией 'aam'. 'not' инвертирует биты в заданном операнде к форме обратного кода операнда.
Не оказывает влияния на флаги. Правила для операнда таки же, как с инструкцией 'inc'. 'and', 'or' и 'xor' производят стандартные логические операции. Они изменяют флаги SF, ZF и PF. Правила для операнда таки же, как с инструкцией 'add'. 'bt', 'bts', 'btr' и 'btc' оперируют с единичным битом, который может быть в памяти или регистре общего назначения.
Расположения бита определяется как смещение от конца нижнего регистра операнда. Значение смещения берется из второго операнда, это может быть либо регистр общего назначения, либо байт. Эти инструкции первым делом присваивают флагу CF значение выбранного байта. 'bt' больше ничего не делает, 'bts' присваивает выбранному биту значение 1, 'btr' сбрасывает его на 0, 'btc' изменяет значение бита на его дополнение. Первый операнд может быть словом или двойным словом. 1 2 3 4 bt ax, 15; тестирует бит в регистре bts word bx , 15; тестирует и ставит бит в памяти btr ax, cx; тестирует и сбрасывает бит в регистре btc word bx , cx; тестирует и дополняет бит в памяти. Инструкции 'bsf' и 'bsr' ищут в слове или двойном слове первый установленный бит и сохраняют индекс этого бита в операнд-адресат, которым должен быть регистр общего назначения.
Сканируемая строка битов определяется операндом-источником, им может быть либо регистр общего назначения, либо память. Если срока нулевая (ни одного единичного бита), то установливается флаг ZF; иначе он очищается. Если не найдено ни одного установленного бита, значение операнда адресата не определено.
'bsf' сканирует от нижнего регистра к верхнему (начиная с бита с индексом ноль). 'bsr' сканирует от верхнего регистра к нижнему (начиная с бита с индексом 15 в слове или с индекса 31 в двойном слове). 1 2 bsf ax, bx; сканирование регистра по возрастанию bsr axsi ; сканирование памяти в обратном порядке. 'shl' сдвигает операнд-адресат влево на определенное вторым операндом количество битов.
Операндом-адресатом может быть регистр общего назначения или память размером в байт, слово или двойное слово. Вторым операндом может быть непосредственное значение или регистр CL. Процессор 'задвигает' нули справа (с нижнего регистра), и биты 'выходят' слева. Последний 'вышедший' бит запоминается в CF. 'sal' - это не синоним 'shl'.
1 2 3 4 shl al, 1; сдвиг регистра влево на один бит shl byte bx , 1; сдвиг памяти влево на один бит shl ax, cl; сдвиг регистра влево на количество из CL shl word bx , cl; сдвиг памяти влево на количество из CL. 'shr' и 'sar' сдвигают операнд-адресат вправо на число битов, определенное во втором операнде. Правила для операндов такие же, как с инструкцией 'shl'. 'shr' 'задвигает' нули с левой стороны операнда-адресата, биты 'выходят' справа. Последний 'вытолкнутый' бит запоминается в CF.
'sar' сохраняет знак операнда, 'забивая' слева нулями, если значение положительное, и единицами, если значение отрицательное. 'shld' сдвигает биты операнда-адресата влево за заданное в третьем операнде число битов, в то время как справа 'задвигаются' биты верхних регистров операнда-источника. Операнд-источник не изменяется.
Операндом-адресатом может быть регистр общего назначения или память размером в слово или двойное слово, операндом-источником должен быть регистр общего назначения, третьим операндом может быть непосредственное значение либо CL. 1 2 3 4 shld ax, bx, 1; сдвиг регистра влево на один бит shld di , bx, 1; сдвиг памяти влево на один бит shld ax, bx, cl; сдвиг регистра влево на количество из CL shld di , bx, cl; сдвиг памяти влево на количество из CL. 'shrd' cдвигает биты операнда-адресата вправо, в то время как слева 'задвигаются' биты нижних регистров операнда-источника. Операнд-источник остается неизменным.
Правила для операндов такие же, как с инструкцией 'shld'. 'rol' и 'rcl' циклически сдвигают байт, слово или двойное слово влево на число битов, заданное во втором операнде.
Для каждой заданной ротации старший бит, выходящий слева, появляется справа и становится самым младшим битом. 'rcl' дополнительно помещает в CF каждый бит высшего регистра, выходящий слева, перед тем, как он возвратится в операнд как младший бит во время следующего цикла ротации.
Правила для операндов такие же, как с инструкцией 'shl'. 'ror' и 'rcr' циклически сдвигают байт, слово или двойное слово вправо на число битов, заданное во втором операнде.
Для каждой заданной ротации младший бит, выходящий справа, появляется слева и становится самым старшим битом. 'rcr' дополнительно помещает в CF каждый бит низшего регистра, выходящий слева, перед тем, как он возвратится в операнд как старший бит во время следующего цикла ротации. Правила для операндов такие же, как с инструкцией 'shl'. 'test' производит такое же действие, как инструкция 'and', но не изменяет операнд-адресат, только обновляет флаги. Правила для операндов такие же, как с инструкцией 'and'.
'bswap' переворачивает порядок битов в 32-битном регистре общего назначения: биты от 0 до 7 меняются местами с битами от 24 до 31, а биты от 8 до 15 меняются с битами от 16 до 23. Эта инструкция предусмотрена для преобразования значений с прямым порядком байтов к формату с обратным порядком и наоборот. 'jmp' передает управление а заданное место. Адрес назначения может быть определен непосредственно в инструкции или косвенно через регистр или память, допустимый размер адреса зависит от того, какой переход, близкий или дальний, а также от того, какая инструкция, 16-битная или 32-битная. Операнд для близкого перехода должен быть размером 'word' для 16-битной инструкции и размером 'dword' для 32-битной инструкции.
Операнд для дальнего перехода должен быть размером 'dword' для 16-битной инструкции и размером 'pword' для 32-битной инструкции. Прямая инструкция 'jmp' содержит адрес назначения как часть инструкции, операндом, определяющим этот адрес, должно быть числовое выражение для близкого перехода и два числа, разделенные двоеточием, для дальнего перехода, первое определяет номер сегмента, второе - смещение внутри сегмента. Непрямая инструкция 'jmp' получает адрес назначения через регистр или переменную-указатель, операндом должен быть регистр общего назначения или память.
Для более подробной информации смотрите также 1.2.5. 1 2 3 4 jmp 100h; прямой близкий переход jmp 0FFFFh: 0; прямой дальний переход jmp ax; непрямой близкий переход jmp pword ebx ; непрямой дальний переход.
'call' передает управление процедуре, сохраняя в стеке адрес инструкции, следующей за 'call', для дальнейшего возвращения к ней инструкцией 'ret'. Правила для операндов такие же, что с инструкцией 'jmp', но 'call' не имеет короткого варианта в виде прямой инструкции, и поэтому не оптимизирована.
'ret', 'retn' и 'retf' прекращают выполнение процедуры передают управление назад программе, которая изначально вызвала эту процедуру, используя адрес, который был сохранен в стеке инструкцией 'call'. 'ret' это эквивалент 'retn', которая возвращает из процедуры, которая была вызвана с использованием близкого перехода, тогда как 'retf' возвращает из процедуры, которая была вызвана с использованием дальнего перехода. Эти инструкции подразумевают размер адреса, соответствующий текущей установке кода, но этот размер может быть изменен на 16-битный с помощью мнемоников 'retw', 'retnw' и 'retfw' и на 32-битный с помощью 'retd', 'retnd' и 'retfd'. Все эти инструкции могут опционально предписывать непосредственный операнд, если добавить константу к указателю стека, они эффективно удаляют любые аргументы, которые вызывающая программа положила в стек перед выполнением инструкции 'call'.
'iret' возвращает управление прерванной процедуре. Эта инструкция отличается от 'ret' в том, что она также выводит из стека флаги в регистр флагов.
Флаги сохраняются в стек механизмом прерывания. Инструкция подразумевает размер адреса, соответствующий текущей установке кода, но этот размер может быть изменен на 16-битный или на 32-битный с помощью мнемоников 'iretw' или 'iretd'. Условные инструкции перехода осуществляют или не осуществляют передачу управления в зависимости от состояния флагов CPU во время вызова этих инструкций. Мнемоники условных переходов могут быть получены добавлением условных мнемоников (смотри таблицу 3) к символу 'j', например инструкция 'jc' осуществляет передачу управления, если установлен флаг CF. Условные переходы могут быть только близкие и прямые и могут быть оптимизированы (смотри 1.2.5), операндом должно быть число, определяющее адрес назначения.
Таблица 3.1 Условия. Большене меньше и не равно. 'loop' - это условные переходы, которые используют значение из CX (или ECX) для определения количества повторений цикла.
Все инструкции 'loop' автоматически уменьшают на единицу CX (или ECX) и завершают цикл, когда CX (или ECX) равно нулю. CX или ECX используется в зависимости от от текущей установки разрядности кода - 16-ти или 32-битной, но вы можете принудительно использовать CX с помощью мнемоника 'loopw', или ECX с помощью мнемоника 'loopd'. 'loope' и 'loopz' это синонимы этой инструкции, которые работают так же, как стандартный 'loop', но еще завершают работу, если установлен ZF. 'loopew' и 'loopzw' заставляют использовать регистр CX, а 'looped' и 'loopzd' заставляют использовать регистр ECX. 'loopne' и 'loopnz' это тоже синонимы той же инструкции, которые работают так же, как стандартный 'loop', но еще завершают работу, если ZF сброшен на ноль. 'loopnew' и 'loopnzw' заставляют использовать регистр CX, а 'loopned' и 'loopnzd' заставляют использовать регистр ECX.
Каждая инструкция 'loop' требует операндом число, определяющее адрес назначения, причем это может быть только близкий переход (в пределах 128 байт назад и 127 байт вперед от адреса инструкции, следующей за 'loop'). 'jcxz' переходит к метке, указанной в инструкции, если находит в CX ноль, 'jecxz' делает то же, но проверяет регистр ECX. Правила для операндов такие же, как с инструкцией 'loop'.
'int' активирует стандартный сервис прерывания, который соответствует числу, указанному как операнд в мнемонике. Это число должно находиться в пределах от 1 до 255. Стандартный сервис прерывания заканчивается мнемоникой 'iret', которая возвращает управление инструкции, следующей за 'int'. 'int3' кодирует короткое (в один байт) системное прерывание, которое вызывает прерывание 3. 'into' вызывает прерывание 4, если установлен флаг OF. 'bound' проверяет, находится ли знаковое число, содержащееся в указанном регистре в нужных пределах. Если число в регистре меньше нижней границы или больше верхней, вызывается прерывание 5.
Инструкция нуждается в двух операндах, первый - это тестируемый регистр, вторым должен быть адрес в памяти для двух знаковых чисел, указывающих границы. Операнды могут быть размером 'word' или 'dword'.
Строковые операции работают с одним элементом строки. Этим элементом может быть байт, слово или двойное слово. Строковые элементы адресуются регистрами SI и DI (или ESI и EDI).
После каждой строковой операции SI и/или DI (или ESI и/или EDI) автоматически обновляются до указателя на следующий элемент строки. Если DF (флаг направления) равен нулю, регистры индекса увеличиваются, если DF равен единице, они уменьшаются. Число, на которое они увеличиваются или уменьшаются равно 1, 2 или 4 в зависимости от размера элемента строки. Каждая инструкция строковой операции имеет короткую форму без операндов, использующую SI и/или DI если тип кода 16-битный, и ESI и/или EDI если тип кода 32-битный. SI и ESI по умолчанию адрес данных в сегменте, адресованном регистром DS, DI и EDI всегда адресует данные в сегменте, выбранном в ES. Короткая форма образуется добавлением к мнемонику строковой операции буквы, определяющей размер элемента строки, для байта это 'b', для слова это 'w', для двойного слова это 'd'.
Полная форма инструкции требует операнды, указывающие размер оператора, и адрес памяти, которыми могут быть SI или ESI с любым сегментным префиксом, или DI или EDI всегда с сегментным префиксом ES. 'movs' переводит строковый элемент, на который указывает SI (или ESI) в место, на которое указывает DI (или EDI). Размер операнда может быть байтом, словом или двойным словом. Операндом-адресатом должна быть память, адресованная DI или EDI, операндом-источником должна быть память, адресованная SI или ESI с любым сегментным префиксом. 1 2 3 movs byte di si ; переводит байт movs word es: di ss: si ; переводит слово movsd; переводит двойное слово.
'cmps' вычитает строковый элемент-адресат из строкового элемента-источника и обновляет флаги AF, SF, PF, CF и OF, но не изменяет никакой из сравниваемых элементов. Если строковые элементы эквивалентны, устанавливается ZF, иначе он очищается.
Первым операндом этой инструкции должен быть строковый элемент, адресованный SI или ESI с любым сегментным префиксом, вторым операндом должен быть строковый элемент, адресованный DI или EDI. 1 2 3 outs dx, byte si ; вывод байта outsw; вывод слова outs dx, dword gs: esi ; вывод двойного слова Префиксы повторения 'rep', 'repe'/'repz' и 'repne'/'repnz' определяют повторяющуюся строковую операцию. Если инструкция строковой операции имеет префикс повторения, операция выполняется повторно, каждый раз используя другой элемент строки. Повторение прекратится, когда будет выполнено одно из условий, указанных префиксом.
Все три префикса автоматически уменьшают регистр CX или ECX (в зависимости от того, какую адресацию использует инструкция строковой операции, 16-битную или 32-битную) после каждой операции и повторяют ассоциированную операцию, пока CX или ECX не станет равным нулю. 'repe'/'repz' и 'repne'/'repnz' используются только с инструкциями 'scas' и 'cmps' (описанными выше). Когда используются эти префиксы, повторение следующей инструкции зависит также от флага нуля (ZF), 'repe' и 'repz' прекращают выполнение, если ZF равен нулю, 'repne' и 'repnz' прекращают выполнение, если ZF равен единице. Вот еще темы с ответами: начал изучать ассемблер сталкнулся с такой проблемой: перепечатываю пример из книги: org 100h mov ax,0B800h mov es,ax. Я недавно хотел разработать так ради прикола мини ОС с использованием в связке Free Pasal и Flat Assembler. Один вопрос как можно Flat.
Здравствуйте, установил AlphaSkins, но не могу сделать прозрачную sSpeedButton. Кто знает как исправить это? Хочется чтобы так же остались.
Вообщем в delphi в SpeedButton есть свойство flat если true то кнопка прозрачная: и можно тупа прикрутить картинку. Или воспользуйтесь поиском по форуму.