Вывод последовательности чисел в обратном порядке - Assembler
Формулировка задачи:
Приветствую всех форумчан! Работая над контрольной работой зашел в тупик, поэтому прошу помощи.
Задание следующее - ввести с клавы последовательность трехзначных dec чисел разделенных пробелом, программа должна вывести ее на экран в обратном порядке в hex числах.
Внизу приведу код, который смог составить.
Код дает ошибки при вводе, затем переполнение при делении. В связи с этим подскажите, пожалуйста,
1. При вводе чисел пробелы не печатаются, пытался исправить, не вышло.
2. После ввода третьего числа и нажатия пробела ввожу следующие 3 числа, печатает только 2 из них, почему, не знаю.
3. С переполнением пытался бороться предварительным обнулением dx, безрезультатно.
За любой ответ буду крайне признателен, так как хочется все же разобраться да и без кода сессии мне не видать.
Листинг программы
- [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 ;
- ;
Решение задачи: «Вывод последовательности чисел в обратном порядке»
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 ;
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д