Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
прогр.docx
Скачиваний:
23
Добавлен:
21.12.2018
Размер:
2.58 Mб
Скачать

Массивы

Массив — структурированный тип данных, состоящий из некоторого числа элементов одного типа.

Описание и инициализация массива в программе

Массив в программе можно моделировать одним из следующих способов:

    1. Перечислением элементов массива в поле операндов одной из директив описания данных. Например:

;массив из 5 элементов. Размер каждого элемента 4 байта:

mas dd 1,2,3,4,5 ; 00 00 00 01 00 00 00 02 00 00 00 04 00 00 00 05

 

    1. Используя оператор повторения dup. К примеру:

;массив из 5 нулевых элементов. Размер каждого элемента 2 байта:

mas dw 5 dup (0) ; 00 00 00 00 00 00 00 00 00 00

 

Такой способ определения используется для резервирования памяти с целью размещения и инициализации элементов массива;

    1. используя директивы label и rept. Директива rept вызывает повторение указанного числа раз строк, заключенных между директивой и строкой endm. К примеру, определим массив байт в области памяти, обозначенной идентификатором mas_b. В данном случае директива label определяет символическое имя mas_b, но эта директива не резервирует память, а лишь определяет характеристики объекта. В данном случае объект — это ячейка памяти. Используя несколько директив label, записанных одна за другой, можно присвоить одной и той же области памяти разные имена и типы. Например:

 

...

n=0

...

mas_b label byte

mas_w label word

rept 5

dw 0flf0h ; f1 f0 f1 f0 f1 f0 f1 f0 f1 f0

endm

 

В результате в памяти будет создана последовательность из пяти слов f1f0. Эту последовательность можно трактовать как массив байт или слов в зависимости от того, какое имя области будет использоваться в программе — mas_b или mas_w;

  1. использованием цикла для инициализации значениями области памяти, которую можно будет впоследствии трактовать как массив. Например: инициализация массива в цикле:

Пример 1: Заполнить массив из 10 элементов размером в байт значениями индексов. Вывести массив на экран в консольном режиме, учитывая, что элементы массива максимум однозначные числа. Программу разработать для DOS16.

;Для DOS16

MASM

MODEL small

STACK 256

.data

mes1 db 0ah,0dh,'Massiv: ',0h

mes2 db '; ',0h

mas db 10 dup (?) ;исходный массив

i db 0

.code

start:

mov ax,@data

mov ds,ax

xor ax,ax ;обнуление ax

mov cx,10 ;значение счетчика цикла в cx

mov si, 0 ;индекс начального элемента в cx

go: ;цикл инициализации

mov bh,i ;i в bh

mov mas[si],bh ;запись в массив i

inc i ;инкремент i

inc si ;продвижение к следующему элементу массива

loop go ;повторить цикл

;вывод на экран получившегося массива

mov cx,10

mov si,0

mov ah,09h

lea dx,mes1

int 21h

show:

mov ah,02h ;функция вывода значения из dl на экран

mov dl,mas[si]

add dl,30h ;преобразование числа в символ

int 21h

mov ah,09h

lea dx,mes2

int 21h

inc si

loop show

exit:

mov ax,4c00h ;стандартный выход

int 21h

end start ;конец программы 

----------------------------------------------------------

Лекция №8. Массивы, структуры, записи, объединения

Пересылка данных с помощью команды xlat

 Команда:

XLAT адрес

XLATB

 Назначение:

Трансляция в соответствии с таблицей

Помещает в AL байт из таблицы в памяти по адресу ES:BX (или ES:EBX) со смещением относительно начала таблицы, равным AL.

В качестве аргумента для XLAT в ассемблере можно указать имя таблицы, но эта информация никак не используется процессором и служит только как комментарий. Если этот комментарий не нужен, можно применить форму записи XLATB.

Пример: Преобразовать шестнадцатеричное число в ASCII-код соответствующего ему символа:

.data

htable db "0123456789ABCDEF"

.code

.

mov al,0Ch

mov bx, offset htable

xlat

После выполнения команды xlat, регистр AL будет содержать не число 0Сh, а ASCII-код буквы «С».

Пример 3: Заполнить массив из 30-ти элементов размером в байт значениями индексов. Вывести массив на экран в одну строку, учитывая, что элементы массива максимум двухзначные числа.

.386

.model flat, stdcall

includelib import32.lib

extrn ExitProcess:PROC

extrn MessageBoxA:PROC

.data

Ttl db 'Massiv',0h

mas db 30 dup (?) ; 32 элементов массива + 10 символов +переходы на

; следующую строчку 2 байта 0ah,0dh

db 0ah

mes1 db 'Massiv: ',0ah,0dh

masVivod db 85 dup (?) ; 10 элементов массива + 10 символов +переходы на

; следующую строчку 2 байта 0ah,0dh

i db 0

N db 30

tabl db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h

.code

start:

xor ecx,ecx ;обнуление есx

xor edx,edx

mov cl,N ;значение счетчика цикла в cl

mov esi, 0 ;индекс начального элемента в si

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

; Заполнение элементов массива значениями их индексов

go:

mov bh,i

mov mas[esi],bh

inc esi

inc i

