Лаб10. Макросы. Числовые массивы

Цель работы: ознакомление с принципами написания макросов и их использования в программах, а также с технологиями обработки числовых массивов.

Теоретическая часть

Макроопределения

Одними из самых мощных языковых средств Ассемблера являются макроопределения. Макроопределением (или макросом) называется набор команд, которому присвоено имя и который вставляется в программу всякий раз, когда Ассемблер встречает это имя в тексте программы. Макрос начинается директивой MACRO и заканчивается ENDM. Например, пусть описано макроопределение PUTSPACE, выводящее символ пробела на экран:

PUTSPACE  	macro
		mov	ah,2
		mov	dl,’ ’
		int	21h
endm

Теперь в программе можно использовать слово PUTSPACE как имя команды, и Ассемблер заменит каждое такое слово на макрорасширение, на три команды, содержащиеся в макроопределении. Макроопределения могут вызываться с параметрами, следовательно, в зависимости от ситуации, включаемый код будет генерироваться с различными параметрами, например, как макрос обмена значений в памяти:

CHANGE_VAR	macro	var1, var2
	         push	var1
	         push	var2
	         pop	var1
	         pop	var2
endm

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

Следующее важное средство, использующееся в макроопределениях, –это директивы условного ассемблирования. Например: напишем макрос, выполняющий умножение регистра AL на число, причем, если множитель – степень двойки, то умножение будет выполняться более быстрой командой сдвига влево.

fast_mul  macro	number
     if number eq 2
        shl ax, 1       ;умножение на 2
     elseif number eq 4
	shl ax, 2       ;умножение на 4
     elseif number eq 8
	shl ax, 3       ;умножение на 8
	...
     elseif number eq 128
	shl ax, 7       ;умножение на 128
     else
	mov dx, number 	;умножение на число, не являющееся
	mul	dx	;степенью двойки.
	endif
endm

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

fast_mul_1	macro	number
	i=1
	while i le number and i ne 0 ;пока i меньше или равно number 
                                     ;и не равно 0
	if number eq       ;если i = number
	   rept number
	   shl ax,1	   ;умножаем ax на 2number логическим сдвигом
;на единицу number раз
	   endm
	   i=0		   ;если умножение уже сделано, то i = 0
	else	           ;если i ? number,
	   i=i*2           ;получаем следующую степень числа 2
	endif
endm
	if i ne 0				
	   mov	dx, number ;умножение на число, не являющееся
	   mul	dx	   ;степенью двойки.
	endif
endm

Числовые массивы

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

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

1) Можно перечислить элементы массива в поле операндов. При перечислении элементы разделяются запятыми:
;массив из 5 элементов. Размер каждого элемента 2 байта
mas1	dw	1, 2, 3, 4, 5	
2) Можно использовать оператор повторения DUP:
;массивы из 5 элементов. Размер каждого элемента 2 байта
mas2 	dw	5 dup (?)
mas3 	dw	5 dup (0)
3) Инициализировать элементы массива можно и в цикле:
        mov cx, 5	 ;значение счетчика циклов в cx
        mov si, 0	 ;индекс начального элемента в si
        mov ax, 1	 ;значение первого элемента массива
go:			 ;метка начала цикла
        mov mas2[si], ax ;запись в массив
 
        inc si	;продвижение к следующему элементу массива
        inc si	;или add si,2 ,т.к. данные размером в слово
        inc ax	;инкремент ax
        loop go	;повторить цикл

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

Все элементы массива располагаются в памяти компьютера последовательно. Для того чтобы локализовать определенный элемент массива, к его имени нужно добавить индекс. В языке Ассемблер индексы массивов – это обычные адреса. Нумерация элементов массива начинается с нуля.

Например, пусть дан массив

mas     dw   5, 3, 7, 1, 2

Считываем третий элемент – число 7 в регистр dx. Этот элемент отстоит от начала массива на 4 байта. Поэтому, чтобы обратиться к этому элементу, к базовому адресу необходимо добавить смещение 4.

mov     si, 4
mov     dx, mas[si]

В общем случае для получения адреса элемента в массиве необходимо начальный (базовый) адрес массива сложить с произведением индекса этого элемента на размер элемента массива:

база + (индекс * размер_элемента)

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

mov     si, 2
mov     dx, mas[si*2]

Масштабирование эффективно лишь тогда, когда размерность элементов массива равна 2, 4 или 8. Если же размерность элементов другая, то обращение к элементам массива нужно организовывать обычным способом, описанным ранее.

