Консультация № 187303
27.04.2013, 21:12
99.97 руб.
0 25 1
Здравствуйте, Эксперты! Для учебной цели дали задание:
Разработать программу, работающую в реальном режиме, располагающуюся в

загрузочном секторе носителя (дискета, usb-flash, жесткий диск) и

выполняющую операцию считывание заданных параметров и вывод на экран в

заданной форме с последующим вводом и установкой.
Считывание и установка минут и секунд
Формат считывания: Десятичный формат установки: Шестнадцатиричный

Это задание для процессора семейства x86
Использую компилятор FASM

В интернете нашел исходный код для загрузчика:
Код:

USE16
org 0x7C00
start:
xor eax, eax
xor esi, esi
xor edi, edi
mov ds, ax
mov es, ax
mov bp, 0x7c00
mov ax, 0x0003
int 0x10
mov si, msg_Load
call print_string_16
jmp 0x0000:0x8000
print_string_16:
pusha
mov ah, 0x0E
.repeat:
lodsb
cmp al, 0
je .done
int 0x10
jmp short .repeat
.done:
popa
ret

msg_Load db "Hello World!", 0


mov ah,0
int 16h

times 510-$+$$ db 0

sign dw 0xAA55

times 512-$+$$ db 0


Скомпилировалось нормально, появился файл bin

Теперь о возникших трудностях:

1) Как записать этот загрузчик на флешку и создать образ ISO для запуска

на виртуальной машине?
Про флешку так толком ничего и не нашел, а по поводу образа, в интернете

я находил такое решение:
"в WinImage создаю дискету на 1.44, далее выбираю опцию boot sector

properties и там открываю свой .bin файл. сохраняю как ima образ и

открываю его в CDBurnerXP. Далее - диск - загрузочные опции - сделать

диск загрузочным - указываю путь к ima и тип эмуляции ставлю 1.44.

сохраняю как ISO образ"
Все сделал как написано, запускаю ISO на виртуальной машине VMware

player, вижу только черный экран и немигающий курсор в левом верхнем

углу.

2) Как считать и установить минуты и секунды в заданных в задании формате?
Нашел такой исходник:
Код:

;---установка времени
MOV CH,HOURS ;вводим значения времени
MOV CL,MINUTES ;
MOV DH,SECONDS ;
MOV DL,HUNDREDTHS ;
MOV AH,2DH ;номер функции установки времени
INT 21H ;устанавливаем время
CMP AH,0FFH ;проверяем правильность значения
JE ERROR ;переход на обработку ошибки

;---получение времени
MOV AH,2CH ;номер функции получения времени
INT 21H ;получаем время
MOV DAY_OF_WEEK,AH ;получаем день недели из AH


Не знаю, работает ли этот код, ведь я не могу проверить из-за того что не могу запустить мой загрузчик.

Обсуждение

давно
Старший Модератор
31795
6196
27.04.2013, 23:51
общий
Второй код можно выбросить он для Вас бесполезен.
Т.к. задание:
Цитата: 396816
Разработать программу, работающую в реальном режиме, располагающуюся в загрузочном секторе носителя (дискета, usb-flash, жесткий диск) и выполняющую операцию считывание заданных параметров и вывод на экран в заданной форме с последующим вводом и установкой:
Считывание и установка минут и секунд
Формат считывания: Десятичный;
Формат установки: Шестнадцатиричный.

Насколько можно судить с задания, то Вы должны создать загрузочный образ для последующего запуска с него.
В момент загрзки в памяти находится только BIOS и соответсвенно нужно пользоватся её функциями или работать на прямую с портами устройств. Ни о каких INT 21H неможет быть и речи, это функции DOS.

В MBR важна не только сигнатрура 0xAA55, там как минимум должна быть заполнена одна из четырех записей о диске, т.е. в 66-ти последних байтах должно быть заполнено как минимум 16-ть байт + 2 байта(0xAA55). BIOS их проверяет и только потом передает управление на 0x7C00.


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

Неизвестный
28.04.2013, 13:26
общий
Пока с MBR не особо понятно. Попробую разобраться. Спасибо!
давно
Старший Модератор
31795
6196
28.04.2013, 20:40
общий
Цитата: 396816
Пока с MBR не особо понятно. Попробую разобраться.


Вот почитайте для ознакомления: Главная загрузочная запись

Обратите внимание на признак активности раздела, BIOS при загрузке ищет в определенной позиции 0х80, а не только 0х55АА, и только тогда передает управление самому загрузчику.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
29.04.2013, 12:32
общий
То, о чем я говорил:

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

Неизвестный
29.04.2013, 13:11
общий
Здравствуйте, Константин Николаевич!

Если я правильно понял
Смещение Длина Описание
000h 446 Код загрузчика
1BEh 64 Таблица разделов
16 Раздел 1
1CEh 16 Раздел 2
1DEh 16 Раздел 3
1EEh 16 Раздел 4
1FEh 2 Сигнатура (55h AAh)


