Прочитав, по крайней мере, первые 3 или 4 главы о 4 разных книгах по программированию на ассемблере, я подошел к этапу, когда я могу поместить «Hello World» в консоль dosbox, используя MASM 6.11.Вообразите мое восхищение !!
Первая версия моей программы использовала функцию DOS 13h.Вторая версия моей программы использовала функцию BIOS 10h
Теперь я хочу сделать третью версию с использованием прямого аппаратного вывода.Я прочитал части книг, в которых объясняется, что экран на VGA-мониторах разделен на 80x25 (не беспокоит обнаружение CGA и все такое, поэтому моя программа использует адрес памяти 0B800h для цветного VGA, потому что DOSBox отличный и все, и мое желаниеперейти на Win Assembler раньше, чем мне исполнилось 90 лет).Я прочитал, что каждый символ на аппаратном экране составляет 2 байта (1 для атрибута и один для самого символа, поэтому у вас есть 80x25x2 = 4000 байтов).Нечетные байты описывают атрибут, а четные байты символ ASCII.
Но моя проблема заключается в следующем.Независимо от того, как я стараюсь, я не могу заставить свою программу выводить простую черно-белую (что является просто атрибутом, я предполагаю, что я могу достаточно легко изменить) строку (которая является просто массивом байтов) в 5 строках сверхуэкран и 20 символов от левого края (это просто количество пустых символов от нулевого индекса с длиной 4000 байтов).(если мой расчет верен, то есть 5x80 = 400 + 20 = 420x2 = 840 - это начальная позиция моей строки в массиве 4000 байтов)
Как отделить атрибут от символа (я его получилработать частично, но он показывает только каждый второй символ, затем кучу случайного мусора (вот как я понял, мне нужна какая-то пара байтов для атрибута и текста), или как мне настроить ее так, чтобы оба распознавались вместе.Как я могу контролировать положение текста на экране после выполнения вычислений. Куда я иду не так.
Я пытался поискать в Интернете этот, казалось бы, простой вопрос, но не смог найти решение.Есть ли кто-нибудь, кто программировал в DOS и x86 Assembly, кто может сказать мне, как сделать эту простую маленькую программу, не используя функции BIOS или DOS, только с помощью аппаратного обеспечения.
Я бы действительно оценил простой фрагмент кодаесли возможно. Или ссылка на какой-то сайт или бесплатную электронную книгу. Я не хочу покупать большую книгу о дос консольном программировании, которая будетв конечном итоге я буду бесполезен, когда перейду к окнам.Единственная причина, по которой я сосредоточен на этом, заключается в том, что я хочу изучать настоящую сборку, а не какой-то макроязык или какой-нибудь претенциозный язык высокого уровня, который претендует на то, что он ассемблер.
Я пытаюсь создать библиотеку подпрограмм, которая будетупростить изучение ассемблера, чтобы людям не приходилось работать, хотя все от 3 до 6 глав в 10 книгах по теории снова и снова объясняют одно и то же, когда на самом деле все, что нужно, достаточно, чтобы знать, как получить какой-то результат, назначить значения дляпеременные, получить некоторый вклад, и сделать несколько циклов и решений.Теория может появиться позже, и к тому времени, когда они придут к циклам и решениям, большинство людей сделают достаточно ассемблера, чтобы в любом случае иметь всю теорию.Я верю, что ассемблеру нужно учить ничем не отличающемуся от любого другого языка, начиная с простой программы hello world и заканчивая вводной информацией.Я хочу сделать это возможным.Но, эй, я только новичок, может быть, мои уловки изменятся, когда я узнаю больше.
Еще одно замечание, я точно знаю, что проблема не в DOSBox, так как у меня очень старый ПК, работающий верноMS-DOS V6.2 и программа по-прежнему не работают (но выдают практически идентичный вывод).На самом деле, DOSBox запускает некоторые из моих старых программ даже лучше, чем True DOS.Gem Desktop является одним из примеров.Просто хотел, чтобы это очистили, прежде чем люди попробуют предположить, что это проблема с эмулятором.Не может быть, не с такими простыми программами.Не боюсь, проблема в том, что мой маленький мозг не совсем понимает, что нужно.
Может кто-нибудь там помочь, пожалуйста !!
Ниже приведена программа, которую я использовал (MASM 6.1 в DOSBox на Win 7 64-bit).Он использует BIOS Intrrupt 10h Функция 13h Подфункция 0. Я хочу сделать то же самое, используя прямой аппаратный ввод-вывод.
.model small
.stack
.data ;part of the program containing data
;Constants - None
;Variables
MyMsg db 'Hello World'
.code
Main:
GetAddress:
mov ax,@data ;Gets address of data segment
mov es,ax ;Loads segment address into es regrister
mov bp,OFFSET MyMsg ;Load Offset into DX
SetAttributes:
mov bl,01001111b ;BG/FG Colour attributes
mov cx,11 ;Length of string in data segment
SetRowAndCol:
mov dh,24 ;Set the row to start printing at
mov dl,68 ;Set the column to start printing at
GetFunctionAndSub:
mov ah,13h ;BIOS Function 10h - String Output
mov al,0 ;BIOS Sub-Function (0-3)
Execute:
int 10h ;BIOS Interrupt 10h
EndProg:
mov ax,4c00h ;Terminate program return 0 to OS
int 21h ;DOS Interrupt 21h
end Main
end
Я хочу иметь это в формате, который легкообъяснить.Так вот мои текущие работы.Я почти получил это.Но он печатает только атрибуты, а вывод символов на экран - это проблема.(Иногда, когда я немного изменяю его, я получаю каждый второй символ со случайными атрибутами (я думаю, я знаю технические детали, почему, но не знаю достаточно ассемблера, чтобы это исправить)).
.model small
.stack
.data
;Constants
ScreenSeg equ 0B800h
;Variables
MyMsg db 'Hello World'
StrLen equ $-MyMsg
.code
Main:
SetSeg:
mov ax, ScreenSeg ;set segment register:
mov ds, ax
InitializeStringLoop: ;Display all characters: - Not working :( Y!
mov cx, StrLen ;number of characters.
mov di, 00h ;start from byte 'h'
OutputString:
mov [di], offset byte ptr MyMsg[di]
add di, 2 ;skip over next attribute code in vga memory.
loop OutputString
InitializeAttributeLoop:;Color all characters: - Atributes are working fine.
mov cx, StrLen ;number of characters.
mov di, 01h ;start from byte after 'h'
;Assuming I have all chars with same attributes - fine for now - later I would make this
;into a procedure that I will just pass the details into. - But for now I just want a
;basic output tutorial.
OutputAttributes:
mov [di], 11101100b ;light red(1100) on yellow(1110)
add di, 2 ;skip over next ascii code in vga memory.
loop OutputAttributes
EndPrg:
mov ax, 4C00h
int 21h
end Main
Конечно, я хочу сократить инструкции, используемые до базовых предметов.(для правильных целей обучения, меньше, чтобы покрыть, обучая других).Я понял причину, по которой я не использовал MOVSB / W / D и т. Д. С REP.Вместо этого я выбрал простой для объяснения ручной цикл, используя стандартные MOV, INC, ADD и т. Д.Это достаточно простые инструкции, которые легко объяснить новичкам.Поэтому, если возможно, я бы хотел, чтобы это было как можно ближе к этому.
Я знаю, по сути, все, что кажется неправильным - это цикл для фактического обработчика строк.Это не позволяет мне увеличивать адрес так, как я хочу.Это меня смущает, потому что я на самом деле неплохой программист, использующий C ++, C #, VB и Delphi (еще когда)).Я знаю, что вы не подумали бы, что, учитывая, что я не могу даже получить правильную петлю в ассемблере, но это такой другой язык.В языках высокого уровня есть 2 или 3 цикла, и, кажется, существует бесконечная комбинация способов создания циклов в ассемблере в зависимости от инструкций.Поэтому я говорю «Простая петля», но на самом деле в этом мало простого.
Я надеюсь, что кто-то может помочь мне с этим, вы спасете мою сборочную карьеру и обеспечите, чтобы я в конечном итоге стал хорошим учителем сборки.,Спасибо заранее, и особенно за чтение этого далеко.