Вывод последовательности чисел в обратном порядке - Assembler

Узнай цену своей работы

Формулировка задачи:

Приветствую всех форумчан! Работая над контрольной работой зашел в тупик, поэтому прошу помощи. Задание следующее - ввести с клавы последовательность трехзначных dec чисел разделенных пробелом, программа должна вывести ее на экран в обратном порядке в hex числах. Внизу приведу код, который смог составить.
[org 100h]
jmp  start
 
mess0   db  13,10,' ВВЕДИТЕ ЧИСЛА В ДЕСЯТИЧНОЙ СИСТЕМЕ (ENTER-ЗАКОНЧИТЬ) $'  
mess1   db  13,10,' В ШЕСТНАДЦАТЕРИЧНОЙ СИСТЕМЕ В ОБРАТНОМ ПОРЯДКЕ   $' 
start:
 mov   dx,mess0 ; печать текста 'ВВЕДИТЕ ... (ENTER-ЗАКОНЧИТЬ)'
   call  MESSAGE
   xor   bp,bp
 
vvod:
   call  ASC2HEX  ; вызов процедуры, преобразующей ascII код в hex числа
   push  cx       ; в стеке первые 3 числа hex
   inc   bp       ; счетчик стека увеличивается на единицу  
   mov   ah,8     ; ввод ,БЕЗ ЭХА средствами DOS
   int   21h      ;
   cmp   al,13    ; это 'enter'?
   jne   vvod     ; если нет, вводим следующее число
      
   mov   dx,mess1 ; печать текста 'В ШЕСТНАДЦАТЕРИЧНОЙ СИСТЕМЕ В ОБРАТНОМ ПОРЯДКЕ'
   call  MESSAGE
   
vivod:   
   pop   ax       ; вытащили из стека последние 3 числа
   mov   bx,10
   v.1:           ; переворот числа в ах задом наперед
     div   bx     ; делим ax на 10, в остатке в dx сохраняется последняя цифра
     shl   dx,4   ; сдвигаем эту цифру влево на один полубайт
     or   ax,ax   ; проверяем, в ах после деления что-нибудь осталось?
     jnz   v.1    ; если да, цикл повторяется снова
   mov   ax,dx    ; в итоге в dx должно накопится число, обратное ax по порядку 
   dec   bp       ; счетчик стека уменьшился на единицу
   mov   bx,16    ; BX=16
   call  HEX2ASC  ; вызов процедуры преобразования hex в ascII код и их печать
   or    bp,bp    ; счетчик стеков равен нулю?
   jnz   vivod    ; если нет, вытаскиваем предпоследние 3 числа
 
 exit:
   xor   ax, ax
   int   16h
   int   20h
 
;============== ВЫВОД НА ЭКРАН СРЕДСТВАМИ DOS ================================|
MESSAGE:
   mov   ah,9 ; строки
   int   21h
ret
;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
;============== ПРОЦЕДУРА СОХРАНЕНИЯ ВВОДА В HEX-ФОРМАТЕ =====================|
ASC2HEX:
   XOR    CX,CX
@0:                       ;
   MOV   AH,8             ; ввод ,БЕЗ ЭХА средствами DOS
   INT   21h              ;
   CMP   AL,20h           ; это пробел - выход из цикла
   JE    stop             ;
   MOV   DL,AL            ; скидываем введенное число в DL
   CMP   AL,30h           ; введенное число asc2
   JB    @0               ; меньше 30? значит в начало
   CMP   AL,39h           ; может больше 39? да - направляем в начало
   JA    @0               ; 
   SUB   AL,30h           ; меньше/равно 39, вычитаем 30h
@2:                       ;
   SHL    CX,4            ; сдвигаем мл.полубайт (CL), в старший
   OR     CL,AL           ; в мл.полубайте (CL) запишем наше число                         
 
@1:
   MOV   AH,2             ; печать средствами DOS
   INT   21h
   JMP    @0              ; читаем следующий символ..
 
stop:                      ; Если нажал ENTER, то результат у нас в CX.
RET                        ;
;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
;============== ФУНКЦИЯ ВЫВОДИТ НА ЭКРАН В РАЗЛИЧНЫХ СС =======================|
HEX2ASC:                   ;
   XOR   CX,CX             ; На входе: BX = система счисления, AX = число
isDiv:                     ;
   XOR   DX,DX             ; очистим место под остаток
   DIV   BX                ; разделим AX на фактор системы счисления
   PUSH  DX                ; сохраняем остаток от деления
   INC   CX                ; увеличим счётчик разрядности цифры
   OR    AX,AX             ; это последняя цифра?!
   JNZ   isDiv             ; нет - читаем следующую..
isOut:                     ; <-- в СХ у нас кол-во пуш'ей (для LOOP)
   POP   AX                ; снимаем со-стека остаток в обратном порядке
   CMP   AL,9              ; проверка на десятичную цифру
   JLE   noHex             ; меньше/равно? значит не HEX-цифра
   ADD   AL,7              ; иначе: коррекция для HEX
