Консультация № 171072
05.08.2009, 11:21
0.00 руб.
0 7 2
Добрый день Уважаемые эксперты. Помогите разобраться с задачей. "Ввод одной десятичной цифры и вывод соответствующей ей двоичного значения. Я не понимаю как здесь лучше поступить. Переводить с помощью того что вычислять остаток от деления на двойку и т. д. или же с помощью оператора сравнения - если al = 1 тогда там bx = 0001 ну и т д. Это первое. Еще в моей программе я попытался организовать ввод десятичного значения. Не пойму по каким причинам после компиляции она выполняет не те действия. Вместо int 21 - int 15 и дальше пошло поехало- не то в общем. Заранее спасибо.


Приложение:
title work
text segment para public 'code'
assume cs:text
vvod proc
mov ah,01
int 21
int 20
mov bx,0130
sub ax,bx
mov cx,ax
vvod endp
text ends
end vvod

Обсуждение

Неизвестный
05.08.2009, 11:29
общий
С неправильным значением прерываний понял - нужно было просто добавить после их значений h.
давно
Старший Модератор
31795
6196
05.08.2009, 12:10
общий
это ответ
Здравствуйте, Dimon4ik.

Начнем со второй части вопроса.
int 21
int 20

Компилятор считает если возле числа нет символа h[sub](16)[/sub],d[sub](10)[/sub],b[sub](2)[/sub](непосредственное указание типа числа) то это число десятичное, преобразовывает его в 16-ю систему и подставляет в код. Ваша ошибка - забыли добавить символ h, т.е. указать тип числа.
Должно быть так:
int 21h
int 20h


Вывод двоичного числа можно организовать с помощью более быстрых команд сдвига, т.к. использовать медленную команду деления нет смысла.
Пример в приложении.
Удачи!

Приложение:
model tiny
.code
.186
org 100h
begin:
;выводим сообщение
mov ah,9
mov dx,offset dbEnter
int 21h
;ждем нажатия клавиши
isInput: xor ax,ax
int 16h
;проверяем цифра ли это
cmp al,'0'
jl isInput
cmp al,'9'
ja isInput
;выводим символ нажатой клавиши
int 29h
;преобразовываем в число
and ax,0fh
push ax
;выводим знак разделитель
mov al,'='
int 29h
;задаем параметры для цикла вывода
mov cx,8
pop dx
;сдвигаем регистр, старший бит идет в CF
isOut: shl dl,1
mov al,30h
;суммируем с учетом флага переноса
adc al,0
;выводим
int 29h
loop isOut
;ждем любую клавишу
xor ax,ax
int 16h
;выход в дос
ret
dbEnter db 10,13,'Enter number:$'
end begin
5
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
7438
7205
05.08.2009, 12:15
общий
это ответ
Здравствуйте, Dimon4ik.
Например, так, как в приложении.
1) достаточно вывести 4 младших битов
2) выводим, начиная со старшего
3) очередной бит получаем сдвигом влево, при этом очередной бит будет в бите СF
4) превращаем бит в цифру сложением символа '0' с битом СF
Удачи!

Приложение:
title work
text segment para public 'code'
assume cs:text
vvod proc

mov ah,01
int 21h
cmp al,'0' ;проверим на цифру
jb vvod ;если не цифра, то на повтор
cmp al,'9'
ja vvod
sub al,30h ;сделаем из цифры '0'-'9' число 0-9
shl al,1 ;будем выводить только 4 младших бита,
shl al,1 ; начиная со старшего, для этого сдвинем влево на 4 бита,
shl al,1 ; чтобы начальный четвертый бит стал восьмым
shl al,1
mov bx, ax ;сохраним

mov ah,2 ;выведем знак '='
mov dl,'='
int 21h

mov cx,4 ;выводим 4 бита

bin_loop: ;цикл по битах
shl bl,1 ;сдвинем влево на 1 бит, старший бит уйдет в бит СF!
mov dl,'0' ;"база" для цифры (превращаем бит 0-1 в цифру '0'-'1')
adc dl,0 ;добавляем к '0' бит СF
mov ah,2 ;выводим
int 21h
loop bin_loop ;на повтор