Каждый раздел содержит:
Смещение Длина Описание
00h 1 Признак активности раздела
01h 1 Начало раздела — головка
02h 1 Начало раздела — сектор (биты 0—5), цилиндр (биты 6, 7)
03h 1 Начало раздела — цилиндр (старшие биты 8, 9 хранятся в байте номера сектора)
04h 1 Код типа раздела
05h 1 Конец раздела — головка
06h 1 Конец раздела — сектор (биты 0—5), цилиндр (биты 6, 7)
07h 1 Конец раздела — цилиндр (старшие биты 8, 9 хранятся в байте номера сектора)
08h 4 Смещение первого сектора
0Ch 4 Количество секторов раздела


Если все так, то тогда у меня такой вопрос: какие должны быть признаки активности разделов, если я пытаюсь загрузить что-то с флешки или с CD (с образа диска ISO)? Если правильно понял, то я должен определиться куда записывать мой загрузчик (имею ввиду на флешку или создавать образ CD), прежде чем мне задать код типа раздела.
Еще вопрос, он так, для моего понимания, зачем задается сигнатура 55h AAh, если это константа и должна задаваться всегда?
Неизвестный
29.04.2013, 13:13
общий
Цитата: Зенченко Константин Николаевич
То, о чем я говорил:

Формируется не загрузочный диск, без активных разделов.


Это наверное и есть причина почему был черный экран с немигающим курсором?
давно
Старший Модератор
31795
6196
29.04.2013, 14:01
общий
Сигнатура 0х55АА указывает, что данный сектор содержит в себе данные о разделах диска.
Основную программу уже набросал:
[code h=200]USE16
org 0x7C00
start:
;
push cs
push cs
push cs
pop ds
pop es
pop ss
mov sp,7C00h
;
mov ax,3h
int 10h
;
call GetTime
mov si,dbMinutes
call GetData
mov [oldTime_M],al
mov si,dbSeconds
call GetData
;Int 1A/AH=03h
;SET REAL-TIME CLOCK TIME
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
mov dh,al;
mov ch,[oldTime_H];
mov cl,[oldTime_S];
mov ah,03h;
int 1Ah;
;
call GetTime
;
;
GetData:
mov al,20h
call OutMess
xor di,di
GData:
xor ax,ax
int 16h
;
cmp al,13h;
jz GD_Stop;
cmp al,'0'
jb GData;
cmp al,'9'
ja GData;
;
push ax;
mov ah,0Eh;
mov bx,06;
int 1Ah;
pop ax;
;
shl di,4;
and al,0Fh;
or di,ax;
jmp short GData;
;
GD_Stop:
mov ax,di;
ret
;
GetTime:
;
;Int 1A/AH=02h
;GET REAL-TIME CLOCK TIME
;return:
;CF clear if successful
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
;CF set on error (i.e. clock not running or in middle of update)
mov ah,02h
int 1Ah
mov [oldTime_H],ch
;
mov al,cl;
call BCD2ASCII;
mov [l_min],al;
mov [h_min],ah;
;
mov al,dl;
call BCD2ASCII;
mov [l_sec],al;
mov [h_sec],ah;
;
mov si,message;
mov al,20h;
call OutMess;
ret
;

;sub-program
;
BCD2ASCII:
mov ah,al;
shr al,4;
call Num2Char;
xchg ah,al;
;
Num2Char:
and al,0Fh;
or al,30h;
ret
;
;
OutMess:
;
;Int 10/AH=0Eh
;VIDEO - TELETYPE OUTPUT
;input:
;AL = character to write
;BH = page number
;BL = foreground color
mov ah,0Eh;
mov bx,07h;
int 10h
lodsb
or al,al
jnz OutMess
ret
;
;
dbMinutes db 10,13,'Enter minutes:',0
dbSeconds db 10,13,'Enter seconds:',0
message db 10,13,'Time '
h_min db ?
l_min db ?,':'
h_sec db ?
l_sec db ?,0
oldTime_H db ?
oldTime_M db ?
;jmp 0x0000:0x8000

times 510-$+$$ db 0

sign dw 0xAA55

