Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
1328.pdf
Скачиваний:
0
Добавлен:
07.01.2021
Размер:
1.07 Mб
Скачать

или

mov ax,[MemLoc]

Здесь значение 1234h получается как прямой, а не как непосредственный операнд: инструкция mov использует встроенное в нее смещение 5002h и загружает в ax значение по смещению 5002h, которое в данном случае равно 1234h.

Часто встречающейся ошибкой является то, что часто забывают использовать операцию offset, например:

mov si,MemLoc,

где нужно использовать смещение MemLoc. На первый взгляд, данная строка не выглядит неправильной, и так как MemLoc это переменная размером в слово, то эта строка не приведет к ошибке ассемблирования. Однако при выполнении в si будут загружены содержащиеся в переменной MemLoc данные (1234h), а не ее смещение (5002h) и результаты будут непредсказуемы.

Надежного способа избежать этой проблемы нет, но можно принять за правило заключать все ссылки на память в квадратные скобки. Когда перед ссылками на адресные константы будет указываться префикс OFFSET, а ссылки на память заключаться в квадратные скобки, это устранит двусмысленность и неопределенность при использовании имен переменных памяти. При таком соглашении работа инструкций

mov si,offset MemLoc

и

mov si,[MemLoc]

становится совершенно понятной, в то время как инструкция mov si,MemLoc

будет настораживать.

Библиографический список

1.Зубков С.В. Assembler для DOS, Windows и UNIX. / С.В. Зубков 11-е изд.,

стер. М.: ДМК Пресс; СПб.: Питер, 2010. 640 с.

2.Бурдаев О.В. Ассемблер в задачах защиты информации / О.В. Бурдаев, М.А. Иванов, И.И. Тетерин Под ред. И.Ю. Жукова. – 3-е изд., стер. – М.: КУДИЦ-

ОБРАЗ, 2008. – 544 с.

59

3. Абель Питер. Язык и программирование для IBM PC. / Питер Абель. Издво КОРОНА-Век, 2009.

60

Приложение 1

Примеры (тексты) программ

Пример П.1.1

;lab3pr1.asm

 

; Примеры

 

mov al,b1

 

sar al,1

; арифметический сдвиг байта вправо

mov byte ptr rezult,al

 

; ----------------------------------------

 

mov al,b1

 

rol al,1

; циклический сдвиг байта влево

mov byte ptr rezult,al

 

; ----------------------------------------

 

mov al,b1

ror al,1 ; циклический сдвиг байта вправо mov byte ptr rezult,al

=================================================================

Пример П.1.2

; lab3pr2.asm COM-программа создания файла на диске и вывода в файл

codesg segmentPARA 'Code'

 

 

assume cs:codesg,ds:codesg,ss:codesg,es:codesg

 

org

100h

 

; обход PSP

begin:

 

jmp

main

;обход через данные

; ---------------------------------------------------

 

 

 

 

flda

dw

250

 

;определение данных

fldb

dw

125

 

 

fldc

dw

?

 

 

soob1

db

'Привет!','$',0ah,0dh

soob2

db

'Error

 

','$',0ah,0dh

fcbrec label byte

 

 

fcbdriv db

03

 

;диск С

fcbname db

'file1

'

 

fcbext

db

'dat'

 

 

fcbblk dw

0000

 

 

fcbrcsz dw

?

 

 

fcbflsz dd

?

 

 

 

dw

?

 

 

 

dt

?

 

 

fcbsqrc db

00

 

 

;

dd

?

 

 

 

 

 

 

Main

proc

near

 

 

 

mov ah,09

 

 

 

lea dx, soob1

 

 

int 21h ---------------------------------------------------

mov ah,16h lea dx,fcbrec

int 21h ---------------------------------------------------

61

cmp al,00 jnz error mov fcbrcsz,1 mov ah,1ah lea dx,soob2

int 21h ---------------------------------------------------

mov ah,15h lea dx,fcbrec

int 21h ---------------------------------------------------

jmp exit

error:

mov ah,09 lea dx, soob2

int 21h ---------------------------------------------------

exit:

 

ret

;возврат в DOS

main endp

 

codesg

ends

