Консультация № 170814
26.07.2009, 16:47
0.00 руб.
0 15 2
Здраствуйте,помогите разобраться с проблемой
arver segment
org 100h
begin:
mov ax,0B800h
mov es,ax
mov di,0
mov ah,31
mov al, 1
mov es:[di] ,ax
mov ah,10h
int 16h
int 20h
arver ends
end begin у меня при открытии com файла ни рожицы,ничего вообще не отображается (менял в регисте al цифры) и в эмуляторе тоже ничего не отображется, хотелось бы узнать почему?

Обсуждение

Неизвестный
26.07.2009, 20:06
общий
Под эмулятором DOSBox Ваш код отлично работает, под Windows XP/Vista - нет.
Неизвестный
26.07.2009, 20:34
общий
а объяснить можете из-за чего в windows XP /Vista не пашет?
Неизвестный
26.07.2009, 21:14
общий
Код:
arver segment
org 100h
begin:
mov ax,0003h
int 10h
mov ax,0B800h
mov es,ax
mov di,0
mov ah,31
mov al, 1
mov es:[di] ,ax
mov ah,10h
int 16h
int 20h
arver ends
Неизвестный
26.07.2009, 21:32
общий
скопировал код вверху и получил ошибку,подумал ну все ,оказывается не хватает в конце end begin( не сразу заметил)и все таки не понял почему в книжке АССЕМБЛЕР ЭТО ПРОСТО!(Олег Калашников),указано что запускается com файл,а тут как я понял exe файл
Неизвестный
27.07.2009, 00:38
общий
В windows-системах с NT-ядром запрещен прямой доступ к видеопамяти (0b800h). Отсутсвие директивы описания стека и наличие директивы адреса загрузки программы - org 100h указывает на структуру com-программы.
Неизвестный
27.07.2009, 00:46
общий
Решение Airyashov со включением видеорежима (mov ax,0003h, int 10h) оказывается отлично решает проблему и под XP
Неизвестный
27.07.2009, 02:19
общий
27.07.2009, 20:00
это ответ
Здравствуйте, Степанов Александр Андреевич.

Данный код при выполнении в среде Windows 2000 и выше не приводит к ожидаемому результату потому, что окно DOS-задачи в текстовом режиме в качестве активной использует видеостраницу №1, которая имеет начальный адрес видеопамяти B800:04001000, а приведенный код выводит "рожицу" в видеостраницу №0, которая начинается с адреса B800:0000.
Принудительная установка режима (mov ax, 3; int 10h) приводит к тому, что активной страницей становится нулевая, после чего запись данных в видеопамять приводит и к их отображению.
Вместо вызова функции установки режима также может быть использована функция установки активной страницы (mov ax 0500h; int 10h).
5
спс
давно
Посетитель
7438
7205
27.07.2009, 10:25
общий
Дмитрий Бобровников:
В windows-системах с NT-ядром запрещен прямой доступ к видеопамяти (0b800h)

Простите, но это полная чушь. Никак не ожидал от Вас такое услышать
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
31795
6196
27.07.2009, 11:45
общий
_Ayl_:
С чего Вы взяли, что по умолчанию вывод идет именно в эту область памяти(т.е. ХР устанавливает именно такой режим):
Цитата: 299557
потому, что окно DOS-задачи в текстовом режиме в качестве активной использует видеостраницу №1, которая имеет начальный адрес видеопамяти B800:0400

80*25*2=400010=FA016, что больше 40016, т.е. записанный символ(рожица) должен отображатся, где нибуть вверхней части экрана. Вот примерчик, по Вашим словам вверхнем-левом углу должен быть символ.


Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
27.07.2009, 12:24
общий
Лысков Игорь Витальевич:
Цитата: Лысков Игорь Витальевич
Простите, но это полная чушь. Никак не ожидал от Вас такое услышать

