Описание значения заданных команд языка ассемблера

Страницы работы

Содержание работы

1.  _text segment para public 'code'

2.  assume cs:_text,ds:_data

3.  .386

4.  .387

5.  start:

6.  mov ax,_data

7.  mov ds,ax

8.  mov si,offset mas1

9.  mov bx,offset mas2

10. mov cx,10

11. a:

12. mov ax,ds:[si]

13. mov ds:[bx],ax

14. add si,2

15. add bx,2

16. loop a

17. b: 

18. mov flg,0

19. mov si,offset mas2

20. mov cx,9

21. c:

22. mov ax,ds:[si]

23. mov dx,ds:[si+2]

24. cmp ax,dx

25. ja d

26. mov ds:[si],dx

27. mov ds:[si+2],ax

28. mov flg,1

29. d:

30. add si,2

31. loop c

32. cmp flg,1

33. je b

34. mov ax,4c00h

35. int 21h

36. _text ends

37. _data segment use16 para public 'data'

38. mas1 dw 7,4,2,8,6,3,5,9,10,1

39. mas2 dw 10 dup (0)

40. flg db 0

41. _data ends

42. end start


  1. Начало сегмента кода (‘code’). Сегменту присваивается имя _text. Директива para указывает, что адрес начала сегмента будет выровнен на величину параграфа, т.е. 16 байт. Иными словами физический адрес начала сегмента будет кратен 16 байтам. Public – дословно с книги: “заставляет компоновщик соединить все сегменты с одинаковым именем.”. Короче это важно только тогда, когда у нас код, данные или стек расписаны сразу в нескольких компилируемых файлах и из них надо слепить один исполняемый файл. Нам от этого ни тепло – ни холодно, т.к. у нас программа сосредоточена в одном файле и директиву public в принципе можно не указывать.
  2. Связывание регистров cs и ds с именами сегментов _text и _data. Делается это для корректной работы транслятора. Сегмент _data описан в конце программы.
  3. Указываем, что компилировать под режим 386 процессора. Смысл использования именно этого режима мне не ясен, т.к. мы не используем его наворотов: 32-битной адресаци и 32-битных регистров EAX, EBX, EDX и т.д. Эту и следующую строки я передрал из методы.
  4. Эта строка мне вообще не понятна и что самое интересное нигде нет ее описания. Я проверял – программа прекрасно работает и без нее.
  5. Объявляем первую и поэтому главную метку start. Считается, что с первой метки начинается описание команд сегмента кода.
  6. Записываем в ax адрес начала сегмента _data.
  7. Переносим адрес из регистра-аккумулятора ax в сегментный регистр ds. Теперь по адресу ds:0 находится младший байт первого элемента массива mas1.
  8. В регистр si записываем смещение (offset) переменной mas1 - адрес массива mas1 относительно адреса ds:0. Так как в данном случае эти адреса совпадают, то в si окажется 0.
  9. Аналогично в bx записываем адрес массива mas2 относительно адреса ds:0. В bx окажется число 20. Объясняю почему: mas1 – массив из 10 двухбайтовых чисел (размер 20 байт), т.е. он в памяти займет адреса с ds:0 по ds:13h (ds:19). Следовательно массив mas2, следующий в памяти следом за mas1 начнется с адреса ds:14h (ds:20). Т.е. его смещение относительно ds:0 равно 20 байтам, что и требовалось доказать.
  10. Заносим в cx кол-во элементов, которые необходимо переслать из массива mas1 в массив mas2.
  11. Объявляем метку а. Можешь назвать ее как угодно, лишь бы имена меток не совпадали и команды перехода ссылались на нужные метки.
  12. Записываем в ax слово (2 байта) находящееся по адресу ds:[si].
  13. Записываем это слово по адресу ds:[bx] из регистра ax. Короче этими двумя командами происходит пересылка одного элемента из массива mas1 в массив mas2.
  14. Увеличиваем si на 2, т.к. размер элемента массива 2 байта.
  15. Увеличиваем bx на 2.
  16. Если cx не равно 0, то уменьшить его на 1 и перейти на метку а. Это все смысл одной команды loop a.
  17. Объявляем метку b.
  18. Обнуляем флаг перестановки – переменную flg. Можешь обозвать ее по-другому, но придется менять в программе и все ссылки на нее.
  19. Записывам в si смещение массива mas2.
  20. Записываем в cx кол-во циклов сравнения элементов.
  21. Объявляем метку с.
  22. В ax записываем элемент находящийся по адресу ds:[si].
  23. В dx записываем элемент находящийся по адресу ds:[si+2], т.е. следующий элемент.
  24. Сравниваем ax и dx. Физически, результатом работы этой команды является установка определенных битов регистра флагов в 1, в зависимости от результата сравнения. Все это нужно для следующей команды, которая как раз анализирует состояние этих битов. Не путай регистр флагов с переменной – флагом перестановки, которую мы объявили в программе. Они не имеют ничего общего. За регистром флагов следит микропроцессор, а за нашим флагом мы следим сами – програмно.
  25. Если ax>dx прыгнуть на метку d. ja – сокращение от Jump if Above (прыгнуть если больше).
  26. Если переход в строке 25 не произошел, т.е. ax<=dx, значит элементы [si] и [si+2] стоят не в порядке убывания и их надо переставить, что мы и делаем строками 26 и 27.
  27.  
  28. Записываем в флаг перемещений единицу. Т.е. в данном проходе произошла хотя бы одна перестановка элементов массива. Это свидетельствует, что упорядочивание массива еще не закончено.
  29. Объявляем метку d.
  30. Увеличиваем si на 2.
  31. Если cx не равно 0, то уменьшить его на 1 и перейти на метку с.
  32. После того как сравнили по порядку все элементы (1 со 2, 2 с 3, 3 с 4 … 9 с 10), сравниваем значение нашего флага перестановки с единицей.
  33. Если он равен 1, прыгнуть на метку b. je – сокращение от Jump if Equal (прыгнуть если равно).
  34. Стандартное завершение работы для программы, компилируемой в exe-файл.
  35. Стандартное завершение работы для программы, компилируемой в exe-файл.
  36. Конец сегмента _text, т.е. кодового сегмента – далее можно описывать прочие сегменты (данных, стека, дополнительных данных и т.д.).
  37. Начало описания сегмента данных (‘data’). Помимо уже известного имеется директива use16, которая говорит о том, что адресация – 16-битная и следовательно размер сегмента ограничивается 64кБ. Если не указать эту директиву, то для режима 386 компилятор выдаст ошибки, т.к. под режим 386 по умолчанию вставляется директива use32 (адресация 32-битная, до 4Гб на сегмент – используется для программирования под защищенный режим микропроцессора).
  38. Объявляем массив mas1
  39. Объявляем массив mas2. Запись dw 10 dup (0) означает 10 однотипных (dup) ячеек с размером каждой 2 байта (dw) с начальным значением каждой равным 0.
  40. Объявляем однобайтовую (db) переменную flg – флаг перестановки.
  41. Конец сегмента _data.
  42. Конец главной метки start. Только для главной метки необходимо в самом конце программы писать: end <имя метки> и не спрашивай зачем – надо и все!

Похожие материалы

Информация о работе