Ассемблер. Знаковые числа

Софт только для использования в DOS

Ассемблер. Знаковые числа

Сообщение R71MT » 22 дек 2015, 03:29

Привет всем! Помогите со-знаковыми числами. Нужно найти наибольший элемент массива... Заранее спасибо...
Последний раз редактировалось R71MT 30 сен 2023, 23:41, всего редактировалось 2 раз(а).
R71MT
Даунгрейдер
 
Сообщения: 7
Зарегистрирован: 22 дек 2015, 03:23

Re: Ассемблер. Знаковые числа

Сообщение Nika » 22 дек 2015, 12:45

Полагаю, что делать чужие домашние задания тут никто не будет.
А пример знакового и беззнакового сравнения - это пожалуйста:
Код: Выделить всё
model tiny
.code
org 100h
begin:  jmp start

val_1   dw  -10h
val_2   dw   10h

str_1_above   db 0dh,0ah,'val_1 > val_2. (BEZznakovoe sravnenie)','$'
str_1_below   db 0dh,0ah,'val_1 < val_2. (BEZznakovoe sravnenie)','$'

str_1_less    db 0dh,0ah,'val_1 < val_2. (Znakovoe sravnenie)'   ,'$'
str_1_greater db 0dh,0ah,'val_1 > val_2. (Znakovoe sravnenie)'   ,'$'


start:
        ;;compare unsigned
        ;;
        mov ax, val_1   
        mov bx, val_2
        cmp ax, bx
        lea dx, str_1_below
        jb  @@msg1
        lea dx, str_1_above
@@msg1:
        mov ah,9
        int 21h

        ;;compare signed
        ;;
        mov ax, val_1   
        mov bx, val_2
        cmp ax, bx
        lea dx, str_1_less
        jl  @@msg2
        lea dx, str_1_greater
@@msg2:
        mov ah,9
        int 21h

        ret
end     begin
Файл .LST:
Код: Выделить всё
     
      6 0102  FFF0                   val_1   dw -10h     ;;<------ val_1 = 0FFF0h  = -10h
      7 0104  0010                   val_2   dw  10h     ;;<------ val_2 = 00010h


Результат работы программы:
Код: Выделить всё
val_1 > val_2. (BEZznakovoe sravnenie)
val_1 < val_2. (Znakovoe sravnenie)
Последний раз редактировалось Nika 30 сен 2023, 23:41, всего редактировалось 6 раз(а).
Nika
Мастер Даунгрейда
 
Сообщения: 852
Зарегистрирован: 16 окт 2013, 23:21

Re: Ассемблер. Знаковые числа

Сообщение R71MT » 24 дек 2015, 04:26

Nika писал(а):А пример знакового и беззнакового сравнения - это пожалуйста:
Код: Выделить всё
val_1   dw  -10h
val_2   dw   10h


Nika, спасибо большое за пример! А как создать массив чисел с вводом с клавиатуры? У Вас числа уже в переменных... По условию задания, знаковые числа вводятся с клавиатуры и идут вперемешку. Мне нужно найти в массиве все отрицательные, и среди отрицательных - наибольшее. Кстати, чё больше -1 или -2 - не уверен. По школьному курсу вроде -1 ?!

Я массив создаю функцией 0Ah досовского сервиса, а как мне теперь найти в буфере отрицательные? Был-бы премного благодарен..
Последний раз редактировалось R71MT 30 сен 2023, 23:41, всего редактировалось 1 раз.
R71MT
Даунгрейдер
 
Сообщения: 7
Зарегистрирован: 22 дек 2015, 03:23

Re: Ассемблер. Знаковые числа

Сообщение Nika » 24 дек 2015, 09:37

R71MT писал(а): Кстати, чё больше -1 или -2 - не уверен. По школьному курсу вроде -1 ?!
Что тольку гадать?
Подставляйте эти числа в пример, который выше - та программа сравнит и выдаст верный ответ.