Типовые операции с массивами

Рассмотрим пример, в котором просматривается массив, состоящий из элементов типа word. Выполняется сравнение этих элементов с нулем и выводится соответствующее сообщение.

Примеры

.model	small
puts	macro s	       ;вывод строки на экран
mov	ah, 9
	lea	dx, s
	int	21h
	endm
putch	macro c	       ;вывод символа на экран
        mov	ah, 2
	mov	dl, c
	int	21h
	endm
 
prolog	macro 	       ;связка ds с сегментом данных
        mov	ax, @data
	mov	ds, ax			 
	endm
epilog	macro	       ;стандартный выход
        mov	ah, 4ch	
	int	21h			
	endm
.stack	64
 
.data	       ;начало сегмента данных
;тексты сообщений
mes1	db	“Не равен 0!”, 0ah, 0dh,$”
mes2	db	“Равен 0!”, 0ah, 0dh,$”
mes3	db	0ah, 0dh, “Элемент $”
mas	dw	5, 3, 0, 7, 1, 0, 0, 2	;исходный массив
 
.code
.486			;директива, позволяющая использовать
			;32–разрядные регистры и масштабирование
			;при обращении к элементам массива
main:
	prolog
	xor	ax, ax	;обнуление ax
prepare:
        mov	cx, 8	;в cx – количество элементов массива,
                        ;которые служат счетчиком циклов
        mov	esi, 0	;индекс в esi
compare: 
        puts	mes3	;вывод сообщения на экран
        mov	dx, si		
        or	dl, 30h	;преобразование цифры в символ
        putch	dl	;вывод значения индекса
 
        mov	dx, mas[esi*2] ;помещаем элемент массива в dx
        cmp	dx, 0	       ;сравнение dx с 0
        je	equal	       ;переход, если равно
not_equal:
	puts	mes1		;вывод сообщения на экран
	jmp	next			
equal:
	puts	mes2		;вывод сообщения на экран
next:
	inc	esi		;на следующий элемент
	dec	cx		;условие для выхода из цикла
	jcxz	exit		;cx = 0? если да – на выход
	jmp	compare		;нет – повторить цикл
exit:
	epilog
	end	main

Задания

  1. Подсчитать количество положительных и количество отрицательных элементов в заданном числовом векторе размера m.
  2. Дана числовая матрица размера mх Создать вектор размера m, содержащий минимальные элементы каждой строки матрицы.
  3. Дана числовая матрица размера mх Создать вектор размера m, содержащий максимальные элементы каждого столбца матрицы.
  4. Дана числовая матрица размера nхn. Определить минимальные элементы в каждой строке матрицы, записать их в первый столбец, а элементы первого столбца – на место соответствующих минимальных.
  5. Дана числовая матрица размера nхn. Определить максимальные элементы в каждом столбце матрицы, записать их в первую строку, а элементы первой строки – на место соответствующих максимальных.
  6. Дан числовой вектор размера m. Подсчитать, сколько раз встречается в нем максимальный элемент.
  7. Дана матрица размера nхn. Определить такие k, где k–я строка матрицы совпадает с k–м столбцом.
  8. Дана целочисленная матрица размера nхn. Определить столбец, содержащий только такие элементы, которые по модулю не больше наперед заданного числа a.
  9. Дан числовой вектор размера m. Найти минимальный из положительных и максимальный из отрицательных элементов.
  10. Дана матрица a размера mхn. Построить вектор b, элементы которого вычисляются по формуле: bi=ai,0+ai,n-1, где i=0,1,…,m-1.
  11. Дана матрица a размера mхn. Построить вектор b, элементы которого вычисляются по формуле: bj=a0,j+am-1,j, где j=0,1,…,n-1.
  12. Дана числовая матрица размера nхn. Построить вектор, элементы которого являются суммами элементов каждой строки матрицы.
  13. Дана числовая матрица размера nхn. Построить вектор, элементы которого являются суммами элементов каждого столбца матрицы.
  14. Дана числовая матрица a размера nхn. Получить матрицу b размера nхn, элементы которой определяются по правилам:

bi,j= {lbrace}{0, if Ai,j >0, 1 otherwise}

  1. Даны числовой вектор из n элементов и числовая матрица размера mхn. Умножить матрицу на вектор.
  2. Перемножить две данные числовые матрицы размера nхn.
рассказать друзьям и получить подарок

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Translate Переводчик

Подписка на новости

SmartResponder.ru
Ваш e-mail: *
Ваше имя: *

Хостинг для Wordpress сайтов