times 512-$+$$ db 0[/code]
Сейчас займусь записью её на флоп и преобразованием его в загрузочный. Комментарии тоже позже.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
29.04.2013, 17:14
общий
Рабочий код вашего задания:
[code h=200]USE16
org 0x7C00
start:
;адресуем сегментные регистры данных и стека
push cs
push cs
push cs
pop ds
pop es;в программе не используется, так за компанию
pop ss
mov sp,7C00h
;
;Int 10/AH=00h
;SET VIDEO MODE
;AH = 00h
;AL = desired video mode
;необязательно, т.к. монитор уже находится в текстовом режиме
mov ax,3h;вызываем функцию BIOS
int 10h;так для приличия
;начало программы
call GetTime;выводим текущее время
;
mov si,dbMinutes;сообщение о вводе минут
call GetData;вводим значение минут
mov [oldTime_M],al;запоминаем значение введенных минут
mov si,dbSeconds;сообщение о вводе секунд
call GetData;вводим значение секунд
mov dh,al;запоминаем секунды в регистре
;
;записываем новое значение минут и секунд
;
;Int 1A/AH=03h
;SET REAL-TIME CLOCK TIME
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
mov ch,[oldTime_H];востанавливаем старое значение часов
mov cl,[oldTime_M];востанавливаем новое значение минут
mov ah,03h;вызываем функцию BIOS
int 1Ah
;выводим новое время
call GetTime
;передаем упраление BIOS
int 18h
;Подпрограммы:
;
;ввод числа
GetData:
mov al,20h;пробел для вывода
call OutMess;выводим сообщение
xor di,di;сбрасываем аккумуятор введенного числа
GData:
;
;считываем символ с клавиатуры
;
;Int 16/AH=00h
;KEYBOARD - GET KEYSTROKE
;Return:
;AH = BIOS scan code
;AL = ASCII character
xor ax,ax;вызываем функцию BIOS
int 16h
;
cmp al,13;клавиша "ENTER"
jz GD_Stop;да заканчиваем ввод
cmp al,'0';проверка минимальной границы
jb GData;меньше-переходим
cmp al,'9';проверка максимальной границы
ja GData;больше-переходим
push ax;сохраняем значение введенной цифры
;
;выводим символ на экран
;
;Int 10/AH=0Eh
;VIDEO - TELETYPE OUTPUT
;input:
;AL = character to write
;BH = page number
;BL = foreground color
mov ah,0Eh;;вызываем функцию BIOS
mov bx,07
int 10h
pop ax;востанавливаем введенную цифру
;
shl di,4;сдвигаем аккумулятор
and ax,0Fh;получаем цифру
or di,ax;суммируем
jmp short GData;повторяем ввод цифры
;
GD_Stop:
mov ax,di;записываем результат п/программы
ret;возврат из п/программы
;
;получаем текущее время
GetTime:
;
;Int 1A/AH=02h
;GET REAL-TIME CLOCK TIME
;return:
;CF clear if successful
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
;CF set on error (i.e. clock not running or in middle of update)
mov ah,02h;вызываем функцию BIOS
int 1Ah
mov [oldTime_H],ch;запоминаем значение часов
;
mov al,cl;начинаем с минут
call BCD2ASCII;переводим BCD число в символ ASCII
mov [l_min],al;запоминаем минуты
mov [h_min],ah;запоминаем десятки минут
;
mov al,dl;теперь секунды
call BCD2ASCII;см. выше
mov [l_sec],al
mov [h_sec],ah
;
mov si,message;сообщение о текущум времени в минутах и секундах
mov al,20h;начальный пробел
call OutMess;выводим сообщение
ret;возврат из п/программы
;
;переводим BCD число в символ ASCII
BCD2ASCII:
mov ah,al;зоапминаем младшую часть числа
shr al,4;сдвигаем старшую часть числа
call Num2Char;вызываем п/пограмму
xchg ah,al;меняем местами старшую и младшую части числа
;
Num2Char:
and al,0Fh;выделяем цифру
or al,30h;переводим в символ ASCII
ret;возврат из п/программы
;
;вывод сообщения как Си-строки
OutMess:
;см. выше
mov ah,0Eh;вызываем функцию BIOS
mov bx,07h
int 10h
lodsb;считываем символ
or al,al;проверяем на нулевое значение
jnz OutMess;не ноль-переходим
ret;возврат из п/программы
;
;данные программы
dbMinutes db 10,13,'Enter minutes:',0
dbSeconds db 10,13,'Enter seconds:',0
message db 10,13,'Time '
h_min db ?
l_min db ?,':'
h_sec db ?
l_sec db ?,0
oldTime_H db ?
oldTime_M db ?
;jmp 0x0000:0x8000

times 510-$+$$ db 0

sign dw 0xAA55

times 512-$+$$ db 0[/code]

На дискету бинарный файл записывался с помощью программки:
[code h=200]use16
org 100h
start: mov ah,3Dh
mov dx,dbName
int 21h
mov [dwHndl],ax
;
mov bx,ax
mov ah,3Fh
mov dx,dbSector
mov cx,512
int 21h
;
mov ah,3Eh
mov bx,[dwHndl]
int 21h
;
xor ax,ax
int 13h
xor ax,ax
int 13h
xor ax,ax
int 13h
;
mov ax,0301h
mov bx,dbSector
mov cx,1
mov dx,0
int 13h
;
ret
dbName db 'q187303.bin',0
dwHndl dw ?
dbSector db 512 dup(?)[/code]

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