noHex:                     ;
   ADD   AL,30h            ; переводим цифру в символ
   INT   29h               ; выводим её на экран
   LOOP  isOut             ; мотаем цикл CX-раз..
RET                        ;
    ;
Код дает ошибки при вводе, затем переполнение при делении. В связи с этим подскажите, пожалуйста, 1. При вводе чисел пробелы не печатаются, пытался исправить, не вышло. 2. После ввода третьего числа и нажатия пробела ввожу следующие 3 числа, печатает только 2 из них, почему, не знаю. 3. С переполнением пытался бороться предварительным обнулением dx, безрезультатно. За любой ответ буду крайне признателен, так как хочется все же разобраться да и без кода сессии мне не видать.

Решение задачи: «Вывод последовательности чисел в обратном порядке»

textual
Листинг программы
org 100h
jmp  start
 
mess0   db  13,10,' ВВЕДИТЕ ЧИСЛА В ДЕСЯТИЧНОЙ СИСТЕМЕ (ENTER-ЗАКОНЧИТЬ) $'  
mess1   db  13,10,' В ШЕСТНАДЦАТЕРИЧНОЙ СИСТЕМЕ В ОБРАТНОМ ПОРЯДКЕ   $' 
start:
 mov   dx,mess0 ; печать текста 'ВВЕДИТЕ ... (ENTER-ЗАКОНЧИТЬ)'
   call  MESSAGE
   xor   bp,bp
   mov   bx,10
vvod:
   call  ASC2HEX  ; вызов процедуры, преобразующей ascII код в hex числа
   push  cx   ; в стеке первые 3 числа hex
   inc   bp   ; счетчик стека увеличивается на единицу
   cmp   al,13    ; это 'enter'?
   jne   vvod     ; если нет, вводим следующее число
 
   mov   dx,mess1 ; печать текста 'В ШЕСТНАДЦАТЕРИЧНОЙ СИСТЕМЕ В ОБРАТНОМ ПОРЯДКЕ'
   call  MESSAGE
   mov   bx,16
vivod:   
   pop   ax   ; вытащили из стека последние 3 числа
   call  HEX2ASC  ; вызов процедуры преобразования hex в ascII код и их печать
   dec    bp;,bp    ; счетчик стеков равен нулю?
   jnz   vivod    ; если нет, вытаскиваем предпоследние 3 числа
 
 exit:
   xor   ax, ax
   int   16h
   int   20h
 
;============== ВЫВОД НА ЭКРАН СРЕДСТВАМИ DOS ================================|
MESSAGE:
   mov   ah,9 ; строки
   int   21h
ret
;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
;============== ПРОЦЕДУРА СОХРАНЕНИЯ ВВОДА В HEX-ФОРМАТЕ =====================|
ASC2HEX:
   XOR    CX,CX
@0:       ;
   MOV   AH,8         ; ввод ,БЕЗ ЭХА средствами DOS
   INT   21h          ;
   cmp   al,13
   jz    stop
   mov   dl,al
   CMP   AL,20h       ; это пробел - выход из цикла
   JE    @1
   CMP   AL,30h       ; введенное число asc2
   JB    @0   ; меньше 30? значит в начало
   CMP   AL,39h       ; может больше 39? да - направляем в начало
   JA    @0
   push  dx
   and   ax,0fh
   xchg  cx,ax
   xor   dx,dx
   mul   bx
   add   cx,ax
   pop   dx
@1:
   MOV   AH,2         ; печать средствами DOS
   INT   21h
   cmp   dl,' '        ; читаем следующий символ..
   jnz   @0
 
stop:          ; Если нажал ENTER, то результат у нас в CX.
RET        ;
;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
;============== ФУНКЦИЯ ВЫВОДИТ НА ЭКРАН В РАЗЛИЧНЫХ СС =======================|
HEX2ASC:       ;
   XOR   CX,CX         ; На входе: BX = система счисления, AX = число
isDiv:         ;
   XOR   DX,DX         ; очистим место под остаток
   DIV   BX    ; разделим AX на фактор системы счисления
   PUSH  DX    ; сохраняем остаток от деления
   INC   CX    ; увеличим счётчик разрядности цифры
   OR    AX,AX         ; это последняя цифра?!
   JNZ   isDiv         ; нет - читаем следующую..
isOut:         ; <-- в СХ у нас кол-во пуш'ей (для LOOP)
   POP   AX    ; снимаем со-стека остаток в обратном порядке
   CMP   AL,9          ; проверка на десятичную цифру
   JLE   noHex         ; меньше/равно? значит не HEX-цифра
   ADD   AL,7          ; иначе: коррекция для HEX
noHex:         ;
   ADD   AL,30h        ; переводим цифру в символ
   INT   29h           ; выводим её на экран
   LOOP  isOut         ; мотаем цикл CX-раз..
   mov   al,' '
   int  29h
RET        ;

Оцени полезность:

15   голосов , оценка 4.133 из 5
Похожие ответы