Консультация № 173828
29.10.2009, 22:24
0.00 руб.
0 6 2
Приветствую! Пришел я к вам с просьбой о помощи) а помощь нужна в следующем:
"Написать на ассемблере подпрограмму вывода на экран значения регистра AX в десятичной системе счисления без использования прерываний DOS и BIOS (для текстового режима видеокарты, для процессора Intel 8086) ", т.е. кто-либо пишет программу, решает забить в AX, например, 1234 и потом вызвать подпрограмму для перевода числа в десятичную систему и вывода его на экран(без прерываний, повторюсь)) вот что получилось из трудов:

Код:
mov ax,0B800h		
mov es,ax
mov di,0

std

mov cx,10
Repeat:
xor dx,dx
div cx

xchg ax,dx
add al,'0'
stosb
inc di
xchg ax,dx
or ax,ax
jne Repeat

и далее сами вопросы. Если пользователь вносит в AX число, то использовать его уже нельзя чтобы не "испортить", т.е. надо воспользоваться push и pop, насколько я понимаю? push ax и далее код подпрограммы. Следующее это цикл. строка "or ax,ax" была написана с расчетом того, что она будет сравнивать AX нулем и далее если не равно, то запускать цикл заново. как мне объяснили, она не проверяет, а обнуляет?бред...не могу понять...

Выражаю огромную признательность заранее!

Обсуждение

Неизвестный
29.10.2009, 23:36
общий
30.10.2009, 09:53
это ответ
Здравствуйте, Trivi.
и далее сами вопросы. Если пользователь вносит в AX число, то использовать его уже нельзя чтобы не "испортить", т.е. надо воспользоваться push и pop, насколько я понимаю? - обычно хорощо когда процедура не портит регистры, но в данном случае программист решает что сохранить что нет.
Код:
Следующее это цикл. строка "or ax,ax" была написана с расчетом того, что она будет сравнивать AX нулем и далее если не равно, то запускать цикл заново. как мне объяснили, она не проверяет, а обнуляет?бред...не могу понять...
- она не обнуляет (обнулит xor)
она выставит флаги в соответствии со значением в ax, будут там ноль, поднимет флаг ZF
в логике кода вроде все верно (если поменять std на cld), только число будет задом наперед
Неизвестный
30.10.2009, 00:19
общий
можно сделать и так

push ax
mov ax,0B800h
mov es,ax
pop ax

но проще сменить регистр
mov dx,0B800h
mov es,dx

далее мы делим число в ax на 10 и записываем в видеобуфер цифры остатков
mov di,0 - неверно!
сохранение происходит в обратном направлении, поэтому при выполнении команды stosb из регистра di будет вычитаться 1
максимальное значение 16-разрядного регистра
0FFFFh = 65535
т.е. максимальная длина вывода составит 5 десятичных цифр
поэтому di нужно инициализировать так, чтобы он указывал в видеопамяти на последнюю цифру результата
mov edi,4*2
или mov edi,8
на 2 умножаем потому, что символ в видеопамяти представлен двумя байтами - байт кода символа + байт атрибутов отображения

stosb
inc di

назначение команды после stosb - обойти байт атрибутов предыдущего символа
но сохранение происходит в обратном порядке
поэтому di нужно не увеличивать, а уменьшать на 1

stosb
dec di

далее
or ax,ax
jne Repeat

эта конструкция будет работать
команда or выполняет операцию ИЛИ над битами операнда назначения, используя в качестве маски второй операнд
если двумя операндами является один и тот же регистр, то значение этого регистра не изменится
например ax=5

OR
101
101
---
101

но установятся флаги
и если ax=0, то ZF=1

можно так:

cmp ax,0
jne Repeat

или так:

test ax,ax
jnz Repeat

а тот, кто вам сказал про обнуление имел в виду исключающее ИЛИ

xor ax,ax

это то же, что и

mov ax,0
давно
Посетитель
7438
7205
30.10.2009, 01:00
общий
это ответ
Здравствуйте, Trivi.
Программа в приложении
Если пользователь вносит в AX число, то использовать его уже нельзя чтобы не "испортить", т.е. надо воспользоваться push и pop, насколько я понимаю?
Вы правы. Чтобы сохранить содержимое регистра, можно воспользоваься push pop.
Следующее это цикл. строка "or ax,ax" была написана с расчетом того, что она будет сравнивать AX нулем и далее если не равно, то запускать цикл заново. как мне объяснили, она не проверяет, а обнуляет?
Все правильно написано. Только команда не сравнивает с нулем, а делает логическое ИЛИ содержимого регистра AX самого с собой, при этом устанавливаются флаги результата. В итоге, переход на метку Repeat будет, если в AX не 0. (Хотя внешне получается, что сравнивается с 0). С той же целью можно было использовать AND или TEST. Вы перепутали с командой XOR, которая, действительно, обнуляет.

Удачи в освоении ассемблера!

Приложение:
.model tiny

color equ 0bh ;цвет выводимых символов

.code
org 100h ;для СОМ-файла
start:
mov ax,3 ;под ХР для прямого вывода на экран
int 10h ;необходимо переустановить видеорежим

mov ax,0B800h ;сегмент видеобуфера
mov es,ax

mov di,4*2 ;адрес правого (младшего) символа числа
;максимум 5 символов, на каждый 2 байта (сам символ и арибут)
std ;автодекремент адреса

mov ax,1234 ;выводимое число
call print ;рисуем на экране

mov ah,0 ;ждем нажатие на клавишу
int 16h

mov ax,4c00h ;выход в ДОС
int 21h

print proc ;процедура вывода на экран
push ax cx dx di ;сохраним используемые регистры в стеке
mov cx,10 ;делим на 10
Repeat:
xor dx,dx ;подготавлим деление
div cx ;dx:ax / cx
xchg ax,dx ;в ax остаток, в dx частное
add al,'0' ;0-9 в '0'-'9'
mov ah,color ;добавим атрибут
stosw ;выведем, di = di - 2
xchg ax,dx ;в ax частное
or ax,ax ;проверим на 0 (xor ax,ax обнуляет регистр)
jne Repeat ;если не 0, то повторим
pop di dx cx ax ;восстановим регистры из стека
ret
print endp
end start
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
30.10.2009, 02:37
общий
Огромное спасибо за ответы, от гранита науки отломилось еще немного знаний в мою пользу!
давно
Посетитель
7438
7205
30.10.2009, 09:37
общий
Airyashov:
в логике кода вроде все верно, только число будет задом наперед
Вы проверяли? Между прочим, в коде не все в порядке... Обратите внимание.
Код:
std
...
stosb
inc di
1)установили автодекремент !!!!!!!
2)записали байт, после чего DI уменьшится на 1 !!!!
3)увеличиваем DI на 1
И что получили? Пишем в одно и тоже место !!!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
30.10.2009, 09:39
общий
да обратил только позно было
Форма ответа