давно
Старший Модератор
31795
6196
29.04.2013, 17:25
общий
Оказалось, что вполне достаточно для BIOS сигнатуры 0xAA55, признак активности раздела используется только загрузчиками MBR.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
30.04.2013, 01:24
общий
03.05.2013, 19:41
Спасибо большое за код! Удалось записать загрузчик на флешку. Флешка работает только если с него загружаться, а сама оперционка ее прочитать не может... Файловую систему чтоль повредил...

Секунды, правда, не отображаются. Показывает все время 0, но я нашел ошибку

;
mov al,dh;теперь секунды
call BCD2ASCII;см. выше


Как сделать ввод чисел в 16-ричной форме?
давно
Старший Модератор
31795
6196
03.05.2013, 22:05
общий
Цитата: 396816
Как сделать ввод чисел в 16-ричной форме?

приблизительно так, только тут не учитывается регистр нажимаемых клавиш, в коде только проверки прописные буквы, если будет интерестно, то по аналогии можете написать и проверку строчных букв.
[code h=200]getnumber:
xor di,di;сбрасываем аккумулятор
mov bx,16;система счисления
GN0: xor ax,ax
int 16h
cmp al,13;клавиша ENTER
jz GN2
cmp al,'0'
jb GN0
cmp al,'9'
jbe GN1
cmp al,'A'
jb GN0
cmp al,'F'
ja GN0
GN1: push ax
mov ah,0Eh
mov bx,07
int 10h
pop ax
cmp al,'9';доп.проверка на НЕХТ код
jbe GN2
sub al,7;коррекция числа
GN2: and ax,0fh;получаем цифру
xchg di,ax;меняем местами аккумулятор и введенное число
xor dx,dx;сбрасываем старший регистр результата
mul bx;умножаем на систему счисления
add di,ax;суммируем в аккумуляторе новое число
jmp short GN0
GN3: mov ax,di
ret[/code]

Введение такого кода заставляет дополнительно заниматся подготовкой данных для функции BIOS, т.к. там на входе должен быть BCD-код.

Цитата: 396816
Удалось записать загрузчик на флешку. Флешка работает только если с него загружаться, а сама оперционка ее прочитать не может... Файловую систему чтоль повредил...

Это всё потому, что не расписаны таблицы разделов, ОСь их не находит и пишет, что диск не форматирован, поврежден вирусом и т.д.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
03.05.2013, 22:09
общий
Цитата: 396816
Секунды, правда, не отображаются. Показывает все время 0, но я нашел ошибку

;
mov al,dh;теперь секунды
call BCD2ASCII;см. выше

Да, сорри замотался, имено поэтому и писал в комментах полную информацию по функциям.
ps: приятно помогать, когда не просто глотают код, а разбираются в нём.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
04.05.2013, 01:40
общий
04.05.2013, 19:37
Исправил в еще одном месте
cmp al,13;клавиша ENTER
jz GN3

Если ввести А, то выводит 07, В -> 0' ', C-> тоже непонятный символ
11 -> 08, 12 -> 09

