Как найти максимальный элемент массива ассемблер

390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

1

В массиве найти минимальный и максимальный элемент

11.09.2012, 02:25. Показов 54441. Ответов 22


Студворк — интернет-сервис помощи студентам

Здравствуйте! На ассемблере последний раз писал что-то ещё на 1-м курсе универа и всё забыл за неимением практики. А тут пришла знакомая и попросила помочь с заданием.
Если не сложно, помогите мне. Буду очень благодарен.
Задание:
1) в массиве найти минимальный и максимальный элемент;

Добавлено через 8 минут
Желательна максимальная простота кода и, если не сложно, комментарии, т.к. это потом ей ещё защищать.



0



Troll_Face

608 / 406 / 8

Регистрация: 26.04.2012

Сообщений: 2,065

12.09.2012, 19:34

2

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mov si, offset array
mov cx, array_len
xor bx, bx                     ;в bh - максимум, в bl - минимум...
@1: 
     lodsb 
     cmp al, bh
     jg max
     cmp al, bl
     jl min
     jmp @@1
min: 
     and bl, al
     jmp @@1
max:
    and bh, al
@@1:
    loop @1

не тестировал, сразу говорю, но вроде так…

Добавлено через 22 часа 34 минуты
body90, пардон))) хотел повыпендриваться)))

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mov si, offset array
mov cx, array_len
xor bx, bx                     ;в bh - максимум, в bl - минимум...
@1: 
     lodsb 
     cmp al, bh
     jg max
     cmp al, bl
     jl min
     jmp @@1
min: 
     mov bl, al
     jmp @@1
max:
    mov bh, al
@@1:
    loop @1



3



390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

12.09.2012, 21:42

 [ТС]

3

И не понимаю, что делает «lodsb». Можете пояснить, для чего эта команда в этом коде?



0



390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

12.09.2012, 21:57

 [ТС]

4

Вот что у меня получается:

Миниатюры

В массиве найти минимальный и максимальный элемент
 



0



390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

12.09.2012, 22:11

 [ТС]

5

В архиве то, что я написал. Запускаю по run.bat.



0



766 / 310 / 11

Регистрация: 27.05.2011

Сообщений: 703

12.09.2012, 22:14

6

body90, ты наверно думаешь, что представленный код является полным?
это только выполнение твоего задания(поиск min,max), оформление здесь отсутствует, как допишешь его, так и сможешь проверить..
возми ту же элементарную программку — Hello World, впиши туда то что тебе написали и всё..
только вот ещё одно, результата на экране ты не увидишь, пока не допишешь вывод, либо ч/з отладчик..



2



body90

390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

12.09.2012, 22:25

 [ТС]

7

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.model   small
.data
array dd 1,2,3,4,5
mov si, offset array
mov cx, 5
xor bx, bx                     ;в bh - максимум, в bl - минимум...
.code
main:
@1: 
     lodsb 
     cmp al, bh ;сравнение al и bh
     jg max
     cmp al, bl
     jl min
     jmp @@1
min: 
     mov bl, al
     jmp @@1
max:
    mov bh, al
@@1:
    loop @1
end main
end

Написал так. Компиллируется без ошибок, но вот когда запускаю *.exe — выскакивает ошибка с кнопкой «Закрыть». Я что-то неправильно сделал?

Цитата
Сообщение от zzzyyyxxx
Посмотреть сообщение

только вот ещё одно, результата на экране ты не увидишь, пока не допишешь вывод, либо ч/з отладчик..

А как вывод делать?



0



766 / 310 / 11

Регистрация: 27.05.2011

Сообщений: 703

12.09.2012, 22:28

8

ну у тебя часть кода находится в данных, перенести надо..
по поводу вывода — https://www.cyberforum.ru/asse… 54461.html, выбирай, что душе угодно..



1



body90

390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

13.09.2012, 02:16

 [ТС]

9

.data должен быть пустым?