Что касается "задания", то оно гораздо более объёмное, чем просто сравнение двух чисел.
После ввода с клавиатуры чисел-строк их нужно ещё сконвертировать в двоичное представление, и только после этого сравнивать или искать наибольшее/наименьшее.
Последний раз редактировалось Nika 30 сен 2023, 23:41, всего редактировалось 1 раз.
Nika
Мастер Даунгрейда
 
Сообщения: 852
Зарегистрирован: 16 окт 2013, 23:21

Re: Ассемблер. Знаковые числа

Сообщение R71MT » 25 дек 2015, 04:42

Вот что у меня получилось.. Коряво правда, но работает. Код FASM:

Код: Выделить всё
USE16                      ; 16-битный код
ORG 100h                   ; место под PSP
JMP start                  ; прыжок на точку входа

mess0  DB  13,10,' FIND MAX NEGATIVE DIGIT (R)'
       DB  13,10,' Example: 1 205 -909 37 -13 -32000 25'
       DB  13,10,' ----------------------------------------------------'
       DB  13,10,' Input digital array ..: $'
mess1  DB  13,10,' Max negative digit ...: -$'
mess2  DB  7,'<--- INPUT ERROR!!!$'
max    DW  0               ; буфер отрицательного числа (для сравнения)

start:
   MOV   AH,9
   MOV   DX,mess0          ; запрос на ввод чисел..
   INT   21h

   XOR   CX,CX             ; счётчик отриц.элементов сбрасываем в нуль
inArray:                   ; заполняем массив..
   MOV   AH,1              ; ввод с эхо средствами DOS
   INT   21h
   CMP   AL,13             ; это ENTER ?!
   JE    findMax           ; если да - начинаем поиск максимального
   CMP   AL,'-'            ; это знак минус ?!
   JE    negative          ; да - сохраняем введённое число в стеке
   JMP   inArray           ; читаем следующий символ..

negative:                  ; попался знак минус..
   CALL  SaveNEG           ; переводим символы юзера в число (fn возвращает в DI)
   CMP   DI,32767          ; макс.знаковое слово = 32767 dec
   JA    error             ; юзер ввёл не больше этого числа ?! Да - ошибка!
   NEG   DI                ; сделаем из числа - отрицательное.
   PUSH  DI                ; сохраним его в стеке..
   INC   CX                ; ^^.. и увеличим счётчик отриц.чисел (для LOOP)
   JMP   inArray           ; читаем следующий символ..

error:                     ; если юзверь ввёл число больше чем 32767..
   MOV   AH,9              ; покажем сообщение об ошибке
   MOV   DX,mess2
   INT   21h
   JMP   exit              ; выходим из программы!

findMax:                   ; юзер нажал ENTER. Начинаем поиск наибольшего.
   MOV   AH,9              ; покажем мессагу
   MOV   DX,mess1
   INT   21h
@1:                        ; в СХ у нас кол-во PUSHей (отриц.чисел)
   POP   AX                ; снимаем со-стека число..
   CMP   AX,[max]          ; ^^.. и сравниваем его с переменной
   JGE   next              ; если больше/равно - пропускаем число
   MOV   [max],AX          ; значит меньше. Записываем его в переменную
next:
   LOOP  @1                ; мотаем цикл CX-раз

   MOV   AX,[max]          ; все числа сравнили! Возьмём наименьшее в АХ
   NEG   AX                ; команда NEG сделает из него наибольшее..
   MOV   BX,10             ; выводить на экран будем в 10-тичной СС
   CALL  HEX2ASC           ; покажем число!

exit:
   XOR   AX,AX             ; ждём клавишу и на выход
   INT   16h
   INT   20h

;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
;//==========; Процедура переводит число в символы и выводит их на экран ==========|
;//==========; на входе принимает: АХ = число, BX = система счисления =============|
HEX2ASC:
   PUSHA                   ; сохраняем все регистры
   XOR   CX,CX             ; флаг разрядности числа
