assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 62
Текст из файла (страница 62)
Сложные структуры данныхЗдесь i = О...и-l — номер строки, aj = O...m-l — номер столбца. Например, пустьимеется массив чисел (размером в 1 байт) mas(i, j) с размерностью 4 • 4 (г = 0...3,;-0...3):23040567050607996708092387090008В памяти элементы этого массива будут расположены в следующей последовательности:23 04 05 67 05 06 07 99 67 08 09 23 87 09 00 08Если мы хотим трактовать эту последовательность как двухмерный массив,приведенный раньше, и извлечь, например, элемент mas(2, 3) = 23, то, проведя нехитрый подсчет, убедимся в правильности наших рассуждений:Эффективный адрес mas(2, 3) = mas + (4 • 2 + 3) • 1= mas + 22.Посмотрите на представление массива в памяти и убедитесь, что по этому смещению действительно находится нужный элемент массива.Логично организовать адресацию двухмерного массива, используя рассмотренную нами ранее базово-индексную адресацию.
При этом возможны два основныхварианта выбора компонентов для формирования эффективного адреса:* сочетание прямого адреса как базового компонента адреса и двух индексныхрегистров для хранения индексов:mov a x , m a s [ e b x ] [ e s i ]« сочетание двух индексных регистров, один из которых является и базовым, и индексным одновременно, а другой — только индексным:mov a x , [ e b x ] [ e s i ]В программе это будет выглядеть примерно так:;Фрагмент программы выборки элемента;массива m a s ( 2 , 3 ) и его обнуления.datamas db 2 3 , 4 , 5 , 6 7 . 5 , 6 , 7 , 9 9 , 6 7 , 8 , 9 , 2 3 , 8 7 , 9 , 0 , 8i=2]=3el_size=l.code!386mov e s i , 4 * e l _ s i z e * imov di,j *el_sizemov a l , m a s [ e s i ] [ e d i ] ; в al элемент m a s ( 2 , 3 )В качестве законченного примера рассмотрим программу поиска элемента в двухмерном массиве чисел (листинг 13.4).
Элементы массива заданы статически.Листинг 13.4. Поиск элемента в двухмерном массиве;prg_13_4.asmMASMMODELSTACK.datasmall256Массивы{матрица размером 2x5 - если ее не инициализировать,;то для наглядности она может быть описана так:;аггау dw 2 DUP (5 DUP (?));но мы ее инициализируем:array dw 1,2,3,3,5,6,7,3,9,0;логически это будет выглядеть так:;аггау= {1 2}О 3}(5 6}{7 3}{9 0}size_elem=2; размер элементаelemdw 3; элемент для поискаfailed db 0ah,0dh, 'Нет такого элемента в массиве! ','$'success db 0ah,0dh, 'Такой элемент в массиве присутствует ","$'foundtime dbколичество наиденных элементовfnd db ' раз(а)' ,0ah,0dh,'$'.codemain:mov ax,@datamov ds.axxor ax,axmov s i, 0;51=столбцы в матрицеmov bx,0;Ьх=строки в матрицеmov ex,5;число для внешнего цикла (по строкам)external:;внешний цикл по строкамpush exсохранение в стеке счетчика внешнего циклаmov ex,2;число для внутреннего цикла (по столбцам)mov s i, 0iternal:внутренний цикл по строкамmov ax,array[bx][si];в ах первый (очередной) элемент матрицыadd si,size_elem;передвижение на следующий элемент в строкесравниваем содержимое текущего элемента в ах с искомым элементом:cmp ax.elem;если текущий совпал с искомым, то переход на here для обработки,;иначе - цикл продолжения поискаjne $-1-6inc foundtimeувеличиваем счетчик совпавшихloop iternalmove_next:{продвижение в матрицеpop exвосстанавливаем СХ из стека (5)add bx,size_elem*2 {передвигаемся на следующую строкуloop external;цикл (внешний)cmp foundtime,0hсравнение числа совпавших с 0ja eql;если больше 0, то переходnot_equal:;нет элементов, совпавших с искомым;вывод сообщения на экранmov ah,09hmov dx,offset failedint 21hна выходjmp exitесть элементы, совпавшие с искомымeql:mov ah,09h; вывод сообщений на экранmov dx,offset successint 21hmov ah,02hmov dl,foundtimeadd dl,30hint 21hmov ah,09hmov dx,offset fndint 21hвыходexit:стандартное завершение программыmov ax,4c00hint 21hконец программыmainend277278Глава 13.
Сложные структуры данныхАнализируя работу программы, не забывайте, что при написании программ наязыке ассемблера нумерацию элементов массива удобнее производить с 0. Припоиске определенного элемента массив просматривается от начала и до конца.Программа сохраняет в поле foundtime количество вхождений искомого элементав массив. В качестве индексных используются регистры SI и ВХ.Типовые операции с массивамиДля демонстрации основных приемов работы с массивами лучше всего подходятпрограммы поиска или сортировки. Программа поиска была приведена ранее. Теперь рассмотрим одну из программ, выполняющих сортировку массива по возрастанию (листинг 13.5).Листинг 13.5.
Сортировка массива;prg_13_5.asmMASMMODELsmallSTACK256.datamesl db 0ah,0dn,'Исходный массив - $',0ah,0dh;некоторые сообщенияmes2 db Oah,0dh,'Отсортированный массив - $',0ah,0dhn equ 9количество элементов в массиве, считая с 0mas dw 2,7,4,0,1,9,3,6,5,8 ;исходный массивtrap dw 0;переменные для работы с массивомi dw 0j dw 0.codemain:mov ax,@datamov ds.axxor ax,ax;вывод на экран исходного массиваmov ah,09hlea dx.meslint 21h;вывод сообщения meslmov ex,10mov si,0show_primary:;вывод значения элементов•.исходного массива на экранmov dx,mas[si]add dl,30hmov ah,02hint 21hadd si ,2loop show_primaryстроки 40-85 программы эквивалентны следующему коду на языке С:for (i=0;i<9;i++)for (j=9;j>i;j--)if (mas[i]>mas[j]){tmp=mas[i];mas[i]=mas[j];mas[j]=tmp;}mov i,0инициализация iвнутренний цикл по jinternal:mov j,9;инициализация jjmp cycl_j;переход на тело циклаexchange:Массивыmov bx, ishl bx,l;bx=imov ax,raas[bx];ax=mas[i]: bx=jcmp ax,mas[bx]j I e lessermov bx, ishl bx,lmov tmp.ax;mas[i] ? mas[j] - сравнение элементов;если mas[i] меньше, то обмен не нужен;и переход на продвижение далее по массиву;иначе tmp=mas[i], mas[i]=mas[j], mas[j]=tmp:;tmp=mas[i]; bx=i;умножаем на 2, так как элементы - слова: tmp=mas[i]movshlmovmovshlmovbx, jbx,lax,mas[bx]bx, ibx.lmas[bx],ax; m a s [ i ] = m a s [j ]; bx=j;умножаем на 2, так как элементы - слова;ax=mas[j]; bx=i;умножаем на 2, так как элементы - слова;mas[i]=mas[j]movshlmovmovlesser:bx, jbx,lax.tmpmas[bx].axmov b x .
jshl bx,ldec jcycl_j:mov ax,jcmp ax.ijg exchangei nc icrnp i , nj 1 internal279;mas[j]=tmp; bx=j;умножаем на 2, так как элементы - слова:ax=tmp;mas[j]=tmpпродвижение далее по массиву во внутреннем;цикле:J-;тело цикла по j;ax=j; сравнить j ? i;если j>i, то переход на обмен; иначе - на внешний цикл по i;сравнить i ? n - прошли до конца массива;если i<n - продолжение обработки;вывод отсортированного массиваmov ah,09hlea dx,mes2int 21hprepare:mov ex,10mov si ,0show:.mov d x .
m a s f s i ]add dl,30hmov ah,02h;вывод значения элемента на экранint 21hadd si , 2loop showexit:mov ax,4c00hint 21hстандартный выходend main;конец программыВ основе программы лежит алгоритм, похожий на метод пузырьковой сортировки. Эта программа не претендует на безусловную оптимальность, так как существует целая теория, касающаяся подобного типа сортировок. Перед нами стоитдругая цель — показать использование средств ассемблера для решения подобно-280Глава 13. Сложные структуры данныхго рода задач.
В программе два цикла. Внешний цикл определяет позицию в массиве очередного элемента, с которым производится попарное сравнение элементов правой части массива (относительно этого элемента). За каждую итерациювнешнего цикла на месте этого очередного элемента оказывается меньший элемент из правой части массива (если он есть). В остальном программа довольнопроста и на языке высокого уровня заняла бы около десятка строк. Более подробно с реализацией различных типов сортировок на языке ассемблера можно познакомиться в [8].СтруктурыРассмотренные нами ранее массивы представляют собой совокупность однотипных элементов. Но часто в приложениях возникает необходимость рассматриватьнекоторую совокупность данных разного типа как некоторый единый тип.
Это оченьактуально, например, для программ баз данных, где с одним объектом может ассоциироваться совокупность данных разного типа. К примеру, ранее мы рассмотрели листинг 13.3, в котором работа производилась с массивом трехбайтовых элементов. Каждый элемент, в свою очередь, представлял собой два элемента разныхтипов: однобайтовое поле счетчика и двухбайтовое поле, которое могло нести ещекакую-то нужную для хранения и обработки информацию. Если читатель знакомс одним из языков высокого уровня, то он знает, что такой объект обычно описывается с помощью специального типа данных — структуры. С целью повыситьудобство использования языка ассемблера в него также был введен такой типданных.По определению структура — это тип данных, состоящий из фиксированногочисла элементов разного типа.Для использования структур в программе необходимо выполнить три действия.1.
Задать шаблон структуры. По смыслу это означает определение нового типаданных, который впоследствии можно использовать для определения переменных этого типа.2. Определить экземпляр структуры. Этот этап подразумевает инициализациюконкретной переменной с заранее определенной (с помощью шаблона) структурой.3. Организовать обращение к элементам структуры.Очень важно хорошо понимать разницу между описанием структуры в программе и ее определением. Описание структуры в программе означает лишь указаниекомпилятору ее схемы, или шаблона; память при этом не выделяется. Компиляторизвлекает из этого шаблона информацию о расположении полей структурыи их значениях по умолчанию. Определение структуры означает указаниетранслятору на выделение памяти и присвоение этой области памяти символического имени.