Вот весь код
[code h=200]
USE16
org 0x7C00
start:
;адресуем сегментные регистры данных и стека
push cs
push cs
push cs
pop ds
pop es;в программе не используется, так за компанию
pop ss
mov sp,7C00h
;
;Int 10/AH=00h
;SET VIDEO MODE
;AH = 00h
;AL = desired video mode
;необязательно, т.к. монитор уже находится в текстовом режиме
mov ax,3h;вызываем функцию BIOS
int 10h;так для приличия
;начало программы
call GetTime;выводим текущее время
;
mov si,dbMinutes;сообщение о вводе минут
call GetData;вводим значение минут
mov [oldTime_M],al;запоминаем значение введенных минут
mov si,dbSeconds;сообщение о вводе секунд
call GetData;вводим значение секунд
mov dh,al;запоминаем секунды в регистре
;
;записываем новое значение минут и секунд
;
;Int 1A/AH=03h
;SET REAL-TIME CLOCK TIME
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
mov ch,[oldTime_H];востанавливаем старое значение часов
mov cl,[oldTime_M];востанавливаем новое значение минут
mov ah,03h;вызываем функцию BIOS
int 1Ah
;выводим новое время
call GetTime
;передаем упраление BIOS
int 18h
;Подпрограммы:
;
;ввод числа
GetData:
mov al,20h;пробел для вывода
call OutMess;выводим сообщение
xor di,di;сбрасываем аккумуятор введенного числа
mov bx,16;система счисления
GData:
;
;считываем символ с клавиатуры
;
;Int 16/AH=00h
;KEYBOARD - GET KEYSTROKE
;Return:
;AH = BIOS scan code
;AL = ASCII character
GN0:
xor ax,ax
int 16h
cmp al,13;клавиша ENTER
jz GN3
cmp al,'0'
jb GN0
cmp al,'9'
jbe GN1
cmp al,'A'
jb GN0
cmp al,'F'
ja GN0
GN1:
push ax
mov ah,0Eh
mov bx,07
int 10h
pop ax
cmp al,'9';доп.проверка на НЕХТ код
jbe GN2
sub al,7;коррекция числа
GN2:
and ax,0fh;получаем цифру
xchg di,ax;меняем местами аккумулятор и введенное число
xor dx,dx;сбрасываем старший регистр результата
mul bx;умножаем на систему счисления
add di,ax;суммируем в аккумуляторе новое число
jmp short GN0
GN3:
mov ax,di
ret
;
;получаем текущее время
GetTime:
;
;Int 1A/AH=02h
;GET REAL-TIME CLOCK TIME
;return:
;CF clear if successful
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
;CF set on error (i.e. clock not running or in middle of update)
mov ah,02h;вызываем функцию BIOS
int 1Ah
mov [oldTime_H],ch;запоминаем значение часов
;
mov al,cl;начинаем с минут
call BCD2ASCII;переводим BCD число в символ ASCII
mov [l_min],al;запоминаем минуты
mov [h_min],ah;запоминаем десятки минут
;
mov al,dh;теперь секунды
call BCD2ASCII;см. выше
mov [l_sec],al
mov [h_sec],ah
;
mov si,message;сообщение о текущум времени в минутах и секундах
mov al,20h;начальный пробел
call OutMess;выводим сообщение
ret;возврат из п/программы
;
;переводим BCD число в символ ASCII
BCD2ASCII:
mov ah,al;зоапминаем младшую часть числа
shr al,4;сдвигаем старшую часть числа
call Num2Char;вызываем п/пограмму
xchg ah,al;меняем местами старшую и младшую части числа
;
Num2Char:
and al,0Fh;выделяем цифру
or al,30h;переводим в символ ASCII
ret;возврат из п/программы
;
;вывод сообщения как Си-строки
OutMess:
;см. выше
mov ah,0Eh;вызываем функцию BIOS
mov bx,07h
int 10h
lodsb;считываем символ
or al,al;проверяем на нулевое значение
jnz OutMess;не ноль-переходим
ret;возврат из п/программы
;
;данные программы
dbMinutes db 10,13,'Enter minutes:',0
dbSeconds db 10,13,'Enter seconds:',0
message db 10,13,'Time '
h_min db ?
l_min db ?,':'
h_sec db ?
l_sec db ?,0
oldTime_H db ?
oldTime_M db ?
;jmp 0x0000:0x8000
times 510-$+$$ db 0
sign dw 0xAA55
times 512-$+$$ db 0
[/code]
Неизвестный
04.05.2013, 14:42
общий
Есть ли какой-нибудь отладчик, чтобы можно было пошагово контролировать изменения значения регистров. У меня только компилятором FASM и программой записи на флешку. Это первая программа на х86. Тяжело пока без отладчика представлять что происходит с регистрами
давно
Старший Модератор
31795
6196
04.05.2013, 19:31
общий
04.05.2013, 19:32
mov bx,16;система счисления
mov bx,07


В коде меняется система счисления. Единственный выход использовать ещё не используемый регистр SI как указатель системы счисления, для этого нужно заменить его в строках:
mov bx,16
mul bx



Отладчик в WINXP -debug.exe, запускается так(важные команды помечены):

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

давно
Старший Модератор
31795
6196
04.05.2013, 20:02
общий
04.05.2013, 20:02
получилось?

Обратите внимание на параметры команды LOAD, я загружал без них, а код под 0х0000:0х7С00.
Можно сгенерировать простой СОМ-файл и тестировать без различных условий
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
04.05.2013, 20:20
общий
04.05.2013, 22:40
Теперь не вижу что ввожу, но те же результаты... Ниже сам код подпрограммы

[code h=200]
GetData:
mov al,20h;пробел для вывода
call OutMess;выводим сообщение
xor di,di;сбрасываем аккумуятор введенного числа
mov bx,16;система счисления
GData:
GN0:
xor ax,ax
int 16h
cmp al,13;клавиша ENTER
jz GN3
cmp al,'0'
jb GN0
cmp al,'9'
jbe GN1
cmp al,'A'
jb GN0
cmp al,'F'
ja GN0
GN1:
push ax
mov ah,0Eh
; mov bx,07
mul bx
int 10h
pop ax
cmp al,'9';доп.проверка на НЕХТ код
jbe GN2
sub al,7;коррекция числа
GN2:
and ax,0fh;получаем цифру
xchg di,ax;меняем местами аккумулятор и введенное число
xor dx,dx;сбрасываем старший регистр результата
mul bx;умножаем на систему счисления
add di,ax;суммируем в аккумуляторе новое число
jmp short GN0
GN3:
mov ax,di
ret
[/code]
давно
Старший Модератор
31795
6196
04.05.2013, 23:21
общий
05.05.2013, 00:07
Цитата: 396816
но те же результаты... Ниже сам код подпрограммы