end

begin

=================================================================

Пример П.1.3

formula3 proc

;lab3pr3.asm, АБП(1), ЦСЛ(10), СДП(11)П, СДЛ(12)

;Примеры:

cmp x1,3 jz fabp_1 cmp x1,4 jz fcsl_10 cmp x1,5 jz fsdr_11 cmp x1,6 jz fsdl_12

;Вычислительная часть!

fabp_1:

;АБП(1)

mov al,b1

 

sar al,1

 

mov byte ptr rezult,al

 

ret

 

fcsl_10:

;ЦСЛ(10)

mov ax,w1

 

mov cx,10

 

csl_10:

 

rol ax,1

 

loop csl_10

 

mov word ptr rezult,ax

 

ret

 

fsdr_11:

;СДП(11)П

mov ax,word ptr d1

 

mov dx,word ptr d1[2]

 

mov cx,11

 

 

62

 

cmp cf,0

 

jnz cf1

 

cf0:

clc

 

 

jmp sdr_11

cf1:

stc

 

sdr_11:

 

 

rcr dx,1

 

rcr ax,1

 

loop sdr_11

 

jc rcf1

 

 

jnc rcf0

rcf1:

mov cf,1

 

jmp next

rcf0:

mov cf,0

next:

mov word ptr rezult,ax

 

mov word ptr rezult[2],dx

 

ret

 

fsdl_12:

;СДЛ(12)

 

mov ax,word ptr d1

 

mov dx,word ptr d1[2]

 

mov cx,12

sdl_12: clc

 

 

rcl ax,1

 

rcl dx,1

 

clc

 

 

loop sdl_12

 

mov word ptr rezult,ax

 

mov word ptr rezult[2],dx

 

ret

 

formula3

endp

=================================================================

Пример П.1.4

; lab3pr4.asm использование блока управления файлом FCB для создания файла

;----------------------------------------------------------

codesg segment para 'Code'

assume cs:codesg,ds:codesg,ss:codesg,es:codesg

org

100h

 

; обход PSP

begin: jmp

main

 

;обход через данные

; ---------------------------------------------------

 

reclen equ

32

 

 

namepar

label

byte

;список параметров:

maxlen

db

reclen

; макс.длина имени

namelen

db

?

; число введенных символов

namedta

db

reclen dup(' ')

; область передачи (DTA)

fcbrec

label

byte

;FCB для дискового файла

fcbdriv

db

04

; дисковод D

fcbname

db

'namefile'

; имя файла

fcbext

db

'dat'

; тип файла

fcbblk

dw

0000

; номер текущего блока

 

 

 

63

fcbrcsz

dw

?

 

; размер логической записи

fcbflsz

 

dd

?

 

; размер файла (DOS)

 

dw

?

 

 

; дата (DOS)

 

dt

?

 

 

; зарезервировано (DOS)

fcbsqrc

db

00

 

; номер текущей записи

 

dd

?

 

 

; относительный номер

crlf

db

13,10,'$'

 

 

errcde

 

db

00

 

 

prompt

db

'Name? ','$'

 

 

row

db

01

 

 

 

opnmsg

db

'*** Open error ***', '$'

wrtmsg

db

'*** Write error ***', '$'

; ---------------------------------------------------------

main

proc

far

 

 

 

 

mov

ax,0600h

 

 

 

call

q10scr

 

 

;очистить экран

 

call

q20curs

 

;установить курсор

 

call

c10open

 

;открыть, установить DTA

 

cmp

errcde,00

 

;есть место на диске?

 

jz

a20loop

;

да - продолжить,

 

ret

 

 

;

нет - вернуться в DOS

a20loop:

 

 

 

 

 

call

d10proc

 

 

 

cmp

namelen,00

 

;конец ввода?

 

jne

a20loop

;

нет продолжить,

 

call

g10clse

;

да закрыть файл

 

ret

 

 

;

и вернуться в DOS

main

endp

 

 

 

 

;Открытие дискового файла:

c10open

proc near

 

mov

ah,16h

;функция создания файла

lea

dx,fcbrec

 

int

21h

 

cmp

al,00

;есть место на диске?

jnz

