Вывод на экран таблицы Ascii (assembler)

  • Автор темы Ancient
  • Дата начала
A

Ancient

Гость
#1
Пример из отсканированной книги "Assembler, язык неограниченных возможностей" Зубков С.В, 1999 Издательство «ДМК Пресс».
:(
В учебнике есть замечательный пример использования функции DOS-а 09. Суть в том, что пример должен выводить ASCII-таблицу (256 символов), 16-ю строками по 16 символов+2 символа "переноса строки.
Код:
; dosout1.asm
; Выводит на экран все ASCII-символы
;
.model tiny
.code
org		 100h		; начало СОМ-файла
start:
mov		 сx,256; вывести 256 символов
mov		 dl,0		; первый символ - с кодом 00
mov		 ah,2		; номер функции DOS "вывод символа"
cloop: int		 21h		 ; вызов DOS
inc		 dl	; увеличение DL на 1 - следующий символ
test		dl,0Fh; если DL не кратен 16,
jnz		 continue_loop; продолжить цикл,
push		dx	; иначе: сохранить текущий символ
mov		 dl,0Dh; вывести CR
int		 21h
mov		 dl,0Ah; вывести LF
int		 21h
pop		 dx	; восстановить текущий символ
continue_loop:
loop		cloop	; продолжить цикл
ret					 ; завершение СОМ-файла
end		 start
Вообще, первоначально в 8-й строке
Код:
 mov		 сx,256
стояло
Код:
 mov		 ex,256; вывести 256 символов
но компилятор (TASM) решительно отказался читать подобное за и loop по описанию предназначен для работы с CX, поэтому произвёл замену EX на CX.

Программа явно COM-типа (
Код:
.model tiny
), поэтому компилировал (на WinXP SP3) тупо:
Код:
tasm dosout1.asm
tlink dosout1.obj
Результатом стал файлик dosout1.com и предупреждение от tlink-а "Warning: No stack".

Итоговая программа работает далеко не один раз, а в зависимости от кто бы его знал чего, от 5 до 36 раз (и более). Измерено с помощью вывода в файл dosout1 >dosout1.txt.
Отладчик ничего конкретного не дал, только понимание что символы выводятся вроде как правильно и то что после последней команды, программа начинает работу сначала.

Внимание вопрос: Какого чёрта? (Почему происходит то, что происходит). Программа должна сработать один раз... а не тучу.
Вопрос2: Что сделать чтобы оно работало "правильно"? :)

PS: Раньше вполне неплохо работал на Pascal-е и Delphi, но с тех пор уже немало воды утекло. Резкий переход на ASM пока что сносит все понятия о понимании. :) Заранее спасибо за помощь...
 
A

Ancient

Гость
#2
Команда RET используется обычно для возвращения из процедуры. DOS вызывает СОМ-программы так, что команда RET корректно завершает программу.
--------------------------------------------------------------------------------
DOS при вызове СОМ-файла помещает в стек сегментный адрес программы и ноль, так что RET передает управление на нулевой адрес текущего сегмента, то есть на первый байт PSP. Там находится код команды INT 20h, которая и используется для возвращения управления в DOS. Можно сразу заканчивать программу командой INT 20h, хотя это длиннее на 1 байт.
С другой стороны, Ваш пример при сборке выдал три предупреждения:
Assembling file: dosot1.ASM
*Warning* dosot1.ASM(30) Open procedure: TPROC
*Warning* dosot1.ASM(30) Open segment: CSEG
*Warning* dosot1.ASM(30) Open segment: STSEG
Error messages: None
Warning messages: 3
Passes: 1
Remaining memory: 452k
Но работал вполне адекватно.
ассемблер не знаю совсем, но программа должна работать как то так:
А откуда тогда пример (работающий), раз совсем не знаете? :) Просто любопытно.