Добавлено через 36 минут
Так тоже вылетает с ошибкой:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.model   small
.data
.code
array dd 1,2,3,4,5
mov si, offset array
mov cx, 5
xor bx, bx                     ;в bh - максимум, в bl - минимум...
@1: 
     lodsb 
     cmp al, bh ;сравнение al и bh
     jg max
     cmp al, bl ;сравнение al и bl
     jl min
     jmp @@1
min: 
     mov bl, al
     jmp @@1
max:
    mov bh, al
@@1:
    loop @1 ; переход на следующий элемент массива
end

Добавлено через 25 минут
Подскажите, пожалуйста, что я ещё неправильно делаю. А то мне сегодня её уже надо отдать…



0



390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

13.09.2012, 02:49

 [ТС]

10

Вот как оно вылетает (первое изображение) после нажатия F9 в TLINK.exe.
На втором изображении то, что видно на консоли, если я сделаю это же через DosBox. После этого курсор просто мигает и не реагирует ни на какие нажатия.

Миниатюры

В массиве найти минимальный и максимальный элемент
 

В массиве найти минимальный и максимальный элемент
 



0



390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

13.09.2012, 05:31

 [ТС]

11

Почему-то мне кажется, что приложение просто зацикливается.

Добавлено через 2 часа 18 минут
И с этим разобрался, но в bh и bl ложатся числа, которых даже нет в массиве. Посмотрел в Turbo Debuggere в окне Wotches. Что может быть не так?



0



Ушел с форума

Автор FAQ

15883 / 7459 / 1010

Регистрация: 11.11.2010

Сообщений: 13,442

13.09.2012, 05:47

12

body90, опять используется массив двойных слов вместо массива байтов, и массив array убери из секции code в секцию data
будь внимательнее и думай головой



1



body90

390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

13.09.2012, 11:08

 [ТС]

13

Mikl___, сделал так, как Вы сказали. Совсем теперь по «циклу» один раз стало проходить.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Title   Laba
;=====================================
StackSG segment ; Stack segment
    dw  1024    dup (?)
StackSG Ends
;=====================================
DataSG  Segment; Data segment
DataSG Ends
;=====================================
CodeSG  Segment ; Code segment
    assume  ss:StackSG,cs:CodeSG,ds:DataSG
 
BEGIN:
array db 7,2,10,4,26
mov si, offset array
mov cx, 5
xor bx, bx
@1: 
     lodsb 
     cmp al, bh
     jg max
     cmp al, bl
     jl min
     jmp @@1
min: 
     mov bl, al
     jmp @@1
max:
    mov bh, al
@@1:
    loop @1
mov     ah,4ch
int 21h
CodeSG  Ends
END BEGIN

Добавлено через 21 минуту
А тут точно можно использовать bh и bl? Я не могу понять их поведения. Они по прежнему получают значения, которых вообще нет в массиве. Ещё и меняют значение, когда выполняется последний кусок кода

Assembler
1
2
3
4
mov     ah,4ch
int 21h
CodeSG  Ends
END BEGIN

хотя обращений к ним нет. Может я чего-то не понимаю.

Добавлено через 25 секунд
Может кто-то скомпиллировать мой код и сказать что не так?



0



Ушел с форума

Автор FAQ

15883 / 7459 / 1010

Регистрация: 11.11.2010

Сообщений: 13,442

13.09.2012, 11:40

14

body90, тебе же сказали — помести array в сегмент данных!



1



body90

390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

13.09.2012, 11:46

 [ТС]

15

Всё равно результат тот же.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Title   Laba
;=====================================
StackSG segment ; Stack segment
    dw  1024    dup (?)
StackSG Ends
;=====================================
DataSG  Segment; Data segment
array db 7,2,10,4,26
DataSG Ends
;=====================================
CodeSG  Segment ; Code segment
    assume  ss:StackSG,cs:CodeSG,ds:DataSG
 
BEGIN:
mov si, offset array
mov cx, 5
xor bx, bx
@1: 
     lodsb 
     cmp al, bh
     jg max
     cmp al, bl
     jl min
     jmp @@1
min: 
     mov bl, al
     jmp @@1
