Трансляция ассемблерной программы
Мы написали ассемблерную программу, которую назвали, например, temp.asm. Теперь эту программу нужно оттранслировать с помощью tasm.exeи получить из нее файл temp.obj. Затем, с помощью программы tlink.exe, файл temp.objпреобразуется в исполняемый файл temp.exe (или temp.com).
Для того, чтобы получить файл temp.objнадо набрать в командной строке:
tasm.exe temp. asm(можно и проще: tasm temp)
и нажать ENTER. Конечно при этом tasm.exeи temp.asmдолжны быть, допустим, в той директории, где мы сейчас работаем (доступны компьютеру). Транслятор может и не создать файл temp.obj, если он найдет в программе ошибки.
Далее надо получить исполняемый файл. Для создания EXE программы надо набрать в командной строке:
tlink.exe temp.obj(или tlink temp)
а для COM программы:
tlink.exe temp.obj /t(или tlink temp /t).
Вообще, очень удобно создать bat– файл, поскольку при отладке программу постоянно приходится транслировать заново. Работа tlink.exeтакже не всегда завершается созданием исполняемого файла. Это бывает, если tlink.exeнашел в программе ошибки.
Приведем пример трансляции.
code segment; (строка 1)
assume cs:code, ds:code; (строка 2)
; пропущена директива org 100h
start:; (строка 4)
jmp begin; (строка 5)
mad db 100, 99, 98,; (строка 7) лишняя запятая после 98
db 97, 96; (строка 8)
nic dw 380; (строка 10)
begin; (строка 12) пропущено двоеточие после begin
mov ah. 7 ; (строка 14) вместо точки нужна запятая
mov al, nic; (строка 15) не согласована разрядность регистра и операнда
int21h; (строка 16) пропущен пробел
mov si, offset madd; (строка 17) неправильно написано имя массива
mov [si+3], 5; (строка 18) не определен формат записываемой информации
Mov ah, 4ch
Int 21h
Code ends
End start
Мы написали эту программу (для COM формата) и назвали ее temp.asm. Эта программа не имеет никакого смысла, так как не выполняет никакой полезной и даже здравой работы. Зато в программе намеренно сделаны ошибки, каждая из которых описана в той же строке, где она находится.
Теперь мы создали файл temp.bat:
Tasm temp
Tlink temp /t
и запустили его. Вот что мы получим:
Assembling file: temp.ASM
**Error** temp.ASM(5) Undefined symbol: BEGIN
*Warning* temp.ASM(7) Missing operand - trailing ? assumed
**Error** temp.ASM(12) Illegal instruction
**Error** temp.ASM(14) Too few operands to instruction
**Error** temp.ASM(15) Operand types do not match
**Error** temp.ASM(16) Illegal instruction
**Error** temp.ASM(17) Undefined symbol: MADD
*Warning* temp.ASM(18) Argument needs type override
Error messages: 6
Warning messages: 2
Passes: 1
Remaining memory: 381k
D:\MY_DIR\ASSEMBL>d:\my_dir\assembl\tlink temp /t
Turbo Link Version 7.00 Copyright (c) 1987, 1994 Borland International
Fatal: Unable to open file 'temp.obj'
Обратите внимание, что транслятор для каждой ошибки написал в скобках номер строки, в которой он эту ошибку нашел. Так что обычно ошибка легко находится программистом. ERROR– это ошибки, их надо исправлять, WARNING –предупреждения, довольно часто (но не всегда!) их можно игнорировать. Объектный файл из-за ошибок создан не был, поэтому tlinkвыдал сообщения о фатальной ошибке.
Исправим в нашей программе все ошибки, кроме одной:
code segment; (строка 1)
assume cs:code, ds:code; (строка 2)
; пропущена директива org 100h
start:; (строка 4)
jmp begin; (строка 5)
mad db 100, 99, 98; (строка 7)
db 97, 96; (строка 8)
nic dw 380; (строка 10)
begin:; (строка 12)
mov ah, 7 ; (строка 14)
mov al, byte ptr nic ; (строка 15)
int 21h; (строка 16)
mov si, offset mad ; (строка 17)
mov byte ptr [si+3], 5 ; (строка 18)
Mov ah, 4ch
Int 21h
Code ends
End start
и вновь запустим наш bat файл. Теперь мы получим:
Assembling file: temp.ASM
Error messages: None
Warning messages: None
Passes: 1
Remaining memory: 381k
D:\MY_DIR\ASSEMBL>d:\my_dir\assembl\tlink temp /t
Turbo Link Version 7.00 Copyright (c) 1987, 1994 Borland International
Fatal: Cannot generate COM file : invalid initial entry point address
Теперь tasm«доволен всем» и объектный файл создан, а вот tlinkотказывается генерировать СОМ файл. Если мы теперь исправим оставшуюся ошибку (вставим org 100h), то после трансляции будем иметь сообщение:
Assembling file: temp.ASM
Error messages: None
Warning messages: None
Passes: 1
Remaining memory: 381k
D:\MY_DIR\ASSEMBL>d:\my_dir\assembl\tlink temp /t
Turbo Link Version 7.00 Copyright (c) 1987, 1994 Borland International
а наш СОМ файл будет создан.
ПРИМЕРЫ ПРОГРАММИРОВАНИЯ НА АССЕМБЛЕРЕ.
Наша первая программа.
В качестве первого примера программы на любом языке обычно используется программа, выводящая на экран надпись: HELLO, WORLD! Давайте и мы напишем такую же программу, но, что бы было интересней, несколько ее усложним.
Итак, вот что будет делать наша программа:
ü Очищать экран (белым цветом);
ü Устанавливать курсор, так чтобы надпись выводилась в центр экрана;
ü Выводить надпись в позицию курсора (черным цветом);
ü Ждать нажатия клавиши. Если нажата одна из клавиш b (blue), g(green) или r(red), цвет надписи меняется соответственно на синий, зеленый или красный. Если нажата клавиша ESC, программа завершает свою работу.
Приведем вначале текст программы:
; программа написана в СОМ формате
Code segment
Assume cs:code, ds:code
Org 100h
start:
Jmp begin
message db 'HELLO, WORLD!'; надпись, которую мы будем выводить
attributes db 70h; исходные атрибуты экрана и надписи
; экран – белый, надпись - черная
curs_x db 35 ; координата Х курсора (№ столбца)
curs_y db 12; координата Y курсора (№ строки)
begin:
; чистим экран
mov ch, 0; координата Y левого верхнего угла экрана (№ строки)
mov cl, 0; координата Х левого верхнего угла экрана (№ столбца)
mov dh, 24; координата Y правого нижнего угла экрана(№ строки)
mov dl, 79; координата Х правого нижнего угла экрана (№ столбца)
mov al, 0; чистить всю заданную область(то есть, у нас, весь экран)
mov bh, 70h; атрибуты (черный символ на белом фоне)
mov ah, 6; функция
Int 10h
m4:
; выводим надпись
mov di, 13; всего выводим 13 символов
mov si, offset message; в siадрес первой буквы надписи
m1:
; позиционируем курсор
mov dh, curs_y; в dhстрока
mov dl, curs_x; в dl столбец
mov bh, 0; в bh№ видеостраницы (для нас начинающих всегда 0)
mov ah, 2; функция
Int 10h
; собственно вывод надписи. Курсор при таком выводе (для нас, УВЫ!) не сдвигается
mov ah, 9; функция
mov bl, attributes; атрибуты
mov cx, 1; коэффициент повторения (сколько раз выводить символ)
mov al, [si]; в al выводимый (на экран в позицию курсора) символ
Int 10h
inc si; в siадрес следующей буквы надписи
inc curs_x; сдвигаем координату Х на одну позицию вправо
dec di; уменьшаем diна единицу
jnz m1; если в di «не ноль», идем на переустановку курсора
; и вывод следующей буквы надписи
mov curs_x, 35; восстанавливаем исходную координату курсора по Х
mov ah, 0; функция
int 16h; здесь висим и ждем нажатия клавиши. Когда клавиша
; нажата ее скэн-код вернется в ah, а ASCII-код – в al.
cmp al, 1bh; это ESC? (1bh - ASCII-код клавиши ESC)
je exit; если «да», идем на выход. «Нет» - проверяем дальше
cmp al, 'r'; это r?
jne m2; «нет» - проверяем дальше
mov attributes, 74h; «да» - меняем атрибуты
jmp m4; и идем на вывод надписи сначала. Старую надпись мы
; не стираем, просто пишем поверх нее новую надпись
; с другими атрибутами
m2:
cmp al, 'g'; далее аналогично
Jne m3
Mov attributes, 72h
Jmp m4
m3:
cmp al, 'b'
jne m4; это вообще «не наша» клавиша, мы ее проигнорируем
Mov attributes, 71h
Jmp m4
; выход из программы. Мы сюда попадем, только если нажмем ESC
exit:
Mov ah, 4ch
Int 21h
Code ends
End start
Не надо думать, что это оптимальная программа. Давайте, для примера, напишем другой вариант этой программы, теперь в EXE формате.
Stack segment stack
Db 100 dup (0)
Stack ends
Data segment
message db 'HELLO, WORLD!$'; надпись, которую мы будем выводить
attributes db 70h; исходные атрибуты экрана и надписи
data ends
Code segment
Assume cs:code, ds:data
start:
Mov ax, data
Mov ds, ax
; чистим экран
m4:
mov ch, 0; координата Y левого верхнего угла экрана (№ строки)
mov cl, 0; координата Х левого верхнего угла экрана (№ столбца)
mov dh, 24; координата Y правого нижнего угла экрана(№ строки)
mov dl, 79; координата Х правого нижнего угла экрана (№ столбца)
mov al, 0; чистить всю заданную область(то есть, у нас, весь экран)
mov bh, attributes; текущие атрибуты
mov ah, 6; функция
Int 10h
;позиционируем курсор
mov dh, 12; в dhстрока
mov dl, 35; в dl столбец
mov bh, 0; в bh№ видеостраницы (для нас начинающих всегда 0)
mov ah, 2; функция
Int 10h
; выводим надпись
mov ah, 9; функция
mov dx, offset message; в dxадрес первой буквы надписи
int 21h; выводим все до доллара
mov ah, 0; функция
int 16h; здесь висим и ждем нажатия клавиши. Когда клавиша
; нажата ее скэн-код вернется в ah, а ASCII-код – в al.
cmp al, 1bh; это ESC? (1bh - ASCII-код клавиши ESC)
je exit; если «да», идем на выход. «Нет» - проверяем дальше
cmp al, 'r'; это r?
jne m2; «нет» - проверяем дальше
mov attributes, 74h; «да» - меняем атрибуты
jmp m4; и идем на новую очистку экрана, установку курсора
; и вывод надписи
m2:
cmp al, 'g'; далее аналогично
Jne m3
Mov attributes, 72h
Jmp m4
m3:
cmp al, 'b'
jne m4; это вообще «не наша» клавиша, мы ее проигнорируем
Mov attributes, 71h
Jmp m4
; выход из программы. Мы сюда попадем, только если нажмем ESC
exit:
Mov ah, 4ch
Int 21h
Code ends
End start
Программа получилась несколько проще. При каждом нажатии любой клавиши (кроме ESC) мы заново очищаем экран с текущими атрибутами, а потом выводим на него надпись, начиная с позиции курсора, который мы все время устанавливаем в одно и тоже место. Недостаток этой программы заключается в постоянной очистке экрана. На медленных компьютерах человеку будет видно мерцание экрана.