Цитата: Зенченко Константин Николаевич
mov bx,16;система счисления
mov bx,07


В коде меняется система счисления. Единственный выход использовать ещё не используемый регистр SI как указатель системы счисления, для этого нужно заменить его в строках:
mov bx,16
mul bx

Вы меня несколько не правильно поняли, входной параметр-регистр функции
Код:
   mov   ah,0Eh
mov bx,07;--------------
int 10h

Мы поменять не можем, т.к. он стандартный и не нами придуман. А вот использовать в качестве системы счисления другой регистр мы можем, я предлагал SI в каких строках его нужно было менять. Сейчас исправленный Ваш код с моим предложением ниже:

[code h=200]USE16
org 0x7C00
start:
;адресуем сегментные регистры данных и стека
push cs
push cs
push cs
pop ds
pop es;в программе не используется, так за компанию
pop ss
mov sp,7C00h
;
;Int 10/AH=00h
;SET VIDEO MODE
;AH = 00h
;AL = desired video mode
;необязательно, т.к. монитор уже находится в текстовом режиме
mov ax,3h;вызываем функцию BIOS
int 10h;так для приличия
;начало программы
call GetTime;выводим текущее время
;
mov si,dbMinutes;сообщение о вводе минут
call GetData;вводим значение минут
mov [oldTime_M],al;запоминаем значение введенных минут
mov si,dbSeconds;сообщение о вводе секунд
call GetData;вводим значение секунд
mov dh,al;запоминаем секунды в регистре
;
;записываем новое значение минут и секунд
;
;Int 1A/AH=03h
;SET REAL-TIME CLOCK TIME
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
mov ch,[oldTime_H];востанавливаем старое значение часов
mov cl,[oldTime_M];востанавливаем новое значение минут
mov ah,03h;вызываем функцию BIOS
int 1Ah
;выводим новое время
call GetTime
;передаем упраление BIOS
int 18h
;Подпрограммы:
;
;ввод числа
GetData:
mov al,20h;пробел для вывода
call OutMess;выводим сообщение
xor di,di;сбрасываем аккумуятор введенного числа
mov si,16;система счисления
GData:
;
;считываем символ с клавиатуры
;
;Int 16/AH=00h
;KEYBOARD - GET KEYSTROKE
;Return:
;AH = BIOS scan code
;AL = ASCII character
GN0:
xor ax,ax
int 16h
cmp al,13;клавиша ENTER
jz GN3
cmp al,'0'
jb GN0
cmp al,'9'
jbe GN1
cmp al,'A'
jb GN0
cmp al,'F'
ja GN0
GN1:
push ax
mov ah,0Eh
mov bx,07
int 10h
pop ax
cmp al,'9';доп.проверка на НЕХТ код
jbe GN2
sub al,7;коррекция числа
GN2:
and ax,0fh;получаем цифру
xchg di,ax;меняем местами аккумулятор и введенное число
xor dx,dx;сбрасываем старший регистр результата
mul si;умножаем на систему счисления
add di,ax;суммируем в аккумуляторе новое число
jmp short GN0
GN3:
mov ax,di
ret
;
;получаем текущее время
GetTime:
;
;Int 1A/AH=02h
;GET REAL-TIME CLOCK TIME
;return:
;CF clear if successful
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
;CF set on error (i.e. clock not running or in middle of update)
mov ah,02h;вызываем функцию BIOS
int 1Ah
mov [oldTime_H],ch;запоминаем значение часов
;
mov al,cl;начинаем с минут
call BCD2ASCII;переводим BCD число в символ ASCII
mov [l_min],al;запоминаем минуты
mov [h_min],ah;запоминаем десятки минут
;
mov al,dh;теперь секунды
call BCD2ASCII;см. выше
mov [l_sec],al
mov [h_sec],ah
;
mov si,message;сообщение о текущум времени в минутах и секундах
mov al,20h;начальный пробел
call OutMess;выводим сообщение
ret;возврат из п/программы
;
;переводим BCD число в символ ASCII
BCD2ASCII:
mov ah,al;зоапминаем младшую часть числа
shr al,4;сдвигаем старшую часть числа
call Num2Char;вызываем п/пограмму
xchg ah,al;меняем местами старшую и младшую части числа
;
Num2Char:
and al,0Fh;выделяем цифру
or al,30h;переводим в символ ASCII
ret;возврат из п/программы
;
;вывод сообщения как Си-строки
OutMess:
;см. выше
mov ah,0Eh;вызываем функцию BIOS
mov bx,07h
int 10h
lodsb;считываем символ
or al,al;проверяем на нулевое значение
jnz OutMess;не ноль-переходим
ret;возврат из п/программы
;
;данные программы
dbMinutes db 10,13,'Enter minutes:',0
dbSeconds db 10,13,'Enter seconds:',0
message db 10,13,'Time '
h_min db ?
l_min db ?,':'
h_sec db ?
l_sec db ?,0
oldTime_H db ?
oldTime_M db ?
;jmp 0x0000:0x8000
times 510-$+$$ db 0
sign dw 0xAA55
times 512-$+$$ db 0[/code]