max:
    mov bh, al
@@1:
    loop @1
mov     ah,4ch
int 21h
CodeSG  Ends
END BEGIN

В момент до выполнения строки

Assembler
1
mov     ah,4ch

bh = 32
bl = 159



1



390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

13.09.2012, 11:47

 [ТС]

16

Вот скрин.

Миниатюры

В массиве найти минимальный и максимальный элемент
 



1



Mikl___

Ушел с форума

Автор FAQ

15883 / 7459 / 1010

Регистрация: 11.11.2010

Сообщений: 13,442

13.09.2012, 11:50

17

должно быть вот так

Assembler
1
2
3
4
5
BEGIN: mov ax,DataSG
mov ds,ax
mov si, offset array
mov cx, 5
xor bx, bx



2



390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

13.09.2012, 11:56

 [ТС]

18

bh работает, а в bl теперь всё время лежит 0, хотя в массиве минимальный элемент = 2.



0



Ушел с форума

Автор FAQ

15883 / 7459 / 1010

Регистрация: 11.11.2010

Сообщений: 13,442

13.09.2012, 12:03

19

body90, естественно, потому что изначально BL=0, а ноль всегда меньше двух
поставь вместо xor bx,bx команду mov bx,7Fh и всё заработает



1



body90

390 / 323 / 19

Регистрация: 26.05.2009

Сообщений: 2,696

13.09.2012, 12:03

 [ТС]

20

Не знаю правильно ли, но вышел из ситуации так:

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Title   Laba
;=====================================
StackSG segment ; Stack segment
    dw  1024    dup (?)
StackSG Ends
;=====================================
DataSG  Segment; Data segment
    array db 7,2,10,4,26
DataSG Ends
;=====================================
CodeSG  Segment ; Code segment
    assume  ss:StackSG,cs:CodeSG,ds:DataSG
 
BEGIN:
mov ax, DataSG
mov ds, ax
mov si, offset array
mov cx, 5
xor bx, bx
mov bl, al
@1: 
     lodsb 
     cmp al, bh
     jg max
     cmp al, bl
     jl min
     jmp @@1
min: 
     mov bl, al
     jmp @@1
max:
    mov bh, al
@@1:
    loop @1
mov     ah,4ch
int 21h
CodeSG  Ends
END BEGIN



0



Есть задание. Необходимо найти значение максимального элемента в массиве. Элементы массива должны иметь тип WORD (2 байта). В первом элементе массива должно хранить количество элементов массива −1. То есть оттуда мы должны считать количество чисел, перейти на адрес второй ячейки массива, и начиная с числа по этому адресу уже сравнивать.

Написал следующий код:

section .text
   global _start 
    
_start: 
        
   mov  eax, 3    ; mov eax, [x]
   mov  ebx,0      ; EBX будет хранить максимальное значение
   mov  ecx, x    ; ECX будет указывать на текущий элемент для выполнения операции сравнения
   add ecx, 2 
 
top:  cmp ebx, [ecx]
   JNS l1
   mov ebx, [ecx]
   l1: add  ecx, 2      ; перемещаем указатель на следующий элемент
   dec  eax        ; выполняем декремент счётчика
   jnz  top        ; если счётчиком не является 0, то тогда выполняем цикл ещё раз
 
done: 
 
   add   ebx, '0'
   mov  [max], ebx ; готово, сохраняем результат в переменной sum
 
display:
 
   mov  edx, 2      ; длина сообщения
   mov  ecx, max   ; сообщение для написания
   mov  ebx, 1     ; файловый дескриптор (stdout)
   mov  eax, 4     ; номер системного вызова (sys_write)
   int  0x80       ; вызов ядра
    
   mov  eax, 1     ; номер системного вызова (sys_exit)
   int  0x80       ; вызов ядра
 
section .data
global x
x:
   dw  3
   dw  2
   dw  4
   dw  3
 
max: 
   dw  0

Компилирую в Linux через консоль, компиляция проходит, но результат выводит неправильный. Кроме того, ему не нравится синтаксис(segmentation fault)