isDiv:
   XOR   DX,DX             ; очищаем место под остаток
   DIV   BX                ; разделить AX на ВХ
   PUSH  DX                ; сохраняем остаток в стеке
   INC   CX                ; увеличиваем разрядность числа
   OR    AX,AX             ; это последний разряд?!
   JNZ   isDiv             ; нет - следуюший разряд..
isOut:
   POP   AX                ; снимаем цифры со-стека в обратном порядке
   CMP   AL,9              ; проверка на 9..
   JLE   noHex             ; ниже?! не трогаем её
   ADD   AL,7              ; коррекция для HEX "A..F"
noHex:
   ADD   AL,30h            ; переводим цифру в символ
   INT   29h               ; выводим её на экран
   LOOP  isOut             ; мотаем цикл CX-раз
   POPA                    ; восстанавливаем все регистры
RET

;//==========; Процедура переводит символы в цифры =================================|
;//==========; CC указывается в рег.BX/.. На выходе: DI = число ====================|
SaveNEG:
   XOR   DI,DI             ; в регистре DI будет число
NextNumber:
   MOV   AH,1              ; ввод с эхо средствами DOS
   INT   21h
   CMP   AL,13             ; это ENTER?
   JE    EnterStop         ; да - выходим!
   CMP   AL,' '            ; это пробел?!
   JE    EnterStop         ; да - выходим!
   AND   AX,0Fh            ; переводим символ в цифру
   XCHG  AX,DI             ; меняем последнее и ранее/введёное число
   MOV   BX,10             ; множитель (СС, в которой надо сохранить цифру)
   XOR   DX,DX             ; взводим флаги нуля и чётности
   MUL   BX                ; умножаем AX на BX. Результат в АХ
   ADD   DI,AX             ; прибавляем его к DI. Теперь в DI введёное число
   JMP   NextNumber        ; следующий символ..
EnterStop:
RET
Последний раз редактировалось R71MT 30 сен 2023, 23:41, всего редактировалось 4 раз(а).
R71MT
Даунгрейдер
 
Сообщения: 7
Зарегистрирован: 22 дек 2015, 03:23

Re: Ассемблер. Знаковые числа

Сообщение Nika » 25 дек 2015, 12:19

сравнение, в принципе, верное - JG/JL.
Только вот результаты странные:

error.png
error.png (2.09 Кб) Просмотров: 19744

Это всё не годится. Нужно получить массив строк, потом из него получить массив двоичных чисел, и уже с ним и работать.
Смысл задания, как я понял, в этом и состоит - научиться работать с массивами данных.
Последний раз редактировалось Nika 30 сен 2023, 23:41, всего редактировалось 4 раз(а).
Nika
Мастер Даунгрейда
 
Сообщения: 852
Зарегистрирован: 16 окт 2013, 23:21

Re: Ассемблер. Знаковые числа

Сообщение R71MT » 27 дек 2015, 22:29

Nika писал(а):Нужно получить массив строк, потом из него получить массив двоичных чисел

непонятно с маркером конца числа. К примеру, юзер может ввести как 1 так и и -26785, как фильтровать ввод?
Последний раз редактировалось R71MT 30 сен 2023, 23:41, всего редактировалось 1 раз.
R71MT
Даунгрейдер
 
Сообщения: 7
Зарегистрирован: 22 дек 2015, 03:23

Re: Ассемблер. Знаковые числа

Сообщение Nika » 28 дек 2015, 00:08

Первый же введённый нецифровой символ - это и есть такой маркер.

Вообще, я стараюсь никогда не напрягать пользователей вводом чисел с клавиатуры.
Есть строка аргументов командной строки, и там данные можно указывать автоматически при запуске из бат-файла .
А можно и отруки, опять же в командной строке. Так удобнее.