Цитата: 396816
Теперь не вижу что ввожу

Это основная беда дебугеров реального времени.
Начинайте обрастать полезными ссылками, к примеру как эта Всякая всячина, но есть и кое-что полезное... В составе пакета Turbo Assembler 4.1 есть программка TD(Turbo Debuger). Проблема останется(ввод данных на экране дебугера), но засчет световой разкраски самого дебугера Вы свои вводимые данные увидете на черных полях.


Можно ещё какбы эмулировать вводимые значения задавая нужные значения и проверять порегистровую обработку.



ps:Смотрите над полем ввода сообщений есть есть выпадающий список"КОМУ", адресуйте сообщения мне.

Лысков Игорь Витальевич, как администратор рассылки получает уведомления о всех сообщениях(именные и безимянные) в его рассылках, а также сами безимянные. Т.е. о Ваших сообщениях он узнает дважды.

и ещё в теге [ cоde ][ /code ] добавляйте параметр h=200 или 300, т.е примерно так [ cоde h=200] [ /code ] тогда, чтобы добратся до последнего сообщения не нужно проматывать долго всесь экран.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
04.05.2013, 23:54
общий
05.05.2013, 00:02
На скорую руку могу предложить ещё один отладчик из пакета masm611-613.zip (6.15 Mб), скачайте и установите его, на все вопросы отвечайте "ДА",Вам нужно будет только указать путь к папке BIN, уменя сейчас на этом РС такой адрес D:\Cat\Lang\MASM61\BIN(синим мои дополнения от стандартного запроса), в конце появится список установки, выбираете без изменений и всё.
отладчик CV.EXE(CodeView)
ps: с MASM'om и TASM'om работать нужно из командной строки.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
05.05.2013, 00:20
общий
05.05.2013, 00:21
Адресаты:
Теперь вижу что ввожу, но работает все же неправильно... Ввожу А минут и 1А секунд, по идее, должен после ввода вывести 10 минут и 26 секунд, а показывает 0 минут и 0; секунд... Может надо переводить в BCD?

Попробую этот отладчик, спасибо!
давно
Старший Модератор
31795
6196
05.05.2013, 00:37
общий
05.05.2013, 00:54
Цитата: 396816
Может надо переводить в BCD?

Цитата: Зенченко Константин Николаевич
Введение такого кода заставляет дополнительно заниматся подготовкой данных для функции BIOS, т.к. там на входе должен быть BCD-код.

Да, к примеру так, сразу предупреждаю, писалось без проверки:
Код:
hext2BCD:
;input: ax HEXT code
;output: ax BCD code
xor cx,cx
mov si,10;тут была ошибка: 10 а не 16
H2B: xor dx,dx
div si
inc cx
push dx
or ax,ax
jnz H2B
;
;
B2H:
shl ax,4
pop dx
or ax,dx
loop B2H
ret

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

давно
Старший Модератор
31795
6196
05.05.2013, 01:17
общий
Вот ещё один DOS отладчик: Отладчик AFD Pro
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
05.05.2013, 01:27
общий
Адресаты:
Спасибо большое! Все, наконец, заработало. Осталось только разобраться что к чему.
Если писать ту же программу, но в защищенном режиме, то программа сильно будет отличаться?
давно
Старший Модератор
31795
6196
05.05.2013, 01:45
общий
Конечно.
Если условия останутся теже(запускать с дискеты, флешки и т.д.) то практически это будет полноценная ОСь.
1)переход из реального в защиту (настройка GDT, LDT и т.д.), изменяется адресация физической памяти-страничная
2)работа на уровне портов с железом, т.е. для всего Вам нужно будет писать исключения, даже для таймера часов.
3)сам защищенный режим в литературе описан плохо, в различных книгах встречаются примеры построенные по одной схеме: реальный режим - подготовка - "приг в защиту", что-то сделали, "приг обратно". Более длительное нахождение в "защите" описано в книгах по ОСям, но как теория без конкретики.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
05.05.2013, 14:51
общий
это ответ
Здравствуйте, Игорь!

В приложении компиляция ответа из мини-форума.
Удачи!

