Учебник по ассемблеру (ASM)
 

Ассемблер в примерах - Удаление максимума и минимума массива

Вопрос:
нужно удалить максимум и минимум массива.

особенности реализации:

использовать процедуру вывода на экран.
разбить код программы на процедуры для лучшей читабельности.
применить передачу параметра через стек!!!

Ответ:
.model tiny, C ; Делаем COM-файл и передаем параметр, как в С
.186
.code
org 100h
start:
   mov ax, 3
   int 10h	; устанавливаем текстовый режим
   
   cld  	; буду использовать строковые инструкции
   		; установим флаг направления
   ;выводим массив
   call output, offset ar, arsize, offset srcArray

    ; определение минимального и максимального
   call minmax, offset ar, arsize, offset min_el, offset max_el

    ; вывод минимального и максимального
   call PrintNum, offset minElem, min_el
   call PrintNum, offset maxElem, max_el

   ; удаляем минимальный и максимальные элементы
   call DelMinMax, offset ar, arsize, min_el, max_el

   ; выведем результат
   call output, offset ar, ax, offset dstArray


  lea dx, PressKey
  mov ah,9
  int 21h

  xor ax, ax
  int 16h

  int 20h
  
; две подпрограммы для вывода чисел на экран  
  writeWordDEC proc near
; вывод на экран слова в AX, воспринимается как беззнаковое
  uses cx, dx, bx, ax
   mov bx, 10
   xor cx, cx
@@1:
   xor dx, dx
   div  bx
   push dx
   inc cx
   or ax, ax
   jnz @@1
 @@2:
   pop ax
   add al, '0'
   int 29h	; это прерывание умеет делать только одно -
   		; выводить символ в AL на экран
   LOOP @@2    

 ret
writeWordDEC endp

WriteWordDEC_signed proc
; вывод на экран слова в AX как знакового
; просто, если отрицательное, выводит минус, превращает в
; положительное и вызывает подпрограмму writeWordDEC
uses ax
 or ax, ax
 jns @@_no_sign 
   push ax
   mov al, '-'
   int 29h
   pop ax
   neg ax ; изменение знака на +
@@_no_sign:
 CALL writeWordDEC     
 ret
WriteWordDEC_signed endp 

;вывод на экран массива с заголовком
output	proc addrarray:word, arraysize:word, prstring:word
uses cx, si, ax, dx
   mov dx, prstring
   mov ah, 9
   int 21h
   mov cx, arraysize
   mov si, addrarray
   jcxz @@output_ret	;вдруг пусто (например, все потерли) :)
@@_next:
    lodsw
    CALL writeWordDEC_signed
    mov al, ' '
    int 29h
    int 29h
LOOP @@_next   
@@output_ret:
    ret
output	endp

;определение мин и макс элементов
minmax	proc	array:word, count:word, addrmin:word, addrmax:word
uses si, dx, bx, cx, ax
    mov si, array
    lodsw
    mov dx, ax	;мин
    mov bx, ax 	;макс
    mov cx, count      
@@_analize_next:
      lodsw
      cmp ax, dx
      jge @@10
      mov dx, ax
@@10:
      cmp ax, bx
      jle @@20
      mov bx, ax
@@20:
LOOP @@_analize_next
    mov si, addrmin	;сохраним по адресу мин
    mov [si], dx
    mov si, addrmax	;сохраним по адресу макс
    mov [si], bx
    ret
minmax	endp

;вывод числа с заголовком
PrintNum	proc string:word, num:word
uses dx, ax
  mov dx, string
  mov ah, 9
  int 21h
  mov ax, num
  CALL writeWordDEC_signed
  ret
PrintNum	endp

DelMinMax proc, arr:word, arrsize:word, delmin:word, delmax:word
uses si, di, cx
    mov si, arr	; адрес исходного массива
    mov di, si	; сюда же будем писать и результат
    mov cx, arrsize      ;длина исходного массива
@@_delete_min_max_next:
      lodsw
      cmp ax, delmin	;если равен минимальному 
      je @@30
      cmp ax, delmax	;  или максимальному
      je @@30		;  то проигнорируем
      stosw		;иначе сохраним
@@30:
LOOP @@_delete_min_max_next
   mov ax, di		;di - адрес за результатом
   sub ax, arr		;ax - длина результата в байтах 
   shr ax, 1		;ax - длина результата в словах 
   ret
DelMinMax endp  

PressKey db 13,10,10,'Press any key ...$'

srcArray db 'Исходный массив:',13,10,'$'
maxElem  db 13,10,'Максимальный элемент массива: $'
minElem  db 13,10,'Минимальный  элемент массива: $'
dstArray db 13,10,'Результирующий массив:',13,10,'$'

	align	2
ar       dw 1, 12, 23, -3, -4, 0, 7	; сюда просто добавляйте числа, если хотите
arsize   equ ($ - ar)/2  	; так определяется констата = размер массива в словах (число элементов)
			; $ - операция вычисления текущего адреса
min_el   dw  0
max_el   dw  0		
end start

   Вперёд
   Содержание