c20

; нет ошибка

mov

fcbrcsz,reclen

;размер записи (EQU)

lea

dx,namedta

;загрузить адрес DTA

mov

ah,1ah

 

int

21ah

 

ret

 

 

c20:

 

 

lea

dx,opnmsg

;сообщение об ошибке

call

x10err

 

ret

 

 

c10open

endp

 

;Ввод с клавиатуры:

d10proc

proc

near

mov

ah,09

;функция вывода на экран

 

 

64

lea

dx,prompt

 

;выдать запрос

int

21h

 

 

mov

ah,0ah

 

;функция ввода

lea

dx,namepar

 

;ввести имя файла

int

21h

 

 

call

e10disp

 

;прокрутка на экране

cmp

namelen,00

 

;имя введено?

jne

d20

;

да продолжить,

ret

 

;

нет выйти

d20:

 

 

 

mov

bh,00

 

;заменить символ Return

mov

bl,namelen

 

 

mov

namedta[bx],' '

 

;записать пробел

call

f10writ

 

;вызвать подпрограмму записи

;

 

 

 

cld

 

 

 

lea

di,namedta

 

;очистить

mov

cx,reclen/2

 

; поле

mov

ax,2020h

 

; имени

rep

stosw

 

 

ret

 

 

;выйти

d10proc

endp

 

 

;Прокрутка и установка курсора:

e10disp

proc near

 

 

mov

ah,09

 

;функция вывода на экран

lea

dx,crlf

 

;CR/LF

int

21h

 

;вызов DOS

cmp

row,18

 

;последняя строка экрана?

jae

e20

;

да обойти,

inc

row

;

нет увеличить строку

ret

 

 

 

e20:

 

 

 

mov

ax,0601h

 

;прокрутка на 1 строку

call

q10scr

 

 

call

q20curs

 

;установить курсор

ret

 

 

 

e10disp

endp

 

 

;Запись на диск:

f10writ

proc near

 

 

mov

ah,15h

;функция записи

lea

dx,fcbrec

 

 

int

21h

 

 

cmp

al,00

;запись без ошибок?

jz

f20

;

да

lea

dx,wrtmsg

;

нет

call

x10err

; выдать сообщение

mov

namelen,00

 

 

65

f20: ret f10writ endp

;Закрытие дискового файла:

g10clse

proc near

 

mov

namedta,1ah

;установить конец файла EOF

call

f10writ

 

mov

ah,10h

;функция закрытия

lea

dx,fcbrec

 

int

21h

 

ret

 

 

g10clse

endp

 

;Прокрутка экрана:

q10scr

proc near

;ax уже установлен

mov

bh,1eh

;цвет желтый на синем

mov

cx,0000

 

mov

dx,184fh

 

int

10h

;прокрутка

ret

 

 

q10scr

endp

 

;Установка курсора:

q20curs

proc near

 

mov

ah,02

 

mov

bh,00

 

mov

dl,00

 

mov

dh,row

;установить курсор

int

10h

 

ret

 

 

q20curs

endp

 

;Вывод сообщения об ошибке на диске:

x10err

proc near

 

mov

ah,09

;dx содержит

int

21h

; адрес сообщения

mov

errcde,01

;установить код ошибки

ret

 

 

x10err

endp

 

codesg

ends

 

end

begin

 

__________________________________________________________________________

Программа, приведенная в данном примере, создает дисковый файл по имени, которое вводится пользователем с клавиатуры. Блок FCB (fcbrec) в данной программе содержит следующие поля:

fcbdriv программа должна создать файл на диске 4 (или D). fcbname имя файла namefile.

fcbext тип файла dat.

fcbblk Начальное значение номера текущего блока 0.

fcbrcsz Размер записей не определен, так как операция открытия устанавливает в данном поле значение 128.

fcbsqrc -начальное значение номера текущей записи 0.

66

В программе организованы следующие процедуры:

begin вызывает c10open для создания файла и установки адреса DTA для DOS, вызывает d10proc для ввода имени файла. Если ввод пустой, то происходит вызов g10clse для завершения программы;