loopnz go

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

mov cl,N

mov edi,0

mov esi,0

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

; Проверяем число больше или равно 10, если «да», то уходим на метку met1 и

; выводим его как двузначное число. Если число меньше 10 (однозначное),

; то уходим на метку met2.

go1: ; цикл инициализации

xor eax,eax

mov al,mas[edi]

cmp al,0ah

jae met1

jmp met2

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

; Формируем двузначное число в массив masVivod. Делим его на 10, чтобы

; отделить первую цифру и получить одну цифру в остатке. Переводим первую

; цифру и остаток в ASCII код

met1:

mov bl,10

div bl

mov ebx, offset tabl

xlat

mov masVivod[esi],al

inc esi

mov al,ah

xlat

mov masVivod[esi],al

jmp met3

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

; Если число однозначное, то заменяем число на символ

; числа и записываем символ числа (ASCII код числа) в регистр al

met2:

mov ebx, offset tabl

xlat

mov masVivod[esi],al

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

; Ставим после числа символ «;» и наращиваем индексы

met3:

inc esi

mov masVivod[esi],';'

inc esi

inc edi

loopnz go1

mov masVivod[esi],0h

;вывод на экран получившегося массива

push 0h

push offset Ttl

push offset mes1

push 0h

call MessageBoxA

push 0h

call ExitProcess

end start

Результат:

Пример 5: Вывести в одну строку все значения элементов массива, учитывая, что значения элементов массива могут быть трёхзначными и имеют размер в один байт. Значение элементов массива сформировать как i*k, i=k.

.386

.model flat, stdcall

includelib import32.lib

extrn ExitProcess:PROC

extrn MessageBoxA:PROC

.data

Ttl db 'Massiv',0h

mas db 30 dup (?) ; 32 элементов массива + 10 символов +переходы на

; следующую строчку 2 байта 0ah,0dh

mes1 db 'Massiv: ',0ah,0dh

masVivod db 85 dup (?) ; 10 элементов массива + 10 символов +переходы на

; следующую строчку 2 байта 0ah,0dh

i db 0

k db 0

N db 16 ; Максимальное значение элемента массива 15*15=225

tabl db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h

.code

start:

xor ecx,ecx

xor edx,edx

mov cl,N

mov esi, 0

go:

mov bl,i

mov al,k

mul bl

mov mas[esi],al

inc esi

inc i

inc k

loopnz go

mov cl,N

mov edi,0

mov esi,0

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

; Проверяем число. Если оно однозначное, то уходим на метку met2. Если число

; двухзначное, то уходим на метку met1. Если число трёхзначное, то продолжаем

; выполнять код программы.

go1:

xor eax,eax

mov al,mas[edi]

cmp al,0ah

jb met2

cmp al,64h

jb met1

; Если число трёхзначное, то делим его на 10, чтобы

; получить две первых цифры числа и остаток. Заносим в регистр целую часть от деления

; а остаток переводим в ASCII код. Оставшиеся две цифры числа (целую часть от

; деления) сохраняем в регистре ah и переходим на метку met4.

mov bl,10

div bl

mov ebx, offset tabl

xchg al,ah

xlat

mov masVivod[esi+2],al

mov al,ah

xor ah,ah

jmp met4

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

; Если число двухзначное, то делим его на 10, чтобы

; получить первую цифру числа и остаток. Заносим в память первую цифру и

; остаток.

met1:

mov bl,10

div bl

mov ebx, offset tabl

xchg al,ah

xlat

mov masVivod[esi+1],al

mov al,ah

xlat

mov masVivod[esi],al

inc esi

jmp met3

met4:

mov bl,10

div bl

mov ebx, offset tabl

xchg al,ah

xlat

mov masVivod[esi+1],al

mov al,ah

xlat

mov masVivod[esi],al

inc esi

inc esi

jmp met3

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

; Имеем однозначное число. Записываем ASCII код этого числа в память.

met2:

mov ebx, offset tabl

xlat

mov masVivod[esi],al

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

; Ставим после числа в памяти символ «;» в качестве разделителя.

met3:

inc esi

mov masVivod[esi],';'

inc esi

inc edi

loop go1

mov masVivod[esi],0h

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

;вывод на экран получившегося массива

push 0h

push offset Ttl

push offset mes1

push 0h

call MessageBoxA

push 0h

call ExitProcess

end start

Результат:

_______________________________________________________________

Самостоятельно на практике: Вывести все значения элементов массива в несколько строк. В каждой строке должно быть по 5 элементов массива. Значения элементов массива могут быть трёхзначными размером в байт.

Доступ к элементам массива

Все элементы массива располагаются в памяти компьютера последовательно и то, как трактовать данную последовательность решает программист.

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

Эти же соображения можно распространить и на индексы элементов массива.

Наример, в программе статически определена последовательность данных:

Mas dw 0,1,2,3,4,5,456,876,7,8752 ; 00 00 00 01 00 02 00 03 00 04

; 00 05 01 С8 03 6С 00 07 22 30

Организовать доступ к предпоследнему байту можно следующим образом:

1) Mas[19] ; =30

2) Mas[13h] ; =C8

3) Mov esi,19

Mas[esi] ; =30