mov ah,8 ;чтобы окно сразу не пропало, ждем нажатие на клавишу
int 21h ;(ввод кода без вывода на экран)
int 20h
vvod endp
text ends
end vvod
5
Спасибо за подробное обьяснение
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
05.08.2009, 13:19
общий
Лысков Игорь Витальевич:
можете более подробнее рассказать как работает вот этот вот момент? Я в математике и ассемблере не очень.. Сам понять не смог...
bin_loop: ;цикл по битах
shl bl,1 ;сдвинем влево на 1 бит, старший бит уйдет в бит С!
mov dl,'0' ;"база" для цифры (превращаем бит 0-1 в цифру '0'-'1')
adc dl,0 ;добавляем к '0' бит С
mov ah,2 ;выводим
int 21h
loop bin_loop ;на повтор
давно
Посетитель
7438
7205
05.08.2009, 13:25
общий
Пусть на входе у нас была цифра (символ!) '3', тогда перед циклом bin_loop регистр bl = 0011000b (b-биты) Это понятно?
Далее команда shl bl,1 сдвинет содержимое регистра влево на один бит, в результате после первого сдвига bl = 01100000b, старший 0 уйдет в бит CF, т.е. CF=0
Команда adc dl,0 сложит содержимое регистра dl с нулем (надо что-то указать) и бита CF, в результате получим dl = '0'
Выводим по функции 2 символ из dl и циклим, пока cx не 0 (команда loop)
На следующих шагах будем иметь:
bl = 11000000b, CF=0, dl = '0'
bl = 10000000b, CF=1, dl = '1'
bl = 00000000b, CF=1, dl = '1'

Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
05.08.2009, 13:59
общий
Dimon4ik:
Давайте, я объясню.
Регистр BL - 8-мибитный. Биты в регистрах нумеруются от младших к старшим, начиная с нуля.
Т.е. биты регистра будут расположены так: 7 6 5 4 3 2 1 0
Допустим, что мы ввели цифру 5. В кодировке ASCII цифре 5 соответствует код 53, который в 16-ричной с.с. записывается как 35h, а в двоичной - как 00110101b.
Вначале (перед циклом) производятся 4 сдвига влево на 1 разряд (т.е. суммарно сдвиг влево на 4 разряда). При этом старшие разряды "выходят" за разрядную сетку, т.е. пропадают.
Справа же биты заполняются нулями.
В результате значение регистра BL перед циклом станет равным 01010000b.

Теперь переходим к циклу.
Первая команда (shl bl, 1) производит сдвиг влево регистра BL на 1 разряд. В результате операции биты 7-1 регистра BL примут значения битов 6-0 данного регистра перед операцией, бит 0 примет значение 0, а значение бита 7 регистра перед выполнением операции будет помещено в бит переноса регистра флагов (CF).

Т.е. на первой итерации после выполнения этой команды регистры процессора будут иметь такие значения:
BL = 10100000b
CF = 0

Вторая команда заносит в регистр DL значение '0'. Цифра '0' в кодировке ASCII имеет код 48, в 16-ричной с.с. он представляется как 30h, в десятичной - 00110000b.
Т.е. регистр DL принимает значение 00110000b

Теперь самая интересная команда - adc dl, 0. Эта команда осуществляет прибавление к значению регистра DL числа 0 и, дополнительно, прибавление значения флага переноса. Т.е. DL = DL + 0 + CF [$8660$] DL = DL + CF.
На первом шаге, т.к. CF = 0, регистр DL останется без изменений, т.е. будет иметь значение 00110000b

Последовательность команд mov ah, 2; int 21h вызывает функцию 2 прерывания 21h. Данная функция выводит в консоль символ, код ASCII которого соответствует значению регистра DL. В нашем случае там записан код символа '0', т.е. будет произведен вывод на экран цифры 0.

Команда loop bin_loop уменьшает значение регистра CX на 1 и в случае, если CX [$8800$] 0, осуществляет передачу управления на заданную метку, т.е. организует цикл. У нас значение CX равно 4, значит, после выполнения команды CX станет равным 3 и будет осуществлена передача управления.

Быстро разберем оставшиеся итерации.
Шаг 2.
Состояние регистров:
BL = 10100000b
CX = 3

shl bl, 1: BL = 01000000b; CF = 1
mov dl, '0': DL = 00110000b
adc dl, 0: DL = 00110001b = 31h = '1'
mov ah, 2
int 21h - вывод цифры 1 на экран
loop bin_loop: CX = 2, переход

Шаг 3.
Состояние регистров:
BL = 01000000b
CX = 2

shl bl, 1: BL = 10000000b; CF = 0
mov dl, '0': DL = 00110000b
adc dl, 0: DL = 00110000b = 30h = '0'
mov ah, 2
int 21h - вывод цифры 0 на экран
loop bin_loop: CX = 1, переход

Шаг 4.
Состояние регистров:
BL = 10000000b
CX = 1

shl bl, 1: BL = 00000000b; CF = 1
mov dl, '0': DL = 00110000b
adc dl, 0: DL = 00110001b = 31h = '1'
mov ah, 2
int 21h - вывод цифры 1 на экран
loop bin_loop: CX = 0, нет перехода

В результате на экран будет выведена такая последовательность: 0101, что соответствует цифре 5
Неизвестный
05.08.2009, 20:26
общий
_Ayl_:
Спасибо большое. Теперь я все понял. Еще раз спасибо за то что обьяснили.
Форма ответа