Приложение:
USE16
org 0x7C00
start:
;адресуем сегментные регистры данных и стека
push cs
push cs
push cs
pop ds
pop es;в программе не используется, так за компанию
pop ss
mov sp,7C00h
;
;Int 10/AH=00h
;SET VIDEO MODE
;AH = 00h
;AL = desired video mode
;необязательно, т.к. монитор уже находится в текстовом режиме
mov ax,3h;вызываем функцию BIOS
int 10h;так для приличия
;начало программы
call GetTime;выводим текущее время
;
mov si,dbMinutes;сообщение о вводе минут
call GetData;вводим значение минут
mov [oldTime_M],al;запоминаем значение введенных минут
mov si,dbSeconds;сообщение о вводе секунд
call GetData;вводим значение секунд
mov dh,al;запоминаем секунды в регистре
;
;записываем новое значение минут и секунд
;
;Int 1A/AH=03h
;SET REAL-TIME CLOCK TIME
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
mov ch,[oldTime_H];востанавливаем старое значение часов
mov cl,[oldTime_M];востанавливаем новое значение минут
mov ah,03h;вызываем функцию BIOS
int 1Ah
;выводим новое время
call GetTime
;передаем упраление BIOS
int 18h
;Подпрограммы:
;
;ввод числа
GetData:
mov al,20h;пробел для вывода
call OutMess;выводим сообщение
xor di,di;сбрасываем аккумуятор введенного числа
mov si,16;система счисления
GData:
;
;считываем символ с клавиатуры
;
;Int 16/AH=00h
;KEYBOARD - GET KEYSTROKE
;Return:
;AH = BIOS scan code
;AL = ASCII character
GN0:
xor ax,ax
int 16h
cmp al,13;клавиша ENTER
jz GN3
cmp al,'0'
jb GN0
cmp al,'9'
jbe GN1
cmp al,'A'
jb GN0
cmp al,'F'
ja GN0
GN1:
push ax
mov ah,0Eh
mov bx,07
int 10h
pop ax
cmp al,'9';доп.проверка на НЕХТ код
jbe GN2
sub al,7;коррекция числа
GN2:
and ax,0fh;получаем цифру
xchg di,ax;меняем местами аккумулятор и введенное число
xor dx,dx;сбрасываем старший регистр результата
mul si;умножаем на систему счисления
add di,ax;суммируем в аккумуляторе новое число
jmp short GN0
GN3:
mov ax,di
mov si,10;система счисления
xor cx,cx:счетчик цифр
GN4:
xor dx,dx
div si;получаем последнюю цифру
push dx;сохраняем её в стеке
inc cx;увеличиваем счетчик цифр числа
or ax,ax;пока не ноль
jnz GN4
GN5:
shl ax,4:сдвигаем на 4-е позиции
pop dx;востанавливаем из стека
or ax,dx;"суммируем"
loop GN5;пока есть цифры
ret
;
;получаем текущее время
GetTime:
;
;Int 1A/AH=02h
;GET REAL-TIME CLOCK TIME
;return:
;CF clear if successful
;CH = hour (BCD)
;CL = minutes (BCD)
;DH = seconds (BCD)
;DL = daylight savings flag (00h standard time, 01h daylight time)
;CF set on error (i.e. clock not running or in middle of update)
mov ah,02h;вызываем функцию BIOS
int 1Ah
mov [oldTime_H],ch;запоминаем значение часов
;
mov al,cl;начинаем с минут
call BCD2ASCII;переводим BCD число в символ ASCII
mov [l_min],al;запоминаем минуты
mov [h_min],ah;запоминаем десятки минут
;
mov al,dh;теперь секунды
call BCD2ASCII;см. выше
mov [l_sec],al
mov [h_sec],ah
;
mov si,message;сообщение о текущум времени в минутах и секундах
mov al,20h;начальный пробел
call OutMess;выводим сообщение
ret;возврат из п/программы
;
;переводим BCD число в символ ASCII
BCD2ASCII:
mov ah,al;зоапминаем младшую часть числа
shr al,4;сдвигаем старшую часть числа
call Num2Char;вызываем п/пограмму
xchg ah,al;меняем местами старшую и младшую части числа
;
Num2Char:
and al,0Fh;выделяем цифру
or al,30h;переводим в символ ASCII
ret;возврат из п/программы
;
;вывод сообщения как Си-строки
OutMess:
;см. выше
mov ah,0Eh;вызываем функцию BIOS
mov bx,07h
int 10h
lodsb;считываем символ
or al,al;проверяем на нулевое значение
jnz OutMess;не ноль-переходим
ret;возврат из п/программы
;
;данные программы
dbMinutes db 10,13,'Enter minutes:',0
dbSeconds db 10,13,'Enter seconds:',0
message db 10,13,'Time '
h_min db ?
l_min db ?,':'
h_sec db ?
l_sec db ?,0
oldTime_H db ?
oldTime_M db ?
times 510-$+$$ db 0
sign dw 0xAA55
times 512-$+$$ db 0
5
Спасибо за помощь! Можно многому научиться
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Форма ответа