Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
АССЕМБЛИРОВАНИЕ И ВЫПОЛНЕНИЕ ПРОГРАММЫ
Ввод программы В разделе рассмотрено, как ввести в компьютер исходный ассемблерный текст программы, как осуществить ассемблирование, компоновку и выполнение программы. Кроме того, показана генерация таблицы перекрестных ссылок для целей отладки. На рис. 1.2 был показан только исходный текст программы, предназначенный для ввода с помощью текстового редактора. Теперь можно использовать DOS EDIT или другой текстовой редактор для ввода этой программы. Для ввода исходной программы EXASM1 наберите команду EDIT EXASM1.ASM [ Return ] При работе в интегрированной среде NORTOT можно пользоваться встроенным редактором NCEDIT.EXE. Для вызова используется кнопка F4. После ввода программы убедитесь в ее правильности. Можно проверить наличие программы в каталоге на диске введением DIR EXASM1.ASM (для одного файла). Программа EXASM.ASM еще не может быть выполнена, так как необходимо провести ее ассемблирование и компоновку. В следующем разделе показана эта же программа после ассемблирования и пояснены этапы ассемблирования и получения листинга. Подготовка программы для выполнения После ввода на диск исходной программы под именем EXASM1.ASM необходимо проделать два основных шага, прежде чем программу можно будет выполнить. Сначала необходимо ассемблировать программу, а затем выполнить компоновку. Шаг ассемблирования включает в себя трансляцию исходного кода в машинный объектный код и генерацию OBJ-модуля. Формат OBJ-модуля уже более приближен к исполнительной форме, но еще не готов к выполнению. Шаг компоновки включает преобразование OBJ-модуля в ЕХЕ-модуль (исполнимый), содержащий машинный код. Программа LINK, находящаяся на диске DOS, осуществляет следующее: 1. Завершает формирование в OBJ-модуле адресов, которые остались неопределенными после ассемблирования. Во многих следующих программах такие адреса ассемблер отмечает как ----R. 2. Компонует, если необходимо, более одного отдельно ассемблированного модуля в одну загрузочную (выполнимую) программу. Это, возможно, две или более ассемблерных программы или ассемблерная программа и программы, написанные на языках высокого уровня, таких как ПАСКАЛЬ или БЕЙСИК. 3. Инициализирует ЕХЕ-модуль командами загрузки для выполнения. После компоновки OBJ-модуля (одного или более) в ЕХЕ-модуль можно выполнить ЕХЕ-модуль любое число раз. Но, если необходимо внести некоторые изменения в ЕХЕ-модуль, следует скорректировать исходную программу, ассемблировать ее в другой OBJ-модуль и выполнить компоновку OBJ-модуля в новый ЕХЕ-модуль. Даже если эти шаги пока остаются непонятными, вы обнаружите, что, приобретя некоторые навыки, весь процесс подготовки ЕХЕ-модуля можно будет довести до автоматизма. 3.3. Ассемблирование программы Для того чтобы выполнить исходную ассемблерную программу, необходимо прежде провести ее ассемблирование и затем компоновку. На диске с ассемблерным пакетом имеются две версии ассемблера: ASM.ЕХЕ – сокращенная версия с отсутствием некоторых незначительных возможностей, TASM.EXE – полная версия. Если размеры памяти позволяют, то используйте версию MASM (подробности см. в соответствующем руководстве по ассемблеру). Простейший вариант вызова программы – ввод команды TASM, что приведет к загрузке программы ассемблера с диска в память. На экране появится: source filename [.ASM ]: object filename [ filename.OBJ ]: source listing [ NUL.LST ]: cross-reference [ NUL.CRF ]: Курсор при этом расположится в конце первой строки, где необходимо указать имя файла. Не следует набирать тип файла ASM, так как ассемблер подразумевает это. Во втором запросе предполагается аналогичное имя файла (но можно его заменить). Третий запрос предполагает, что листинг ассемблирования программы не требуется. Последний запрос предполагает, что листинг перекрестных ссылок не требуется. Для получения листинга на дисководе В наберите В: и нажмите Return. Если вы хотите оставить значения по умолчанию, то в трех последних запросах просто нажмите клавишу Return. Выполнить ассемблирования возможно, набрав командную строку: TASM EXASM1.ASM или TASM EXASM1.ASM/L При этом во втором случае сформируется файл EXASM1.LST с листингом программы, в котором будут сообщены все ошибки. Пример листинга программы на рис. 3.1. Turbo Assembler Version 2.5 03/12/00 12: 05: 20 Page 1 exasm1.asm
1 0000 STACKSG SEGMENT PARA STACK 'Stack' 2 0000 0C*(53 54 41 43 4B + DB 12 DUP ( 'STACKSEG' ) 3 53 45 47) 4 0060 STACKSG ENDS 5 6; ---------------------------------------------------------------------------------------- 7 0000 CODESG SEGMENT PARA 'Code' 8 0000 BEGIN PROC FAR 9 ASSUME SS: STACKSG, CS: CODESG, DS: NOTHING 10 0000 B8 0123 MOV AX, 0123H ; 3аписать 0123 в АХ. Рис.3.1. Пример листинга программы 11 0003 05 0025 ADD AX, 0025H ; Прибавить 25 к AX. 12 0006 8B D8 MOV BX, AX; Переслать AX в BX. 13 0008 03 D8 ADD BX, AX; Прибавить BX к AX. 14 000A 8B CB MOV CX, BX; Переслать BX в CX. 15 000C 2B C8 SUB CX, AX; Вычесть AX из CX. 16 000E B8 4C00 MOV AX, 4C00H 17 0011 CD 21 INT 21H; Возврат в DOS. 18 0013 BEGIN ENDP; Конец процедуры. 19 0013 CODESG ENDS; Конец сегмента. 20 END BEGIN; Конец программы. Turbo Assembler Version 2.5 03/12/00 12: 05: 20 Page 2 Symbol Table
Symbol Name Type Value
?? DATE Text " 03/12/00" ?? FILENAME Text " exasm1 " ?? TIME Text " 12: 05: 20" ?? VERSION Number 0205 @CPU Text 0101H @CURSEG Text CODESG @FILENAME Text EXASM1 @WORDSIZE Text 2 BEGIN Far CODESG: 0000
Groups & Segments Bit Size Align Combine Class
CODESG 16 0013 Para none CODE STACKSG 16 0060 Para Stack STACK Рис. 3.1. Окончание Ассемблер преобразует исходные команды в машинный код и выдает на экран сообщения о возможных ошибках. Типичными ошибками являются нарушения ассемблерных соглашений по именам, неправильное написание команд (например MOVE вместо MOV), а также наличие в операндах неопределенных имен. Ассемблер делает попытки скорректировать некоторые ошибки, но в любом случае следует перезагрузить текстовый редактор, исправить исходную программу (EXASM1.ASM) и повторить ассемблирование. Листинг содержит не только исходный текст, но также в левой части транслированный машинный код в шестнадцатеричном формате. В самой левой колонке находятся шестнадцатеричные адреса команд и данных. Сегмент стека начинается с относительного адреса 0000. В действительности он загружается в память в соответствии с адресом в регистре SS и нулевым смещением относительно этого адреса. Сегмент кода также начинается с относительного адреса 0000. Он загружается в память в соответствии с адресом в регистре CS и нулевым смещением относительно этого адреса. Поскольку ASSUME является директивой ассемблеру, то первая команда, генерирующая машинный код, – это MOV AX, 0123H. Последняя команда END содержит операнд BEGIN, который имеет отношение к имени команды PROC по смещению 0000. Это адрес сегмента кодов, с которого начинается выполнение после загрузки программы. Таблица идентификаторов За листингом ассемблирования программы следует таблица идентификаторов. Первая часть таблицы содержит определенные в программе сегменты и группы вместе с их размерами в байтах, выравниванием и классом. Вторая часть содержит идентификаторы – имена полей данных в сегменте данных (в нашем примере их нет) и метки, назначенные командам в сегменте кодов (одна в нашем примере). Для того чтобы ассемблер не создавал эту таблицу, следует указать параметр /N вслед за командой MASM, т. е. MASM/N.
Двухпроходный ассемблер В процессе трансляции исходной программы ассемблер делает два просмотра исходного текста. Одной из основных причин этого являются ссылки вперед. Это происходит в том случае, когда в некоторой команде кодируется метка, значение которой еще не определено ассемблером. В первом проходе ассемблер просматривает всю исходную программу и строит таблицу идентификаторов, используемых в программе, т. е. имен полей данных и меток программы и их относительных адресов в программе. В первом проходе подсчитывается объем объектного кода, но сам объектный код не генерируется. Во втором проходе ассемблер использует таблицу идентификаторов, построенную в первом проходе. Так как теперь уже известны длины и относительные адреса всех полей данных и команд, то ассемблер может сгенерировать объектный код для каждой команды. Ассемблер создает, если требуется, файлы OBJ, LST и CRF. Компоновка программы Если в результате ассемблирования не обнаружено ошибок, то следующий шаг – компоновка объектного модуля. Файл EXASM1.OBJ содержит только машинный код в шестнадцатеричной форме. Так как программа может загружаться почти в любое место памяти для выполнения, то ассемблер может не определить все машинные адреса. Кроме того, могут использоваться другие подпрограммы для объединения с основной. Назначением программы LINK является завершение определения адресных ссылок и объединение (если требуется) нескольких программ: TLINK EXASM.OBJ На данном этапе единственной возможной ошибкой может быть указание неправильных имен файлов. Исправить это можно только перезапуском программы LINK.
Выполнение программы После ассемблирования и компоновки программы можно ее выполнить. На рис. 3.2 приведена схема команд и шагов для ассемблирования, компоновки и выполнения программы EXASM1. Если ЕХЕ-файл находится на диске C, то выполнить ее можно командой: C: \EXASM1.EXE или C: \EXASM1 DOS предполагает, что файл имеет тип ЕХЕ (или СОМ), и загружает файл для выполнения. Но так как наша программа не вырабатывает видимых результатов, выполним ее трассировкой под отладчиком DEBUG или TURBO DEBUG. Рис. 3.2. Схема ассемблирования, компоновки и выполнения программы Пример исходной программы Особенность программы, приведенной на рис. 3.1, состоит в том, что она не содержит определения данных. Обычно все программы имеют определенные константы, рабочие поля для арифметических вычислений и области для операций ввода-вывода. На рис. 3.3 приводится программа, написанная на языке Ассемблер и для краткости уже ассемблированная. Эта программа знакомит с несколькими новыми особенностями. 1 page 60, 132 2 TITLE EXASM2 ( EXE ) Операции пересылки и сложения. 3; ------------------------------------------------------------------------------------------- 4 0000 STACKSG SEGMENT PARA STACK ‘Stack’ 5 0000 20 [ DW 32 DUP (? ) 6? ? ? ? 7 ] 9 0040 STACKSG ENDS 10; ------------------------------------------------------------------------------------------- 11 0000 DATASG SEGMENT PARA ‘Data’ 12 0000 00FA FLDA DW 250 13 0002 007D FLDB DW 215 14 0004???? FLDC DW? 15 0006 DATASG ENDS 16; ------------------------------------------------------------------------------------------- 17 0000 CODESG SEGMENT PARA ‘Code’ 18 0000 BEGIN PROC FAR 19 ASSUME CS: CODESG, DS: DATASG, SS: STACKSG, ES: NOTHING 20 0000 1E PUSH DS; 3аписать DS в стек. 21 0001 2B C0 SUB AX, AX; 3аписать в стек. 22 0003 50 PUSH AX; Нулевой адрес. Рис. 3.3. Листинг ассемблирования программы с сегментом данных 23 0004 B8 ---- R MOV АХ, DATASG; Поместить адрес. 24 0007 8E D8 MOV DS, AX; DATASG в регистр DS. 26 0009 A1 0000 R MOV AX, FLDA; Переслать 0250 в AX. 27 000C 03 06 0002 R ADD AX, FLDB; Прибавить 0125 к AX. 28 0010 A3 0004 R MOV FLDC, AX; Записать сумму в FLDC. 29 0013 CB RET; Вернуться в DOS. 30 0014 BEGIN ENDP 31 0014 CODESG ENDS 32 END BEGIN ------------------------------------------------------------------------------------------------------- Segments and Groups: Name Size Align Combine Class CODESG....................................0014 PARA NONE ‘CODE’ DATASG....................................0006 PARA NONE ‘DATA’ STACKSG..................................0040 PARA STACK ‘STACK’ Symbols: Name Type Value Attr BEGIN........................................F PROC 0000 CODESG Length=0014 FLDA..........................................L WORD 0000 DATASG FLDB..........................................L WORD 0002 DATASG FLDC..........................................L WORD 0004 DATASG Рис. 3.3. Окончание
Сегмент стека содержит директиву DW (Define Word), описывающую 32 слова, в которых генерируется неопределенное значение, обозначенное знаком вопроса (? ). Определение размера стека в 32 слова является наиболее реальным, так как в больших программах может потребоваться много «прерываний» для ввода-вывода и вызова подпрограмм – все они используют стек. Определение стека дублированием константы ‘STACKSEG’ в примере на рис. 1.2 необходимо лишь для удобства при работе с отладчиком DEBUG. 3амечание. Определяйте размер стека не менее, чем в 32 слова. При малых размерах стека ни ассемблер, ни компоновщик не смогут определить этого, и выполнение программы может разрушиться самым непредсказуемым образом. На рис. 3.3 определен сегмент данных DATASG, начинающийся по относительному адресу 0000. Этот сегмент содержит три значения в формате DW. Поле FLDA определяет слово (два байта), содержащее десятичное значение 250, которое ассемблер транслирует в шестнадцатеричное 00FA (см. на рис. 3.3 слева). Поле FLDB определяет слово с десятичным значением 125, которое транслируется в шестнадцатеричное 007D. Действительные значения этих двух констант в памяти FA00 и 7D00 соответственно, что можно проверить с помощью отладчика DEBUG. Поле FLDC определяет слово с неизвестным значением, обозначенным знаком вопроса (? ). Сегмент кода в данном примере имеет имя CODESG и отличается новыми особенностями, связанными с сегментом данных. Во-первых, директива ASSUME указывает на определение DATASG через регистр DS. Данной программе не требуется регистр ES, но некоторые программисты описывают его для стандартизации. Во-вторых, после команд PUSH, SUB и PUSH, которые инициализируют стек, следуют две команды, обеспечивающие адресацию сегмента данных: 0004 В8 ---- R MOV AX, DATASG 0007 8Е D8 MOV DS, AX Первая команда MOV загружает сегмент DATASG в регистр AX. На самом деле, поместить в регистр AX весь сегмент 64 Кб нельзя, поэтому команда загружает лишь начальный адрес сегмента DATASG. Обратите внимание на машинный код слева: В8 ---- R Четыре дефиса говорят о том, что ассемблер не может определить адрес DATASG, он определяется лишь тогда, когда объектная программа будет скомпонована и загружена для выполнения. Поскольку загрузчик может расположить программу в любом месте памяти, ассемблер оставляет данный адрес открытым и показывает это символом R. Компоновщик должен будет подставить в это место действительный адрес. Вторая команда MOV пересылает содержимое регистра АХ в регистр DS. Таким образом, данная программа имеет директиву ASSUME, которая соотносит регистр DS с сегментом данных, и команды, инициализирующие регистр DS относительным адресом DATASG. Могут возникнуть два вопроса по поводу этой программы. Во-первых, почему не использовать одну команду для инициализации регистра DS, например: MOV DS, DATASG? Дело в том, что не существует команд для непосредственной пересылки данных из памяти в регистр DS. Следовательно, для инициализации DS необходимо кодировать две команды. Во-вторых, почему программа инициализирует регистр DS, а регистры SS и CS нет? Оказывается, регистры SS и CS инициализируются автоматически при загрузке программы для выполнения, а ответственность за инициализацию регистра DS и, если требуется, ES лежит полностью на самой программе. Пока все эти требования могут показаться весьма туманными, но сейчас не нужно понимать их. Все последующие программы используют аналогичную стандартную инициализацию стека и сегмента данных. Поэтому можно просто копировать данные коды для каждой новой программы. Действительно, вы можете сохранить на диске стандартную часть программы, а для каждой новой программы копировать эту часть с новым именем и, используя редактор, записать дополнительные команды. В качестве упражнения создайте с помощью вашего редактора программу, приведенную на рис. 3.3, выполните ее ассемблирование и компоновку. Затем с помощью отладчика TURBO DEBUGGER просмотрите сегмент кодов, сегмент данных, регистры и проделайте пошаговое выполнение программы. ОТЛАДЧИК TURBO DEBUGGER Turbo Debugger – это современный отладчик, позволяющий отлаживать программы на уровне исходного текста и предназначенный для программистов, работающих на языках семейства Turbo фирмы Borland, и для программистов, работающих на других языках и желающих иметь более мощную среду отладки. Многочисленные, перекрывающие друг друга окна, а также сочетание спускающихся и раскрывающихся меню обеспечивают быстрый интерактивный пользовательский интерфейс. Интерактивная контекстнозависимая система подсказки обеспечит вас подсказкой на всех стадиях работы. 4.1. Навигация по диалоговым блокам Навигация по диалоговым блокам выполняется при помощи клавиш Tab и Shift-Tab. По набору селективных кнопок можно перемещаться при помощи клавиш-стрелок, изменяющих текущую выбранную кнопку. Если у вас есть мышь, то навигация по блокам диалога даже упрощается. Нужно просто нажать кнопку на нужном элементе. Для того чтобы закрыть блок диалога, нажмите кнопку над верхним левым углом. Использование окон Всю информацию и данные Turbo Debugger отображает в меню (локальных и глобальных), блоках запроса (в которые информацию вводит пользователь) и в окнах. Используются различные виды окон в зависимости от того, какого типа информация в них отображается. Все окна открываются и закрываются с помощью команд меню или активных клавиш, соответствующих этим командам. Большая часть окон отладчика Turbo Debugger вызывается из спускающегося меню View (просмотр). Из этого меню вызывается 14 видов окон. Имеется и окно другого типа, которое называется окном проверки (Inspect) и открывается выбором пункта Data|Inspect или пункта Inspect из большинства локальных меню. Окна, вызываемые из меню View Breakpoints Stack Log Watches Variables Module... F3 File... CPU Dump Registers Numeric processor Execution history Hierarchy Another Ниже приведено описание 13 видов окон, которые можно открыть, вызвав соответствующие команды из меню View (просмотр). Если вы открыли одно такое окно или более, вы можете перемещать их, изменять размеры, закрывать и управлять этими окнами самыми различными способами при помощи команд меню Window или (System), рассматриваемых в разделе " Работа с окнами". Окно модуля (Module) Данное окно отображает текст программы, которую вы отлаживаете. Вы можете перемещаться по всему модулю и проверять данные и код, указывая имена переменных курсором и выполняя соответствующие команды локальных меню. По всей вероятности, на работу в этом окне вы будете затрачивать больше всего времени, поэтому постарайтесь изучить все команды локальных меню для этого окна. Для того чтобы открыть окно модуля можно также использовать клавишу F3.
Окно слежения (Watches) Отображает переменные и их изменяющиеся значения. Для того чтобы занести переменную в это окно, надо установить на нее курсор и нажать клавиши Ctrl-W. Популярное:
|
Последнее изменение этой страницы: 2016-05-28; Просмотров: 3072; Нарушение авторского права страницы