Ну, а там получили эту строку - и выполняем её разбор, есть разные способы, дело вкуса.
Последний раз редактировалось Nika 30 сен 2023, 23:41, всего редактировалось 3 раз(а).
Nika
Мастер Даунгрейда
 
Сообщения: 852
Зарегистрирован: 16 окт 2013, 23:21

Re: Ассемблер. Знаковые числа

Сообщение R71MT » 28 дек 2015, 06:01

..вот гемор...Ввести/вывести не прабла, а вот отфильтровать ввод в буфере - эта проблема.
Если сохранять ввод функцией 0Ah, то потом в буфере не разберёшся... Как быть? Маркер конца разрядности числа пусть будет пробел(20h). И скать его SCASB'ом ?
Последний раз редактировалось R71MT 30 сен 2023, 23:41, всего редактировалось 1 раз.
R71MT
Даунгрейдер
 
Сообщения: 7
Зарегистрирован: 22 дек 2015, 03:23

Re: Ассемблер. Знаковые числа

Сообщение R71MT » 28 дек 2015, 06:04

...Новый Год подкрадывается, причём здесь PSP я сам не понял....
..если создать буфкр к функциии 0Ah, то как отделять цифры?!
Последний раз редактировалось R71MT 30 сен 2023, 23:41, всего редактировалось 2 раз(а).
R71MT
Даунгрейдер
 
Сообщения: 7
Зарегистрирован: 22 дек 2015, 03:23

Re: Ассемблер. Знаковые числа

Сообщение Nika » 28 дек 2015, 09:24

Много вопросов, на которые ответы будут слишком долгими.
Самый простой вариант - найти уже работающую программу и посмотреть, как там организован разбор строки.
Последний раз редактировалось Nika 30 сен 2023, 23:41, всего редактировалось 1 раз.
Nika
Мастер Даунгрейда
 
Сообщения: 852
Зарегистрирован: 16 окт 2013, 23:21

Re: Ассемблер. Знаковые числа

Сообщение R71MT » 29 дек 2015, 04:03

Пока написал такую процедуру. Возвращает в DI:

Код: Выделить всё
ASC2HEX:
   XOR    CX,CX                   ; копить число будем в CX
@0:
   MOV    AH,1                    ; ввод с эхом средствами DOS
   INT    21h
   CMP    AL,13                   ; это ENTER ?!
   JE     stop                    ; да - выходим из цикла ввода
   SUB    AL,30h                  ; нет - переводим символ в цифру
   CMP    AL,9                    ; это цифра 9 ?!
   JBE    @2                      ; если ниже/равно, то не трогаем её
   SUB    AL,11h                  ; значит HEX-буква. Отнимаем от неё фактор
   CMP    AL,5                    ; если заглавная буква, то остаток будет
   JBE    @1                      ; ^^ ..в пределах(5). Ниже/равно - коррекция!
   SUB    AL,20h                  ; значит прописная буква. Коррекция..
@1:
   ADD    AL,10                   ; коррекция букв "A..F", в "11..15"
@2:
   SHL    CX,4                    ; сдвигаем мл.тетраду(CL), в старшую
   OR     CL,AL                   ; в мл.тетраду(CL) запишем наше число
   JMP    @0                      ; читаем следующий символ..
stop:                             ; юзверь нажал ENTER! Результат у нас в CX.
RET
Последний раз редактировалось R71MT 30 сен 2023, 23:41, всего редактировалось 1 раз.
R71MT
Даунгрейдер
 
Сообщения: 7
Зарегистрирован: 22 дек 2015, 03:23

Re: Ассемблер. Знаковые числа

Сообщение Nika » 29 дек 2015, 15:05

Ну, можно и так.
Последний раз редактировалось Nika 30 сен 2023, 23:41, всего редактировалось 1 раз.
Nika
Мастер Даунгрейда
 
Сообщения: 852
Зарегистрирован: 16 окт 2013, 23:21


Вернуться в Программы для DOS

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7