c10open создает для файла элемент в директории, устанавливает размер записей 32 (шест.20) и инициализирует адрес буфера DTA для DOS. d10proc выдает запрос на ввод имен, вводит имена с клавиатуры и

вызывает процедуру f10writ для записи вводимых имен на диск. e10dispуправляет прокруткой и установкой курсора. f10writ записывает имена в дисковой файл.

g10clse записывает маркер конца файла и закрывает файл.

x10err выдает на экран сообщение об ошибке в случае некорректной операции создания файла или записи данных.

Каждая операция записи автоматически добавляет 1 к fcbsqrc (номер текущей записи) и шест. 20 (размер записи) к fcbflsz (размер файла). Так как каждая запись имеет длину 32 байта, то операция заносит в буфер 16 записей и затем записывает весь буфер в сектор диска. Ниже показано содержимое DTA и буфера:

DTA: |текущая запись|

Буфер: |запись 00|запись 01|запись 02|...|запись 15| Если пользователь ввел 25 имен, то счетчик записей увеличится от 1 до 25

(шест.19). Размер файла составит:

25 * 32 байта = 800 байтов или шест. 320 Операция закрытия заносит во второй сектор оставшиеся в буфере девять

записей и изменяет в оглавлении дату и размер файла. Размер записывается байтами в переставленном порядке: 20030000. Последний буфер имеет следующий вид:

Буфер: |запись 16|запись 17|...|запись 24|шест.1A|...|...|

Для простоты в приведенной программе создаются записи файла, содержащие только одно поле. Записи большинства других файлов, однако, содержат различные символьные и двоичные поля и требуют описания записи в DTA. Если записи содержат двоичные числа, то не следует использовать маркер конца файла (EOF), так как двоичное число может совпасть с шест. кодом 1A.

Для того, чтобы сделать программу более гибкой, можно разрешить пользователю указать дисковод, на котором находится или будет находиться файл. В начале выполнения программа может выдать на экран сообщение, чтобы пользователь ввел номер дисковода, а затем изменить первый байт блока

FCB.

=================================================================

Пример П.1.5

; lab3pr5.asm программа, использующая FCB для чтения дискового файла

;Чтение записей созданных в CREATDSK

;-------------------------------------------------------

codesg segmentPARA 'Code'

assume cs:codesg,ds:codesg,ss:codesg,es:codesg

org

100h

; обход PSP

begin: jmp

main

;обход через данные

 

 

67

; ---------------------------------------------------

 

fcbrec label

byte

 

;FCB для файла

fcbdriv

db

04

; дисковод D

fcbname

db

'namefile'

; имя файла

fcbext

 

db

'dat'

; тип файла

fcbblk

 

dw

0000

; номер текущего блока

fcbrcsz

dw

0000

; длина логической записи

fcbflsz

 

dd

?

; размер файла (DOS)

 

 

dw

?

; дата (DOS)

 

 

dt

?

; зарезервировано (DOS)

fcbsqrc

db

00

; текущий номер записи

 

 

dd

?

; относительный номер

reclen

 

equ

32

;длина записи

namefld

db

reclen dup(' '), 13, 10, '$'

endcde

db

00

 

openmsg

db

'*** Open error ***', '$'

readmsg

db

'*** Read error ***', '$'

row

db

00

 

 

main

proc

far

 

 

 

mov

ax,0600h

 

 

call

q10scr

 

;очистить экран

 

call

q20curs

;установить курсор

 

call

e10open

;открыть файл и установить DTA

 

cmp

endcde,00

;открытие без ошибок?

 

jnz

a90

;

нет завершить

a20loop:

 

 

 

 

call

f10read

;прочитать запись

 

cmp

endcde,00

;чтение без ошибок?

 

jnz

a90

;

нет выйти

 

call

g10disp

;выдать имя на экран

 

jmp

a20loop

;продолжить

a90:

ret

 

 

;завершить

begin

endp

 

 

 

;Открытие файла на диске:

e10open

proc near

 

lea

dx,fcbrec

 

mov

ah,0fh

;функция открытия

int

21h

 

cmp

al,00

;файл найден?

jnz

e20

; нет ошибка

mov

fcbrcsz,reclen

