ХАНДЫФАР

Функция ArrayCopyIf копирует элементы из первого массива во второй массив на основании условия, заданного пользовательской функцией, переданной через указатель. Если размер массива DX = 0, функция завершает работу без изменений. Пользовательская функция обязана сохранять регистры AX, BX, DX, SI и DI в стеке.

Параметры:

  • DS:AX: Указатель на первый массив (источник).
  • ES:BX: Указатель на второй массив (назначение).
  • CX: ___Указатель на пользовательскую функцию, которая определяет, должен ли элемент быть скопирован.
  • DX: ___Размер массива (количество элементов). Если DX = 0, функция завершает работу.

Возвращаемое значение:

  • CX: Количество скопированных элементов во втором массиве.

Состояние флагов:

  • Функция не изменяет состояние флагов.

Особенности:

  • Функция проходит по первому массиву и копирует элементы во второй массив, если они удовлетворяют условию, заданному пользовательской функцией.

  • Пользовательская функция должна возвращать ZF=1, если элемент должен быть скопирован, и ZF=0, если нет.

  • Если размер массива DX = 0, функция завершает работу и возвращает CX = 0.

  • Функция не изменяет значения регистров, кроме CX.

  1. title Автор: Довгополов Евгений Сергеевич
  2. .model small
  3. .stack 100h
  4. data segment public
  5. ____array__dw _1, 2, 3, 4, 5, 7, 8, 9, 10
  6. ____arrlen equ ($-array) / 2
  7. ____buffer_dw _arrlen dup(?)
  8. ____fmtout db__"[%d] \0"
  9. data ends
  10. code segment public
  11. ____assume _ds:data, cs:code
  12. ____include Handyfar.inc
  13. ____include Handymac.inc
  14. ____main proc
  15. ________call____SetDataSegment
  16. ________mov_____dx, arrlen
  17. ________lea_____cx, IsDivBy2
  18. ________lea_____bx, es:[buffer]
  19. ________lea_____ax, ds:[array]
  20. ________call____ArrayCopyIf
  21. ________lea_____bx, ds:[buffer]
  22. ________xor_____si, si
  23. ____PrintArrayLoop:
  24. ________push____word ptr[bx+si]
  25. ________lea_____ax, ds:[fmtout]
  26. ________call____PrintFormatString
  27. ________add_____sp, 2
  28. ________incw____si
  29. ________loop____PrintArrayLoop
  30. ________xor_____al, al
  31. ________call____ExitProcess
  32. ____main endp
  33. ____IsDivBy2 proc
  34. ________push____ax
  35. ________push____bx
  36. ________push____dx
  37. ________mov_____bx, 2
  38. ________cwd
  39. ________idiv____bx
  40. ________test____dl, dl
  41. ________pop____dx
  42. ________pop____bx
  43. ________pop____ax
  44. ________ret
  45. ____IsDivBy2 endp
  46. code ends
  47. end main
Функция ArrayCopyIf копирует элементы из первого массива во второй массив на основании условия, заданного пользовательской функцией, переданной через указатель. Если размер массива DX = 0, функция завершает работу без изменений. Пользовательская функция обязана сохранять регистры AX, BX, DX, SI и DI в стеке.

Параметры:

  • DS:AX: Указатель на первый массив (источник).
  • ES:BX: Указатель на второй массив (назначение).
  • CX: ___Указатель на пользовательскую функцию, которая определяет, должен ли элемент быть скопирован.
  • DX: ___Размер массива (количество элементов). Если DX = 0, функция завершает работу.

Возвращаемое значение:

  • CX: Количество скопированных элементов во втором массиве.

Состояние флагов:

  • Функция не изменяет состояние флагов.

Особенности:

  • Функция проходит по первому массиву и копирует элементы во второй массив, если они удовлетворяют условию, заданному пользовательской функцией.

  • Пользовательская функция должна возвращать ZF=1, если элемент должен быть скопирован, и ZF=0, если нет.

  • Если размер массива DX = 0, функция завершает работу и возвращает CX = 0.

  • Функция не изменяет значения регистров, кроме CX.

  1. title Автор: Довгополов Евгений Сергеевич
  2. .model small
  3. .stack 100h
  4. data segment public
  5. ____array__dw _1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12
  6. ____arrlen equ ($-array) / 2
  7. ____buffer_dw _arrlen dup(?)
  8. ____fmtout db__"[%d] \0"
  9. data ends
  10. code segment public _______________; Начало сегмента кода
  11. ____assume _ds:data, cs:code
  12. ____include Handyfar.inc___________; Подключаем файл с функциями
  13. ____include Handymac.inc___________; Подключаем файл с макросами
  14. ____main proc _____________________; Начало процедуры main
  15. ________call____SetDataSegment_____; Вызываем процедуру SetDataSegment
  16. ________mov_____dx, arrlen_________; Копируем длину массива в регистр dx
  17. ________lea_____cx, IsDivBy2_______; Загружаем адрес процедуры IsDivBy2 в регистр cx
  18. ________lea_____bx, es:[buffer]____; Загружаем адрес переменной buffer в регистр es:bx
  19. ________lea_____ax, ds:[array]_____; Загружаем адрес переменной array в регистр ds:ax
  20. ________call____ArrayCopyIf________; Вызываем процедуру ArrayCopyIf(ds:ax, es:bx, cx, dx) := CX
  21. ________lea_____bx, ds:[buffer]____; Загружаем адрес массива buffer в регистр ds:bx
  22. ________xor_____si, si_____________; Обнуляем регистр-индекс si
  23. ____PrintArrayLoop:
  24. ________push____word ptr[bx+si]____; 2-й: Сохраняем значение в bx под индексом si в стеке
  25. ________lea_____ax, ds:[fmtout]____; 1-й: Загружаем адрес строки формата fmtout в регистр ds:ax
  26. ________call____PrintFormatString__; Вызываем процедуру PrintFormatString(ax:fmtout, bx)
  27. ________add_____sp, 2______________; Выравниваем стек
  28. ________incw____si_________________; Вызываем макрос incw. Увеличиваем индекс si на 2
  29. ________loop____PrintArrayLoop_____; Выполняем цикл пока CX≠0
  30. ________xor_____al, al_____________; Обнуляем регистр al
  31. ________call____ExitProcess________; Вызываем процедуру ExitProcess
  32. ____main endp _____________________; Конец процедуры main
  33. ____IsDivBy2 proc__________________; Начало процедуры IsDivBy2
  34. ________push____ax_________________; Обязательно сохраняем значение регистра ax в стеке
  35. ________push____bx_________________; Обязательно сохраняем значение регистра bx в стеке
  36. ________push____dx_________________; Обязательно сохраняем значение регистра dx в стеке
  37. ________mov_____bx, 2______________; Копируем число 2 в регистр bx
  38. ________cwd________________________; Выполняем знаковое расширение регистра dx
  39. ________idiv____bx_________________; Делим значение в регистре ax на bx
  40. ________test____dl, dl_____________; Проверяем значение на 0
  41. ________pop____dx__________________; Обязательно выталкиваем значение из стека обратно в регистр dx
  42. ________pop____bx__________________; Обязательно выталкиваем значение из стека обратно в регистр bx
  43. ________pop____ax__________________; Обязательно выталкиваем значение из стека обратно в регистр ax
  44. ________ret________________________; Возврат из функции
  45. ____IsDivBy2 endp__________________; Конец процедуры IsDivBy2
  46. code ends _________________________; Конец сегмента кода
  47. end main __________________________; Конец файла. Точкой входа указывается процедура main
Made on
Tilda