Это действительно полная чушь, как я проверил и убедился. Я встречал такую информацию на каком-то FAQ-тематическом ресурсе.
Неизвестный
27.07.2009, 14:42
общий
Зенченко Константин Николаевич:
Спасибо за указание на ошибку в адресе
Вот хоть убей, не помню, откуда взялось смещение 400h. Сидело в голове, что адрес первой страницы имеет такое смещение.
На самом деле первая страница в режиме 80*25 начинается с адреса B800:1000, а для режима 40*25 - с адреса B800:0800.
В первом случае страница занимает 4000 байт (и 96 байт не используются для выравнивания начального адреса следующей страницы),
во втором - 2000 байт (на выравнивание расходуется 48 байт).
давно
Посетитель
7438
7205
27.07.2009, 14:52
общий
_Ayl_:
У меня получилось показать буковку на экране

Только вот беда: программа нормально отработает только, если запустить COM-файл, ну или из-под command.com
Вы попробуйте запустить из-под cmd - и Вы ничего не увидете
Так что, этот метод в общем случае не годится...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
31795
6196
27.07.2009, 14:53
общий
_Ayl_:

Возможно это таблица прерываний. Первые 400h байт.

Внимательней пожалуйста.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
27.07.2009, 15:28
общий
Там всё несколько хитрее:
Код:
model tiny
.code
.186
org 100h
begin:
;первая попытка, потом строки закомментировать
mov ax,3h
int 10h
mov al,'a'
int 29h
mov al,'+'
int 29h
mov al,'b'
int 29h
;xor ax,ax
;int 16h
;вторая попытка - разкомментировать.
;mov ax,83h
;int 10h
;xor ax,ax
;int 16h
mov ax,0b000h
mov es,ax
mov cx,7fffh
xor di,di
isSearch:
cmp byte ptr es:[di+0],'a'
jnz noCompare
cmp byte ptr es:[di+2],'+'
jnz noCompare
Cmp byte ptr es:[di+4],'b'
jnz noCompare
push ax
push cx
mov ax,di
mov cx,4
isShow:
rol ax,4
push ax
and ax,0fh
cmp al,9
jle isDecimal
add al,7
isDecimal:
add al,30h
int 29h
pop ax
loop isShow
pop cx
pop ax
noCompare:
inc di
inc di
loop isSearch
mov al,'='
int 29h
xor ax,ax
int 16h
ret
end begin

До определения видеорежима вывод идет мимо видеобуфера и только после его опредения через видеобуфер.

Попробуйте вариант, когда обе установки видеорежима закомментированны.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
27.07.2009, 22:51
общий
это ответ
Здравствуйте, Степанов Александр Андреевич.

Вы спрашивали:
Цитата: 266722
а объяснить можете из-за чего в windows XP /Vista не пашет?

Смотрите приложение.
В приложении программа, которая тестирует вывод информации в 3-ем текстовом режиме командной оболочкой ХР.
Начнем с истории: вывести информацию в чистом MS-DOS можно было четырьмя способами:
- использовать функции MS-DOS(21h-е прерывание, я использовал не докумментированую функцию int 29h, информация записывается в видеобуфер либо средсвами BIOS либо своими MS-DOS и выводится на экран);
- использовать функции BIOS(int 10h - 09h,10h,0eh,13h, информация записывается в видеобуфер и только потом выводится на экран);
- использовать прямую запись в видеобуфер (именно Ваш вопрос: программа записывает нужную информацию в видеобуфер, а потом видеоконтролер считывает её и выводит на экран);
- использовать прямую работу с видеоконтролером(программа передаёт нужную информацию прямо в видеокнтролер минуя посредников, а он её выводит на экран).
Именно в такой последовательности эммулируется MS-DOS в command.com Win9x. Разработчики WinNT(2K, XP или Vista) пошли другим путем, они посчитали, что пользователю не нужно знать как эммулируется их программа в cmd.exe, главное чтобы она выполняла задачи разработчика. Если Вы в WinNT пользуетесь стандартными средствами MS-DOS или BIOS всё проходит гладко, пользователь этого даже не замечает, но с нестандартными методами вывода появляюся проблемы.
у Вас именно нестандарный метод.
Итак по программе в приложении, что она делает: Информация на экран выводится стандартными средствами MS-DOS или BIOS, а потом ищется в видеобуфере её наличие:
Есть несколько вариантов её использования:
Вариант №1(вариант №2 должен быть закомметирован)- перед началом вывода устанавливается 3-ий текстовый режим и информация записывается куда нужно.Строки:
mov al,10;переход на следующую строку, нужны только чтобы не затиралась информация в варианте №2
int 29h

