На этом шаге мы рассмотрим структуру ассемблерной программы и способы ее трансляции.
Материал, приведенный в шагах этого раздела, базируется на книге В.Пирогова "Ассемблер для Windows". - СПб.:БХВ-Петербург, 2003. - 656 с.
В изложении материала мы будем придерживаться использования пакета MASM версии 7 и TASM (TASM32.EXE версии 5.0, TLINK32.EXE версии 1.6.71). Рекомендуем пользоваться версиями не ниже указанных.
При объяснении материала мы не будем останавливаться на тех командах, которые описаны в разделе 16-битное программирование, в необходимых случаях мы будем давать соответствующую ссылку.
Двум стадиям трансляции (смотри шаг 26 в разделе 16-битное программирование) соответствуют две основные программы:
Пусть файл с текстом программы на языке ассемблера называется PROG.ASM, тогда, не вдаваясь в подробный анализ, две стадии трансляции будут выглядеть следующим образом:
c:\masm32\bin\ml /с /coff PROG.ASM
c:\masm32\bin\Link /SUBSYSTEM:WINDOWS PROG.OBJ
В результате появляется исполняемый модуль PROG.EXE. Конструкции /с и /coff являются параметрами программы ML.EXE, a /SUBSYSTEM:WINDOWS является параметром для программы LINK.EXE. О других ключах этих программ более подробно смотри приложение 1.
Формат конечного модуля зависит от операционной системы. Установив стандарт на структуру объектного модуля, мы получаем возможность:
Для иллюстрации процесса трансляции рассмотрим несколько простых, "ничего не делающих" программ.
.386P ;Плоская модель памяти. .MODEL FLAT, STDCALL ;Сегмент данных. _DATA SEGMENT DWORD PUBLIC USE32 'DATA' _DATA ENDS ;Сегмент кода. _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: RET ;Выход. _TEXT ENDS END START
В примере 1 представлена "ничего не делающая" программа. Назовем ее PROG1.
ML /с /coff PROG1.ASM LINK /SUBSYSTEM:WINDOWS PROG1.OBJ
или для Турбо Ассемблера:
TASM32 /ml PROG1.ASM TLINK32 -aa PROG1.OBJ
Примем пока параметры трансляции программ как некую данность и продолжим наши изыскания.
Часто удобно разбить текст программы на несколько частей и объединять эти части еще на 1-й стадии трансляции. Это достигается посредством директивы INCLUDE. Например, один файл будет содержать код программы, а константы, данные (определение переменных) и прототипы внешних процедур помещаются в отдельные файлы. Часто такие файлы записывают с расширением INC.
Именно такая разбивка демонстрируется в следующей программе.
;файл CONS.INC CONS1 EQU 1000 CONS2 EQU 2000 CONS3 EQU 3000 CONS4 EQU 4000 CONS5 EQU 5000 CONS6 EQU 6000 CONS7 EQU 7000 CONS8 EQU 8000 CONS9 EQU 9000 CONS10 EQU 10000 CONS11 EQU 11000 CONS12 EQU 12000 ;файл DAT.INC DAT1 DWORD 0 DAT2 DWORD 0 DAT3 DWORD 0 DAT4 DWORD 0 DAT5 DWORD 0 DAT6 DWORD 0 DAT7 DWORD 0 DAT8 DWORD 0 DAT9 DWORD 0 DAT10 DWORD 0 DAT11 DWORD 0 DAT12 DWORD 0 ;файл PROG2.ASM .386P ;Плоская модель памяти. .MODEL FLAT, STDCALL ;Подключить файл констант. INCLUDE CONS.INC ;Сегмент данных. _DATA SEGMENT DWORD PUBLIC USE32 'DATA' ;Подключить файл данных. INCLUDE DAT.INC _DATA ENDS ;Сегмент кода. _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: MOV EAX,CONS1 SHL EAX,1 ;Умножение на 2. MOV DAT1,EAX MOV EAX,CONS2 SHL EAX,2 ;Умножение на 4. MOV DAT2,EAX MOV EAX,CONS3 ADD EAX,1000 ;Прибавим 1000. MOV DAT3,EAX MOV EAX,CONS4 ADD EAX,2000 ;Прибавим 2000. MOV DAT4,EAX MOV EAX,CONS5 SUB EAX,3000 ;Вычесть 3000. MOV DAT5,EAX MOV EAX,CONS6 SUB EAX,4000 ;Вычесть 4000. MOV DAT6,EAX MOV EAX,CONS7 MOV EDX,3 IMUL EDX ;Умножение на З. MOV DAT7,EAX MOV EAX,CONS8 MOV EDX,7 ;Умножение на 7. IMUL EDX MOV DAT8,EAX MOV EAX,CONS9 MOV EBX,3 ;Деление на З. MOV EDX,0 IDIV EBX MOV DAT9,EAX MOV EAX,CONS10 MOV EBX,7 ;Деление на 7. MOV EDX,0 IDIV EBX MOV DAT10,EAX MOV EAX,CONS11 SHR EAX,1 ;Деление на 2. MOV DAT11,EAX MOV EAX,CONS12 SHR EAX,2 ;Деление на 4. MOV DAT12,EAX RET ;Выход. _TEXT ENDS END START
Программа примера 2 также достаточно бессмысленна, но зато демонстрирует удобства использования директивы INCLUDE. Напомним, что мы не останавливаемся в книге на очевидных командах микропроцессора. Заметим только по поводу команды IDIV. В данном случае команда IDIV осуществляет операцию деления над операндом, находящемся в паре регистров EDX:EAX. Обнуляя EDX, мы указываем, что операнд целиком находится в регистре EAX.
Трансляция программы осуществляется так, как это было указано ранее для ассемблеров MASM и TASM в примере 1.
При этом используются следующие стандартные обозначения:
На следующем шаге мы рассмотрим применение объектных модулей.