|
Ушел с форума
16374 / 7686 / 1080
Регистрация: 11.11.2010
Сообщений: 13,761
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 10.11.2013, 18:31 [ТС] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
ГЛАВА 4 Разработка программы включает несколько этапов:ЭТАПЫ СОЗДАНИЯ ПРОГРАММЫ НА ЯЗЫКЕ АССЕМБЛЕРА
Рис. 4.1. Этапы разработки программ на ассемблере Подготовка текста программы Использование стандартных редакторов При использовании стандартных редакторов текста необходимо сохранять редактируемые файлы с текстами программ в виде обыкновенных файлов в формате ASCII, то есть без дополнительных символов форматирования, которые вставляются в текст специализированными редакторами, например Word. Иногда используются специализированные текстовые редакторы для программистов, с разноцветной подсветкой синтаксиса, автоматической нумерацией строк, всплывающими подсказками и тому подобными «наворотами», но пишущие на различных диалектах ассемблера придерживаются аскетичных принципов в создании программ и, как правило, обходятся простейшим текстовым редактором и работой с командной строкой.Ассемблирование программы Подготовленный текст является исходными данными для специальных программ, называемых ассемблерами. Задача ассемблеров – преобразовать текст программы в форму двоичных команд, которые могут быть выполнены микропроцессором. Если обнаружены синтаксические ошибки, то результирующий код создан не будет. Процесс создания исполняемого файла происходит в две стадии:.asm -> .obj -> .exe/.dll/.com На первой стадии (.asm -> .obj) из ассемблерного файла путем компиляции получаются файлы промежуточного объектного кода, имеющего расширение .obj (при этом могут использоваться дополнительные inc-файлы). Файл с расширением .obj содержит машинный код при условии, что не встретились синтаксические и семантические ошибки. Если в исходном файле с программой на языке ассемблера обнаруживаются ошибки, то программисту выдается список обнаруженных ошибок, в котором ошибки указываются с номером строки, в которой они обнаружены. Программист циклически выполняет действия по редактированию и компиляции до тех пор, пока не будут устранены все ошибки в исходном файле. На этом этапе уже возможно получение готовой программы, но чаще всего в ней не хватает некоторых компонентов. Если компилятор по какой-либо причине (неверно прописан путь к такому файлу или файл отсутствует) не может найти inc-файл, то выдается предупреждение и obj-файл получен не будет.Ассемблирование, как правило, проходит в два приема. При первом проходе переводятся мнемонические команды, десятеричные числа и символы в соответствующие машинные коды, подсчитывается, сколько какая команда занимает места, обнаруженные имена, введенные пользователем (константы, метки, переменные) их тип и числовое значение записывается в таблицу. В эту же таблицу записывается, с каких адресов начинаются процедуры, адреса меток, адреса начала/конца сегментов и т. д., при втором проходе подставляются адреса начала процедур, заменяются названия меток на адреса. В результате ассемблирования получается так называемый «объектный файл». В качестве дополнительной возможности ассемблер может создать файл листинга программы. Обычно для получения файлов объектного кода необходимо выполнить соответствующую программу ассемблера (программы MASM.EXE и ML.EXE фирмы Microsoft и TASM.EXE или TASM32.EXE фирмы Borland), указав в командной строке имя файла с текстом программы. Например, если у текстового файла с исходным текстом программы название prog.asm.
или
Компоновка программы Следующая стадия (.obj -> .exe/.dll/.com) называется линковкой или компоновкой и служит для замещения символьных имен, используемых программистом, на реальные адреса.Сравните шестнадцатеричное содержимое OBJ и EXE файла, который у вас получился. В EXE-файле присутствует та же последовательность байтов, что и в OBJ-файле. Но помимо этого еще присутствует: имя ассемблированного файла, версия ассемблера, «имя собственное» сегмента и так далее. Это «служебная» информация, предназначенная для тех случаев, когда ваш исполнимый файл вы хотите собрать из нескольких. При разработке больших приложений исходный текст состоит, как правило, из нескольких модулей (файлов с исходными текстами), потому что хранить все тексты в одном файле неудобно – в них сложно ориентироваться. Каждый модуль по раздельности компилируется в отдельный файл с объектным кодом. В каждом из этих файлов прописаны свои сегменты кода/данных/стека, которые затем надо объединить в одно целое. А исполнимый файл нам нужно получить только один – с единым сегментом кода/данных/стека. Именно это LINK и делает: завершает определение адресных ссылок и объединяет, если это требуется, несколько программных модулей в один. И этот один у нас и является исполнимым. Кроме того, к нашим модулям надо добавить машинный код подпрограмм, реализующих различные стандартные функции (например, вычисляющих математические функции SIN или LN). Такие функции содержатся в библиотеках (файлах со стандартным расширением .LIB), которые либо поставляются вместе с компилятором, либо создаются самостоятельно. Поэтому процесс подготовки обязательно включает в себя этап компоновки, когда определяются все неизвестные при раздельном ассемблировании адреса совместно используемых переменных или функций. Процесс объединения объектных модулей в один файл осуществляется специальной программой-компоновщиком или сборщиком (программа LINK.EXE фирмы Microsoft и TLINK.EXE фирмы Borland), которая выполняет связывание объектных модулей и машинного кода стандартных функций, находя их в библиотеках, и формирует на выходе работоспособное приложение – исполнимый код для конкретной платформы. Исполнимый код – это законченная программа с расширением COM, DLL или EXE, которую можно запустить на компьютере с установленной операционной системой, для которой эта программа создавалась. Имя исполняемого файла задастся именем первого .OBJ файла:
Возможно потребуется LST-файл, особенно, если необходимо проверить сгенерированный машинный код. CRF-файл полезен для очень больших программ, где необходимо видеть, какие команды ссылаются на какие поля данных. Кроме того, ассемблер генерирует в LST-файле номера строк, которые используются в CRF-файле. Листинг содержит не только исходный текст, но также слева транслированный машинный код в шестнадцатиричном формате. В самой левой колонке находятся шестнадцатеричные адреса команд и данных. За листингом ассемблирования программы следует таблица идентификаторов. Первая часть таблицы содержит определенные в программе сегменты и группы вместе с их размером в байтах, выравниванием и классом. Вторая часть содержит идентификаторы - имена полей данных в сегменте данных и метки, назначенные командам в сегменте кодов В MAP-файле перечисляются имена. адреса загрузки и размеры всех сегментов, входящих в программу. В нем также приводятся имена и адреса загрузки каждой группы в программе, начальный адрес программы и сообщения о тех или иных ошибках, которые могли иметь место. Если в командной строке LINK задана опция /MAP, то в map-файле перечисляются имена и адреса загрузки всех обобщенных символов. Загрузка программы Компонент операционной системы, называемый загрузчиком (loader), считывает данные из исполняемого файла, загружает программу в память и передает управление по адресу точки входа. В результате программа начинает выполняться.В тех случаях, когда при написании новой программы на языке ассемблера требуются лишь незначительные изменения машинных кодов, иногда быстрее и удобнее внести изменения непосредственно в объектный файл, а не проходить всю цепочку редактирования исходной программы и осуществлять ее повторную трансляцию с внесенными изменениями. Для этого существуют специальные шестнадцатеричные редакторы (типа Hacker Viewer), которые позволяют рассматривать файлы с бинарным (машинным) кодом в виде последовательности ассемблерных команд. Эту же технологию применяют в тех случаях, если исходный текст программы не доступен (взлом программы). Отладка программы До тех пор пока Вы не наберетесь достаточного опыта в программировании на языке ассемблера, за исключением учебных, тривиальных программ, в отладке будет нуждаться любая ваша программа. Для этого используются различные отладчики (CodeView фирмы Microsoft, Turbo Debugger фирмы Borland, SoftIce фирмы NuMega, OllyDebug написанный Olech Yuschuk), позволяющие в процессе выполнения программы контролировать значения регистров или переменных, при необходимости изменять их. Можно просматривать содержимое различных участков памяти. Можно выполнять программы по шагам или расставить точки останова (BREAK POINTS), которые вызовут прекращение работы программы и переход управления к отладчику.Использование интегрированных сред Для подготовки текста программы на языке ассемблера очень удобно использование интегрированных программных сред. Такие возможности предоставляются практически всеми разработчиками ассемблеров, например: PWD – Programmer Workbench для компиляторов masm, QC – Quick C для компиляторов QuickAssembler фирмы Microsoft, все компиляторы языка C и C++ фирмы Borland (TC и BC). Интегрированные среды позволяют получить быстрый доступ к справочной информации. Можно сразу же ассемблировать и скомпоновать набранный текст, провести его отладку, а затем вновь вернуться к редактированию. Структура программы Как вы увидите в следующих главах, язык ассемблера заставляет нас помещать определенное количество строк в качестве заголовка программ, которые мы пишем. Другими словами, нам нужно каждый раз записывать несколько псевдооператоров, которые сообщают языку ассемблера основную информацию. В качестве рекомендации на будущее ниже приведен абсолютный минимум, необходимый для программ, которые вы пишите:
Директива описания типа микропроцессора Модель памяти задается директивой .model
Строка .model flat говорит, что будет создаваться exe-файл для 32-разрядной операционной системы Windows. Плоская (flat) модель памяти 32-разрядной Windows располагает три сегмента (сегмент кода, стека и данных) в едином четырехгигабайтном адресном пространстве, позволяя вообще забыть о существовании сегментов. Но для 16-разрядных приложений MS-DOS и Windows 3.x максимально допустимый размер сегментов составляет всего лишь 64 килобайта, что явно не допустимо для большинства приложений. В крошечной (tiny) модели памяти сегмент кода, стека и данных также расположены в едином 64-килобайтном адресном пространстве, но в отличие от плоской модели это адресное пространство чрезвычайно ограничено в размерах, поэтому и код, и стек, и данные более серьезных приложений приходилось размещать в нескольких сегментах (модели памяти small, medium, compact, large, huge, tchuge). В этих моделях памяти, например, для вызова функции недостаточно было знать ее смещение, а требовалось указать еще и сегмент, в котором функция была расположена. Команды передачи управления переходы (jmp) и вызовы (call) в этих моделях памяти могут быть близкими (near) и дальними (far). Если вы пишете программы для 32/64-разрядной операционной системы Windows, то о других моделях памяти кроме flat можно забыть со спокойной совестью. Для адресации четырех гигабайтов виртуальной памяти, выделенной в распоряжение процесса, Windows использует два селектора, один из которых загружается в сегментный регистр CS, а другой в регистры DS, ES и SS. Оба селектора ссылаются на один и тот же базовый адрес памяти, равный нулю, и имеют идентичные лимиты, равные четырем гигабайтам. Windows использует еще и регистр FS, в который загружается селектор сегмента, содержащего информационный блок потока TIB. Фактически существует всего один сегмент, вмещающий в себя и код, и данные, и стек процесса. Благодаря этому передача управления коду, расположенному в стеке, осуществляется близким (near) вызовом или переходом. Отличия между регионами кода, стека и данных заключаются в атрибутах принадлежащих им страниц страницы кода допускают чтение и исполнение, страницы данных чтение и запись, а страницы стека чтение, запись и исполнение одновременно. Допустим у нас есть логический адрес 0137:00456789h. Чтобы этот адрес перевести в линейный – в селекторе 137 находится соответствующий ему дескриптор в таблице дескрипторов: база = 0, граница = 0FFFFFFFFh, следовательно, линейный адрес равен 0 (база) + 00456789h. Однако линейный адрес не является физическим адресом. Для его получения используется третья ступень – страничная адресация. То есть 20 старших бит линейного адреса используются для выбора 4 Kбайт памяти из каталога страниц, оставшиеся 12 бит представляют смещение внутри полученной страницы (в качестве упражнения рекомендую написать небольшую программу под 32-разрядной Windows, которая будет показывать сегментные регистры, значения дескрипторов для каждого селектора, базу, границу, RPL и т.п). В 32-разрядной Windows и сегмент кода, и сегмент данных и стека приложения имеют одинаковые базу и границу (0 и 0FFFFFFFFh). Это называется плоской (FLAT) моделью памяти. Хотя cs и ds имеют разные значения и дескрипторы, они указывают на одно и то же линейное адресное пространство 0..0FFFFFFFFh. Следовательно, логические адреса cs:12345678 и ds:12345678 совпадают. Есть возможность модифицировать код при помощи mov byte ptr $+8,21h (секция кода должна быть помечена как writeable). В данном случае в инструкции mov неявно подразумевается ds:, в который можно писать. Однако, при попытке сделать mov cs:xxxxxxxx, получим исключение (сегментная защита). В сегмент кода писать нельзя, но зато можно писать в сегмент данных, который «совпадает» с сегментом кода, и тем самым модифицировать код. А теперь вспомним про страничную защиту. Именно она используется в Windows, когда Вы задаете атрибуты секций PE-файла (.data, .code и т.д). Собственно, к сегментам памяти они не имеют отношения, посему когда речь идет о Win32, не путайте понятия секций PE-файлов и сегментов памяти! Когда Windows грузит РЕ-файл, она смотрит атрибуты секций и соответственно им устанавливает «защиту» страниц памяти, в которые будет загружена секция. Это и есть типа страничная защита. Помимо этого каждая страница имеет специальный флаг, определяющий уровень привилегий, необходимых для доступа к этой странице. Некоторые страницы, например, те, что принадлежат операционной системе, требуют наличия прав супервизора, которыми обладает только код нулевого кольца. Прикладные программы, исполняющиеся в кольце 3, таких прав не имеют и при попытке обращения к защищенной странице порождают исключение. Директива .model В третьей строчке написано .code. По этой команде (директиве) будет определен сегмент кода. Это нужно, потому что у реальных программ код (команды) и данные (переменные) должны быть разделены. Если Вы хотите в каком-либо месте программы вставить данные, то пишите .data, а потом уже сами данные (но их можно и не разделять). Я рекомендую вставлять данные между командами ret и end start. start: – это место, где находится точка входа в программу. На языке ассемблера всегда надо помечать место, где находится начало программы (первая команда). Строка ret нужна, чтобы выйти из программы – если бы ее не было, то программа бы «завесила» компьютер. Последняя строчка end start завершает текст исходной программы.
Пишем первую программу на языке ассемблера Итак это была теория. А вот это практика. Попробуем написать программу на языке ассемблера самостоятельно. Все что вам нужно это компьютер и набор программ masm32.Сначала наберем с помощью текстового редактора вот такой файл:
Мой компьютер->Сервис->Свойства папки->Типы файлов->Создать Если все набрано правильно, то в текущем каталоге появится файл с именем исходника, но с расширением .exe. Запускаем его и видим результат. Контрольные вопросы
12
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Новые блоги и статьи
|
|||
|
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров
В текущей версии модели успешно реализован ключевой механизм. . .
|
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям
Реализованные компоненты:
Механизм закисления почвы через протонную помпу
Конкуренция между типами микориз
pH как триггер сукцессии
C/ P соотношение. . .
|
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
|
Решил проблему с ошибкой пагинации сообщений с сервера на алгоритме обхода дерева "Эстафета хвоста".
Hrethgir 12.07.2026
Проблема была в том, что удалялась именно новая кнопка, а не старая. Ни один ИИ не обнаружил это, а сам я смог только когда с работой стало попроще и когда заставил работать будущее автономное. . .
|
|
сукцессия 25. Хронология ошибок
anaschu 12.07.2026
# От 50-тонного гриба до устойчивого леса: хроника ошибок при построении модели вековой сукцессии микоризы
## О чём эта статья
В процессе построения ОДУ-модели (система дифференциальных. . .
|
сукцессия 24. Промежуточное общее описание модели
anaschu 12.07.2026
Хендофф: модель АМ→ЭКМ сукцессии микоризы (ризосфера, 50 лет)
Содержание проекта
Симуляция вековой (50 лет) экологической сукцессии в почве леса
Основные участники: АМ-гриб, ЭКМ-гриб,. . .
|
сукцессия 23. Более физиологичная физиология, более экологичная экология, более диффурные диффуры.
anaschu 12.07.2026
Что реально нашли и починили за эти 5 часов
Правило Линдемана (КПД конверсии сахара в тело, kEff) — раньше 100% полученного углерода шло прямо в биомассу гриба; теперь только kEff=0. 5 (после. . .
|
сукцессия 22. От артефактов к физиологии: калибровка агентной модели грибной сукцессии для воспроизведения сезонной динамики и pH-плато
anaschu 11.07.2026
Аннотация
В данной работе представлена калибровка агентной модели динамики грибных сообществ (fungal-succession), направленная на устранение нефизичных артефактов (коллапс биомассы, мгновенное. . .
|