Вывод последовательности чисел в обратном порядке - 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 ;