mov eax, [x]

Если кто разбирается в ассемблере, помогите, пожалуйста. Где я ошибся?

Improve Article

Save Article

Like Article

  • Read
  • Discuss
  • Improve Article

    Save Article

    Like Article

    Problem – Determine largest number in an array of n elements. Value of n is stored at address 2050 and array starts from address 2051. Result is stored at address 3050. Starting address of program is taken as 2000. 

    Example: 

    Algorithm:

    1. We are taking first element of array in A
    2. Comparing A with other elements of array, if A is smaller then store that element in A otherwise compare with next element
    3. The value of A is the answer

    Program:

    Memory Address Mnemonics Comment
    2000 LXI H 2050 H←20, L←50
    2003 MOV C, M C←M
    2004 DCR C C←C-01
    2005 INX H HL←HL+0001
    2006 MOV A, M A←M
    2007 INX H HL←HL+0001
    2008 CMP M A-M
    2009 JNC 200D If Carry Flag=0, goto 200D
    200C MOV A, M A←M
    200D DCR C C←C-1
    200E JNZ 2007 If Zero Flag=0, goto 2007
    2011 STA 3050 A→3050
    2014 HLT  

    Explanation:

     Registers used: A, H, L, C

    1. LXI 2050 assigns 20 to H and 50 to L
    2. MOV C, M copies content of memory (specified by HL register pair) to C (this is used as a counter)
    3. DCR C decrements value of C by 1
    4. INX H increases value of HL by 1. This is done to visit next memory location
    5. MOV A, M copies content of memory (specified by HL register pair) to A
    6. INX H increases value of HL by 1. This is done to visit next memory location
    7. CMP M compares A and M by subtracting M from A. Carry flag and sign flag becomes set if A-M is negative
    8. JNC 200D jumps program counter to 200D if carry flag = 0
    9. MOV A, M copies content of memory (specified by HL register pair) to A
    10. DCR C decrements value of C by 1
    11. JNZ 2007 jumps program counter to 2007 if zero flag = 0
    12. STA 3050 stores value of A at 3050 memory location
    13. HLT stops executing the program and halts any further execution

    Advantages of finding the largest number in an array:

    1. It is a simple and straightforward task that can be easily implemented in any programming language.
       
    2. It is a common operation used in many algorithms and applications, such as finding the maximum value in a data set or determining the winner of a game.
       
    3. It is a fast operation that can be completed in O(n) time complexity, where n is the number of elements in the array.
       

    Disadvantages of finding the largest number in an array:

    1. If the array is unsorted, finding the largest number requires iterating through the entire array, which can be inefficient for very large arrays.
       
    2. If multiple elements in the array have the same maximum value, finding only one of them requires additional logic or iterations, which can add complexity to the algorithm.
       
    3. If the array is very large and memory is limited, storing the entire array in memory may not be feasible, which could require a more complex solution such as sorting the array in smaller parts.

    Last Updated :
    07 May, 2023

    Like Article

    Save Article

    У меня задание, где нужно ввести массив и вывести его на экран. Но теперь пеподу понадобилось, чтоб еще найти максимальный элемент и заменить его на 1 и вывести на экран массив с замененным элементом. Я ввод/вывод еле сделал (и то не без дорых людей). Я как найти и заменить вообще не знаю. С ума сойти...
    Все время с++ изучали, а тут вот и ассемблер теперь нужно.
    Помогите пожалуйста, если можете.

    MODEL SMALL            ;Малая модель памяти cs<>ds,cs<>ss
    STACK 100h            ;100h памяти под сегмент
    LOCALS @@            ;Метки с префиксом @@ счит. локальными
    mSize   equ 3            ;Размер матрицы

    ;—————————————————
    ; Сегмент данных
    ;—————————————————
    data   segment                       ;Начало сегмента данных
     matrix   db mSize*mSize dup(?)
     prompt2 db ‘Массив:’,’$’      ;DOS-строка ‘числа…’
     prompt3 db ‘Введите число:’,’$’   ;DOS-строка ‘введите…’
     endl    db 13,10,’$’         ;DOS-строка — перевод на след. строчку

     nbSize    db ?            ;Заголовок под буфер ввода
     nbInp    db ?
     buf    db 6 dup(?)         ;DOS-строка буфер для числа
        db ‘$’
    data   ends               ;Конец сегмента данных

    ;—————————————————
    ; Сегмент кода
    ;—————————————————
    code    segment            ;Начало сегмента
       assume cs:code,ds:data      ;Обещаем выставить cs=code,ds=data
     start:               ;Точка входа в программу
       mov   ax,data         ;ds=data (Инициализируем DS сегмент)
       mov   ds,ax

       mov   cx,mSize*mSize              ;cx=кол-ву эл-тов матрицы
       mov   si,OFFSET matrix      ;ds:si указывает на матрицу
       call   doEnterMatrix               ;Вызываем процедуру заполнения матрицы

       call   doClearScreen               ;Очищаем экран

           mov   si,OFFSET matrix      ;ds:si указывает на матрицу
       mov   cx,mSize*mSize               ;cx = кол-ву элементов в матрице

              ;Вызываем вывод перевода строки

       mov   si,OFFSET prompt2      ;ds:si указывает на prompt2
       call   doPrintStr         ;Печатаем на экране строку prompt2
       mov   cx,mSize*mSize              ;cx = кол-ву элементов в матрице
       mov   si,OFFSET matrix      ;ds:si теперь указывает на матрицу
       call   doOut                 ;Вызываем вывод матрицы
       mov   si,OFFSET endl               ;ds:si указывает на симв. перев. строки
       call   doPrintStr         ;Вызываем вывод перевода строки

       call   doWaitAKey         ;Ожидаем нажатие клавиши

       mov   ax,4C00h         ;Выходим из программы —
       int   21h            ; прерывание 21h(DOS),ф-я 4Ch

    ;—————————————————
    ; doEnterMatrix — процедура ввода
    ;—————————————————

     doEnterMatrix   proc near                       ;Начало описания процедуры
       push   es            ;Сохраняем es в стеке
       push   di            ;Сохраняем di в стеке
       push   si            ;Сохраняем si в стеке
       push   cx            ;Сохраняем cx в стеке
       push   ax            ;Сохраняем ax в стеке
       pushf               ;Сохраняем флаги в стеке

       mov   byte ptr ds:[nbSize],5   ;Макс. кол-во символов, кот.можно ввести

       mov   ax,ds            ;ax=ds
       mov   es,ax            ;es=ax=ds
       mov   di,si            ;si=di
       cld               ;Сбрасываем флаг направления (вперёд)
    @@lAgain:               ;Начало цикла
       call   doClearScreen               ;Вызываем очистку экрана
       mov   si,OFFSET prompt3      ;ds:si указывает на строку prompt3
       call   doPrintStr         ;Вызываем проц. вывода строки на экран

       mov   ah,0Ah                 ;ah=0Ah
       mov   dx,OFFSET nbSize      ;ds:dx указывает на буфер для ввода
       int   21h            ;Прерывание 21h(DOS) ввод строки
       push   cx            ;Сохраняем cx в стеке
       xor   ch,ch            ;ch=0 (быстрое обнуление)
       mov   cl,byte ptr ds:[nbInp]           ;cl=кол-ву введённых символов
       mov   si,OFFSET buf              ;ds:si указывает на буфер ввода
       call   doStr2Byte         ;Вызвать преобразование строки в число
       pop   cx            ;Восстановить cx из стека

           cld               ;Сбрасываем флаг направления(вперёд)
       stosb               ;Сохраняем полученное число в матрицу
       loop   @@lAgain         ;Конец цикла

       popf               ;Восстанавливаем флаги из стека
       pop   ax            ;Восстанавливаем ax из стека
       pop   cx            ;Восстанавливаем cx из стека
       pop   si            ;Восстанавливаем si из стека
       pop   di            ;Восстанавливаем di из стека
       pop   es            ;Восстанавливаем es из стека
       ret               ;Выходим из процедуры
     doEnterMatrix  endp                     ;Конец описания процедуры

    ;—————————————————
    ; doEnterMatrix — процедура вывода
    ;—————————————————
     doOut   proc near                       ;Начало описания процедуры
       push   si         ;Сохраняем si в стеке
       push   dx         ;Сохраняем dx в стеке
       push   cx         ;Сохраняем cx в стеке
       push   bx         ;Сохраняем bx в стеке
       push   ax         ;Сохраняем ax в стеке
       pushf            ;Сохраняем флаги в стеке

       xor   ah,ah         ;ah=0 (верхняя часть ax)
       cld            ;Сбрасываем флаг направления (вперёд)
      @@lNext:                              ;Начало цикла
       lodsb            ;al=следующему эл-ту матрицы

           mov   bx,si         ;Сохраняем si в bx (bx=si)
       mov   dx,cx         ;Сохраняем cx в dx (dx=cx)
       mov   cx,LENGTH buf           ;cx = размеру буфера
       mov   si,OFFSET buf           ;ds:si указывает на начало буфера
       call   doWord2Str      ;Вызываем преобразование числа в строку
       mov   cx,dx         ;Восстанавливаем cx из dx (cx=dx)
       mov   si,OFFSET buf           ;ds:si указывает на буфер (строку)
       call   doPrintStr      ;Выводим буфер (строку)(число)
       mov   si,bx         ;Восстанавливаем si из bx (si=bx)

      @@lSkip:            ;Метка @@lSkip
       loop   @@lNext      ;Конец цикла

       popf            ;Восстанавливаем из стека флаги
       pop   ax         ;Восстанавливаем из стека ax
       pop   bx         ;Восстанавливаем из стека bx
       pop   cx         ;Восстанавливаем из стека cx
       pop   dx         ;Восстанавливаем из стека dx
       pop   si         ;Восстанавливаем из стека si
       ret            ;Выходим из процедуры
     doOut   endp         ;Конец описания процедуры

    ;—————————————————
    ; doClearScreen — процедура очистки экрана
    ;—————————————————
       doClearScreen   proc near       ;Начало описания процедуры
       push   ax         ;Сохраняем ax в стеке
       pushf            ;Сохраняем флаги

       mov   ax,0003h      ;ah = 0, al = 03 (номер видео режима)
       int   10h         ;Прерыване 10h(BIOS) устан. вид.режима

       popf            ;Восстанавливаем из стека флаги
       pop   ax         ;Восстанавливаем из стека ax
       ret            ;Выходим из процедуры
        doClearScreen   endp      ;Конец описания процедуры

    ;—————————————————
    ; doWaitAKey — процедура ожидания клавиши
    ;—————————————————
     doWaitAKey   proc near               ;Начало описания процедуры
       push   ax         ;Сохраняем ax в стеке
       pushf            ;Сохраняем флаги в стеке

       xor   ah,ah         ;ah=0 (быстрое обнуление)
       int   16h         ;Прерывание 16h(BIOS) читаем клавишу

       popf            ;Восстанавливаем из стека флаги
       pop   ax                      ;Восстанавливаем из стека ax
     doWaitAKey   endp         ;Конец описания процедуры

    ;—————————————————
    ; doPrintStr — Вывод DOS строки на экран
    ;—————————————————
     doPrintStr   proc near               ;Начало описания процедуры
       push   dx         ;Сохраняем dx в стеке
       push   ax         ;Сохраняем ax в стеке
       pushf            ;Сохраняем флаги в стеке

       mov   ah,09h               ;ah = 09h
       mov   dx,si         ;dx = si
       int   21h         ;Прерывание 21h(DOS) выв. строки

       popf            ;Восстанавливаем из стека флаги
       pop   ax         ;Восстанавливаем из стека ax
       pop   dx         ;Восстанавливаем из стека dx
       ret            ;Выходим из процедуры
     doPrintStr   endp         ;Конец описания процедуры

    ;—————————————————
    ; doWord2Str — Перевод числа в строку
    ;—————————————————
     doWord2Str   proc near               ;Начало описания процедуры
       push   si         ;Сохраняем si в стеке
       push   dx         ;Сохраняем dx в стеке
       push   cx         ;Сохраняем cx в стеке
       push   bx         ;Сохраняем bx в стеке
       push   ax         ;Сохраняем ax в стеке
       pushf            ;Сохраняем в стеке флаги

       mov   dl,al         ;Сохраняем al в dl (dl=al)
       mov   al,’ ‘              ;al = пробелу
       call   doFillBuf      ;Заполняем буфер пробелами
       mov   al,dl         ;Восстанавливаем al (al=dl)

       test   ah,10000000b   ;ax<0? (первый бит установлен?)
       jz   @@skipNeg      ;Нет => @@skipNeg
       neg   ax         ;ax=-ax
       mov   byte ptr ds:[si],’-‘   ;Записываем в буфер симв. ‘-‘
    @@skipNeg:
       dec   cx         ;Уменьшаем cx (место под знак)
       add   si,cx         ;ds:si указывает на конец буфера
       mov   bx,10         ;bx=10 (будем делить на 10)
    @@lNext:                                ;Начало цикла
       xor   dx,dx         ;Обнуляем остаток от деления (dx=0)
       div   bx         ;Делим ax на bx (ax=ax/10, dx=остаток)
       add   dl,’0′         ;Прибавляем к dl символ ‘0’
       mov   byte ptr ds:[si],dl   ;Сохраняем в буфере
       test   ax,ax         ;ax = 0? (делить имеет смысл?)
       jz   @@lExit         ;нет => выход из цикла
       dec   si         ;Сдвигаемся по буферу
       loop   @@lNext         ;Следующий шаг

    @@lExit:
       popf            ;Восстанавливаем из стека флаги
       pop   ax         ;Восстанавливаем из стека ax
       pop   bx         ;Восстанавливаем из стека bx
       pop   cx         ;Восстанавливаем из стека cx
       pop   dx                      ;Восстанавливаем из стека dx
       pop   si         ;Восстанавливаем из стека si
       ret            ;Выходим из процедуры
     doWord2Str   endp         ;Конец описания процедуры

    ;—————————————————
    ; doStr2Byte — Перевод строки в байт
    ;—————————————————
     doStr2Byte   proc near               ;Начало описания процедуры
       push   si         ;Сохраняем si в стеке
       push   dx         ;Сохраняем dx в стеке
       push   cx         ;Сохраняем cx в стеке
       push   bx         ;Сохраняем bx в стеке

       mov   bx,cx         ;Сохраняем cx в bx
       cld            ;Сбрасываем флаг направления(вперёд)
       lodsb            ;Читаем первый символ
       cmp   al,’-‘              ;Сравниваем его с символом ‘-‘
       jne   @@lSkip              ;Если не равен => lSkip
       dec   cx         ;Иначе уменьшаем счётчик символов
       dec   bx         ;И сохранённый тоже
    @@lNext:            ;Начало цикла (проверка строки)
       lodsb            ;Загружаем следующий символ в al
    @@lSkip:
       cmp   al,’0′              ;Сравниваем его с ‘0’
       jb   @@lExitE      ;Если меньше,то выходим из цикла(ошибка)
       cmp   al,’9′               ;Сравниваем его с ‘9’
       ja   @@lExitE      ;Если больше,то выходим из цикла(ошибка)
       loop   @@lNext              ;Конец цикла

           dec   si         ;Передвигаем si на последний символ
       mov   cx,bx         ;Восстанавливаем cx из bx
       std            ;Устанавливаем флаг переноса (назад)
       mov   dx,0A01h      ;dh=10, dl=1 (коэфф.умножения, множит.)
       xor   bx,bx         ;bx=0 (сумма — быстрое обнуление)
    @@lNextD:            ;Начало цикла
       lodsb            ;Считываем предыдущий символ
       sub   al,’0′              ;Преобразуем символ в число
       mul   dl         ;Умножаем его на dl (1,10,100…)
       test   ah,ah         ;Проверяем вышел ли он за пределы байта
       jnz   @@lExitE      ;Если вышел — выходим из цикла (ошибка)
       add   bx,ax         ;bx=bx+ax (суммируем)
       mov   al,dl         ;al=dl (готовимся к умножению множителя=)
       mul   dh         ;умножаем
       mov   dl,al         ;dl=множителю (1,10,100…)
       loop   @@lNextD      ;Конец цикла

           lodsb            ;Дочитываем символ
       cmp   al,’-‘              ;Сравниваем его с ‘-‘
       jne   @@lSkipN      ;Если нет =>lSkipN
       neg   bx         ;Иначе bx=-bx
    @@lSkipN:
       mov   ax,bx         ;ax=bx=числу
       clc            ;Сбрасываем флаг переноса (нет ошибки)
       jmp   @@lExit              ;Выходим

    @@lExitE:
       stc            ;Устанавливаем флаг переноса(ошибка)
    @@lExit:
       pop   bx         ;Восстанавливаем из стека bx
       pop   cx         ;Восстанавливаем из стека cx
       pop   dx                      ;Восстанавливаем из стека dx
       pop   si         ;Восстанавливаем из стека si
       ret            ;Выходим из процедуры
     doStr2Byte endp         ;Конец описания процедуры

    ;—————————————————
    ; doFillBuf — Заполняет буфер заданным значением
    ;—————————————————
     doFillBuf   proc near               ;Начало описания процедуры
       push   es         ;Сохраняем es в стеке
       push   di         ;Сохраняем di в стеке
       push   cx         ;Сохраняем сx в стеке
       push   bx         ;Сохраняем bx в стеке

           mov   bx,ds         ;bx = ds
       mov   es,bx         ;es = bx = ds
       mov   di,si         ;di = si
       cld            ;Сбрасываем флаг направления (вперёд)
       rep   stosb         ;Пишем сод. ax, cx раз в строку es:di

       pop   bx         ;Восстанавливаем из стека bx
       pop   cx         ;Восстанавливаем из стека cx
       pop   di         ;Восстанавливаем из стека di
       pop   es         ;Восстанавливаем из стека es
       ret            ;Выходим из процедуры
     doFillBuf   endp              ;Конец описания процедуры

    code   ends                            ;Конец сегмента кода
    end   start                       ;Конец программы

    cseg segment
    assume cs:cseg,ds:cseg,es:cseg,ss:cseg
    org 100h
     
    start:  mov di,offset array;адрес массива
        mov cx,l_arr    ;число элементов массива
        dec cx      ;число сравнений на 1 меньше
        push cx     ;сохраним его
        mov bx,[di] ;примем за минимум 1 элемент
        mov ax,bx   ;и за максимум тоже 
        add di,2    ;di -> 2 элемент
        push di
    chkmin: cmp [di],bx ;след. элемент меньше минимального ?
        jge nomin   ;нет, проверяем дальше
        mov bx,[di] ;да, поместим его в bx
    nomin:  add di,2    ;di -> след. элемент
        loop chkmin ;повторить cx раз
        pop di      ;di -> 2 элемент
        pop cx      ;восстановим счетчик
    chkmax: cmp [di],ax ;след. элемент больше максимального ?
        jle nomax   ;нет, проверяем дальше
        mov ax,[di] ;да, отправим его в ax
    nomax:  add di,2    ;di -> след. элемент
        loop chkmax ;повторить cx раз
        ret
     
    array   dw 2456,321,-12,876,55,14,8,625,-324,156
    l_arr=($-array)/2
     
    cseg ends
    end start

    Понравилась статья? Поделить с друзьями:
  • Как найти корень в квадрате 121
  • Как найти объем сферы через радиус
  • Как найти контакт на телефоне андроид удаленный
  • Как найти художников по картинке
  • Как найти зайца в феврале