;длина записи (EQU)

mov

ah,1ah

 

lea

dx,namefld

;адрес DTA

int

21h

 

ret

 

 

e20:

 

 

mov

endcde,01

;сообщение об ошибке

lea

dx,openmsg

 

call

x10error

 

 

 

68

ret e10open endp

;Чтение дисковой записи:

f10read

proc near

 

 

mov

ah,14h

;функция чтения

lea

dx,fcbrec

 

 

int

21h

 

 

cmp

namefld,1ah

;считан маркер EOF?

jne

f20

;

нет

mov

endcde,01

;

да

jmp

f90

 

 

f20:

 

 

 

cmp

al,00

;чтение без ошибок?

jz

f90

;

да выйти

mov

endcde,01

;

нет:

cmp

al,01

;конец файла?

jz

f90

;

да выйти,

lea

dx,readmsg

;

нет значит

call

x10err

; ошибка чтения

f90:

 

 

 

ret

 

 

 

f10read

endp

 

 

;Вывод записи на экран:

g10disp

proc near

 

 

mov

ah,09

;функция вывода на экран

lea

dx,namefld

 

 

int

21h

 

 

cmp

row,20

;последняя строка экрана?

jae

g30

;

нет...

inc

row

;

да увеличить строку

jmp

g90

 

 

g30:

 

 

 

mov

ax,0601h

 

 

call

q10scr

; прокрутить

call

q20curs

; установить курсор

g90: ret

 

 

 

g10disp

endp

 

 

;Прокрутка (скроллинг) экрана:

q10scr

proc near

;ax уже установлен

mov

bh,1eh

;установить цвет

mov

cx,0000

 

mov

dx,184fh

;функция прокрутки

int

10h

 

ret

 

 

q10scr

endp

 

;Установка курсора:

q20curs

proc near

mov

ah,02

mov

bh,00

69

mov dh,row mov dl,00 int 10h ret

q20curs endp

;Вывод сообщения об ошибке на диске:

x10err

proc

near

mov

ah,09

;dx содержит адрес

int

21h

; сообщения

ret

 

 

x10err

endp

 

codesg

ends

 

end

begin

 

В данном примере приведена программа, которая выполняет чтение файла, созданного предыдущей программой, и вывод на экран имен из записей файла. Обе программы содержат идентичные блоки FCB, хотя имена полей FCB могут быть различны. Содержимое полей имени и типа файла должны быть одинаковы. Программа содержит следующие процедуры:

begin вызывает процедуру e10open для открытия файла и установки DTA и вызывает f10read для чтения записей. Если считан маркер конца файла, то программа завершается, если нет, то вызывается процедура g10disp.

e10open открывает файл, устанавливает значение размера и записей, равное 32 (шест. 20), и инициализирует адрес DTA.

f10read выполняет последовательное чтение записей. Операция чтения автоматически увеличивает номер текущей записи в блоке FCB.

g10disp выводит на экран содержимое прочитанной записи.

x10err выводит на экран сообщение об ошибке в случае некорректной операции открытия или чтения.

Операция открытия выполняет поиск имени и типа файла в оглавлении. Если необходимый элемент оглавления найден, то автоматически в блок FCB заносятся размер файла, дата и длина записей. Первая операция чтения записи с номером 00 получает доступ к диску и считывает весь сектор (16 записей) в буфер. После этого первая запись заносится в DTA, а номер текущей записи в FCB увеличивается с 00 до 01:

Буфер: |запись 00|запись 01|запись 02|... |запись 15| DTA : |запись 00|

Второй операции чтения нет необходимости обращаться к диску. Так как требуемая запись уже находится в буфере, то операция просто пересылает запись 01 из буфера в DTA и увеличивает номер текущей записи на единицу.

Таким же образом выполняются следующие операции чтения, пока все 16 записей из буфера не будут обработаны.

Операция чтения 16-й записи приводит к физическому чтению следующего сектора в буфер и пересылке первой записи сектора в DTA. Последующие операции чтения переносят остальные записи из буфера в DTA. Попытка прочитать после последней записи вызовет состояние конца файла и в регистр al будет записан код возврата шест. 01.

70

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]