переводят строку именно для второго варианта, пока их не касаемся, но учтем это, т.е. в 3-ем текстовом режиме одна строка на экране длиною 80-т символов и каждый символ занимает два байта(код символа и цвет+фон), итого получается 16010=A016. Программа выводит информацию в 16-ой системе.
Вариант №2 (первый вариант закомментирован), текстовый режим устанавливается после вывода на экран. Заметьте он устанавливается со старшим битом равным 1, строка mov ax,83h, разложите число в битовое представление. Такой вариант позволяет переходить в нужный режим не очищая экран. При этом курсор переводится в левый-верхний уголо и вывод начнется именно с этой позиции, именно для этого и переводилась строка. Такой подход заставляет видеоконтролер нужным образом заполнить видеобуфер самому.
Теперь вариант №0, когда все варианты отключены, т.е. закомментированы. Это практически и есть Ваша программа, но мы всё делаем методом от обратного, т.е. выводим информацию, а потом ищем нужную запись в видеобуфере. В результате - результата нет.
Итого что имеется:
Вариант №1 - информация в видеобуфере есть и программа работает правильно.
Вариант №2 - информация в видеобуфере есть, но она копируется когда устанавливается режим без очистки экрана.
Вариант №0 - видеобуфер Видео буфер пуст и вывод идет именно четвёртым способом, т.е. прямая работа с видеоконтролером.
Но это работа эммулятора WinNT, а не чистой MS-DOS.
Еще капельку истории, о том как происходит вывод в эмуляторе. По своей сути эммулятор WinNT, это только консольное приложение WinNT, которое использует нужные фунции для вывода на экран.
После продолжительных споров с экспертом Лысковым И. В., мы оба пришли к выводу,
что эммулятор CMD.EXE с целью увеличеиня быстродействия приложений пользователя эмулируя функции MS-DOS или BIOS, использует прямую запись информации в видеоконтролер минуя видеобуфер, роль видеоконтролера выполняют консольные функции Windows API. И только когда непосредственно задан видеорежим создается полная эммуляция работы "железа", т.е. запись в видеобуфер, чтение информации из него видеоконтролером и выводом её на экран

Удачи!

Приложение:
model tiny
.code
.186
org 100h
begin:
;Вариант №1
mov ax,3h
int 10h
mov al,10;переход на следующую строку, только чтобы не затиралась информация
int 29h
mov al,'a'
int 29h
mov al,'+'
int 29h
mov al,'b'
int 29h
;тут ещё в предыдущем режиме
xor ax,ax
int 16h
;Вариант №2

int 10h
;тут уже в установленном
xor ax,ax
int 16h
;
;Код поиска и вывода адреса
mov ax,0b800h
mov es,ax
mov cx,3fffh
;начинаем с начала сегмента
xor di,di
isSearch:
cmp byte ptr es:[di+0],'a'
jnz noCompare
cmp byte ptr es:[di+2],'+'
jnz noCompare
Cmp byte ptr es:[di+4],'b'
jnz noCompare
push ax
push cx
mov ax,di
mov cx,4
isShow:
rol ax,4
push ax
and ax,0fh
cmp al,9
jle isDecimal
add al,7
isDecimal:
add al,30h
int 29h
pop ax
loop isShow
pop cx
pop ax
noCompare:
inc di
inc di
loop isSearch
mov al,'='
int 29h
xor ax,ax
int 16h
ret
end begin
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа