- •Лабораторная работа №1 Компилятор fasm Арифметические операции.
- •Теоретическая часть
- •1. Представление данных в компьютерах
- •1.1. Двоичная система счисления
- •1.2. Биты, байты и слова
- •1.3. Шестнадцатеричная система счисления
- •1.4. Числа со знаком
- •1.5. Логические операции
- •1.7. Организация памяти
- •2. Процессоры Intel в реальном режиме
- •2.1. Регистры процессора
- •2.1.1. Регистры общего назначения
- •1.6. Коды символов
- •2.1.2. Сегментные регистры
- •2.1.3. Стек
- •2.1.4. Регистр флагов
- •2.2.4. Косвенная адресация
- •2.2.5. Адресация по базе со сдвигом
- •2.2.6. Косвенная адресация с масштабированием
- •2.2.7. Адресация по базе с индексированием
- •2.2.8. Адресация по базе с индексированием и масштабированием
- •2.3. Основные непривилегированные команды
- •2.3.2. Двоичная арифметика
- •3. Компилятор fasm
- •Практическая часть
- •Задания для самостоятельной работы
- •Индивидуальные варианты
3. Компилятор fasm
Познакомимся с молодым, стремительно набирающим популярность компилятором FASM (Flat Assembler). Этот компилятор достаточно прост в установке и использовании.
Задание. Запускаем наш FASMW.EXE и набираем в нем код нашей первой программы:
D:\Лаб.раб._103\fasm\fasmw\fasms.exe
Нажмем Run -> Run, или F9 на клавиатуре. В окне сохранения указываем имя файла и папку для сохранения. Желательно привыкнуть сохранять каждую программу в отдельную папку, чтобы в будущем не путаться. Если компилятор выдал ошибку, внимательно перепроверьте указанную им строку. Также необходимо знать, что компилятор чувствителен к регистру, поэтому .data и .Data воспринимаются как две разные инструкции. Если же вы все правильно сделали, то результатом будет простейший MessageBox (рис. 1).
Рис.1.
Рассмотрим текст программы:
В первой строке директивой include мы включили в нашу программу большой текст из нескольких файлов. Директива include как бы вставляет в указанное место текст из другого файла. Автоматически подключили (присоединили) к нашей программе еще и текст из win32a.inc, macro/if.inc, множество макроинструкций и общий набор библиотек функций Windows. Каждый из подключаемых файлов может содержать еще несколько подключаемых файлов, и эта цепочка может продолжаться и далее. При помощи подключаемых файлов мы организуем, некое подобие языка высокого уровня: чтобы избежать длительного описания каждой функции вручную, мы подключаем целые библиотеки описания стандартных функций Windows.
Далее у нас обозначена секция данных — .data. В этой секции мы объявляем две переменные — Caption и Text. Это не специальные команды, поэтому их имена можно изменять, например, a и b (только без пробелов, не используя русский язык и зарезервированные слова).
Команда db означает "определить байт" (define byte). Весь этот текст не поместится в один байт, ведь каждый отдельный символ занимает целый байт. В данном случае этой командой мы определяем переменную-указатель. Она будет содержать адрес, в котором хранится первый символ строки. В кавычках указывается текст строки, причем кавычки по желанию можно ставить и 'такие', и "такие" — главное чтобы начальная кавычка была такая же, как и конечная. Ноль после запятой добавляет в конец строки нулевой байт, который обозначает конец строки (null-terminator).
Во второй строчке в данном конкретном примере можно обойтись и без ноля (удаляем вместе с запятой — иначе компилятор укажет на ошибку), но это сработает лишь потому, что в нашем примере сразу за второй строчкой начинается следующая секция, и перед ее началом компилятор автоматически впишет множество выравнивающих предыдущую секцию нолей.
Примечание. В общих случаях ноли в конце текстовых строк обязательны!
Следующая секция — секция исполняемого кода программы — .code. В начале секции стоит метка start:. Она означает, что именно с этого места начнет исполняться наша программа.
Первая команда — это макроинструкция invoke. Она вызывает встроенную в Windows API-функцию MessageBox. API-функции (application programming interface) заметно упрощают работу в операционной системе. Мы как бы просим операционную систему выполнить какое-то стандартное действие, а она выполняет и по окончании возвращает нам результат проделанной работы. После имени функции через запятую следуют ее параметры. У функции MessageBox параметры такие:
1-й параметр должен содержать «имя-номер» окна-владельца. «Имя-номер» — это что-то вроде личного номера, который выдается операционной системой каждому объекту (процессу, окну и др.). 0 в нашем примере означает, что у окна нет владельца, оно само по себе и не зависит ни от каких других окон.
2-й параметр — указатель на адрес первой буквы текста сообщения, заканчивающегося вышеупомянутым нулем. Чтобы наглядно понять, что это всего лишь адрес, сместим этот адрес на 2 байта прямо в вызове функции: invoke MessageBox,0,Text+2,Caption,MB_OK и убедимся, что теперь текст будет выводиться без первых двух букв.
3-й — указатель адреса первой буквы заголовка сообщения.
4-й — стиль сообщения. Со списком этих стилей вы можете ознакомиться, например, в INCLUDE\EQUATES\ USER32.INC (у Вас этой папки нет). Для этого вам лучше будет воспользоваться поиском в Блокноте, чтобы быстро найти MB_OK и остальные. Кстати, все эти стили можно заменить числом, означающим тот, иной, стиль или их совокупность, например: MB_OK + MB_ICONEXCLAMATION. В USER32.INC указаны шестнадцатеричные значения. Некоторые стили не могут использоваться одновременно — например, MB_OKCANCEL и MB_YESNO. Причина в том, что сумма их числовых значений (1+4=5) будет соответствовать значению другого стиля — MB_RETRYCANCEL.
Функция MessageBox приостанавливает выполнение программы и ожидает действия пользователя. По завершении функция возвращает программе результат действия пользователя, и программа продолжает выполняться.
Вызов функции ExitProcess завершает процесс нашей программы. Эта функция имеет лишь один параметр — код завершения. Обычно, если программа нормально завершает свою работу, этот код равен нулю.
Последняя строка нашего кода — .end start, — завершение текущей секции.
