Загрузка данных из другого сегмента
Простое чтение файла:
mov ax,3d00h ; ah - 3dh; al - 00 (for reading)
mov dx,file_name
int 21h
jc err_exit
mov [handle16],ax
; читаем через описатель
mov ah,3fh
mov bx,[handle16]
mov dx,adress
mov cx,87 ; 87 байт
int 21h
cmp ax,cx
jne err_exit
; вывод содержимого файла
mov ah,9h
mov dx,adress
int 21h
int 20h
err_exit:
int 20h
handle16 dw 0x00
filename db 'myfile.dat',0
adress:
Все прекрасно работает, но только в этом сегменте. Я хочу загрузить файл размером 64 Кб в другой сегмент (т.е. не тот где сейчас код) и так как в функции 3fh запись файла происходит в буфер по адресу DS: DX, то по идеи чтобы загрузить в этот семент файл то стоит написать так:
; читаем через описатель
push ds ; сохраним сегмент данных
mov ax,0xD000 ; в этот сегмент загрузим файл
mov ds,ax
mov ah,3fh
mov bx,[handle16]
mov dx,0 ; со смещением 0
; т.е. по сути данные из файла будут располагаться по адресу D000h:0000h, или я не прав?
mov cx,87 ; 87 байт
int 21h
pop ds ; возвратим ds на кодовый сегмент
cmp ax,cx
jne err_exit
А теперь я хочу вывести текст, который находится по адресу D000h:0000h на экран. Т.е. это будет выглядеть так:
mov ax,0xD000
mov ds,ax
mov ah,9h
mov dx,0
int 21h
Если не менять ds вообще в программе - то все работает нормально, файл загружается, после чего той же функцией 9й выводится на экран.
Т.е. когда файл и код в одном сегменте - то все нормально.
А если добавить то что выделено жирным шрифтом - то программа выводит черт знает что, и вообще не разберешь файл загрузился по этому адресу или нет.
И вообще, зачем регистру ds знать где находятся данные, ведь программист всегда сделает так:
......
code
......
jmp next_code
data1 db 'asdasd',0
data2....
data3....
next_code:
.....
code
......
Или это нужно для того чтобы загружать в кеш только код, а не все подряд?
И как в фасме будет выглядеть конструкция типа
.DATA
........
.CODE
mov ax,@data
mov ds,ax
Вариант в фасме типа
dataSEG:
.....bla bla...
codeSEG:
mov ax,dataSEG
mov ds,ax
Не катит - пробовал
код комовской проги :
org 100h ; code starts at offset 100h
use16 ; use 16-bit code
display_text = 9
mov ah,display_text
mov dx,hello
int 21h
int 20h
hello db 'Hello world!',24h
код экзешной проги :
format MZ
push cs
pop ds
mov ah,9
mov dx,hello
int 21h
mov ax,4C00h
int 21h
hello db 'Hello world!',24h
Потому что данные из файла я хочу загрузить в другой сегмент (не в тот где сейчас находится программа) а в другой, так как файл будет занимать ровно 64Кб (в размер сегмента). Вот я и хочу поместить его в свободный сегмент. По таблице с физического адреса 0xD0000 начинаются свободные адреса.
Возможно файл будет занимать и больше чем 64Кб, тогда его прийдется загружать в несколько сегментов по частям. Вопрос: как записать данные в 1,2,3,10 и т.д. сегменты?
Физическая память идёт до адреса 0x9FFFF и после 0x100000 (не доступно из обычного реального режима). А память 0xA0000 - 0xFFFFF - видео буфер, BIOS, и просто отсутствующие участки памяти. Причём всё кроме видео буфера (0xA0000 - 0xBFFFF, кажется, с верхней границенй могу ошибаться) доступно только как ReadOnly и чтение туда файла ни к чему не приводит. А вообще нежелательно самому выделять память в DOS. Ведь эта память может быть уже выделенна под другое и её изменение приведёт к нестабильной работе системы. Лучше для этого использовать функции DOS для выделения/освобождения блоков памяти.
А как быть в БИОСе ?
Неужели загруженные файлы хранить, не дай Бог, в видеопамяти? Ведь все остальное ReadOnly..
Что значит в BIOS? Это когда нет ОС? Тогда варианта два: либо писать свой менеджер памяти, либо использовать фиксированный адрес (я говорил что этот вариант не приемлем в DOS, но без оськи он вполне подходит, только делайте адрес выше 0x400 и ниже 0x9FFFF). Но учтите, что в BIOS нет не только функций работы с памятью, но и функций работы с файлами (только с секторами диска), поэтому драйвер файловой системы придётся писать самому.
Повторюсь - задачей является загрузка файла (средствами функций ДОС 3dh и 3fh) в память в свободный сегмент памяти, и вывод всего текста из файла на экран (именно из свободного, отдельного от кода, сегмента).
Ну вот проблемы следующие:
1) Функция 48h - распределить память. Т.е. я задаю размер памяти требуемый, функция возвращает сегментный адрес свободного блока...
Но стоит только затребовать больше 7 параграфов, то сразу carry устанавливается в 1 и ошибка... А 7 параграфов по 16 байт это 112 байт. Это что размер свободной памяти?
2) Даже с этими 7ю параграфами программа не хочет работать. Как будто бы издевается надо мной. То выводит какую то фигню на экран, то пишет error потому что cx считанных байт не совпадают с запрошенным ax байтами, то еще что то.. Уже честно, нет сил... Опять сегодня ложусь в пол второго ночи...Блин!))) А из за такой фигни))
Если кому не лень, посоветуйте что нибудь, подправьте или ткните носом куда надо, либо кодом, что нибудь. Заранее спасибо..
Код только кажется большим, на самом деле он простой, и понятный.
вот:
mov ah,48h ;нoмep функции
mov bx,7 ;тpeбуeм 7 пapaгpaфов, если больше 7 - то ошибка :(((((
int 21h ;пытaeмcя oтвecти блoк
jc ERROR ;oбpaбaтывaeм oшибку в cлучae нeудaчи
mov [BLOCK_SEG],AX;инaчe coxpaняeм aдpec блoкa
;---ocвoбoждaeм тoт жe блoк
MOV AX,[BLOCK_SEG] ;пoлучaeм cтapтoвый aдpec блoкa
MOV ES,AX ;пoмeщaeм eгo в ES
MOV AH,49H ;нoмep тpeбуeмoй функции
INT 21H ;ocвoбoждaeм блoк пaмяти
; ------ OPEN FILE --------
mov ax,3d00h ; ah - 3dh; al - 00 (for reading)
mov dx,filename
int 21h
jc ERROR
mov [handle16],ax
; ----- GET DATA FROM HANDLE
mov ax,[BLOCK_SEG]
mov ds,ax ; занесем данные в освобожденный сегмент
mov ah,3fh
mov bx,[handle16]
xor dx,dx ; DS:0000
mov cx,87 ; 87 bytes (мой файл размером в 87байт)
int 21h
cmp ax,cx ; обработаем ошибку
jne ERROR
; ----- CLOSE FILE -----
mov ah,3eh
mov bx,[handle16]
int 21h
; ------ WRITING MESSAGE -----
; выведем загруженный текстовый файл на экран (файл в сегменте DS:0000)
push [BLOCK_SEG]
pop ds ; указателем на адрес строки служит DS:DX
mov dx,0
mov ah,9h
int 21h
; WAIT AND EXIT ; Ожидание и выход
xor ah,ah
int 16h
int 20h
filename db 'maph.dat',0
c_err db 'error$'
BLOCK_SEG dw 0x00
handle16 dw 0x00
; Выведем сообщение, если произошла ошибка
ERROR:
push cs
pop ds
mov ah,9h
mov dx,c_err
int 21h
xor ah,ah
int 16h
int 20h
P.S. И что значит "Вы должны добавить отзыв кому то еще, прежде чем добавить его KIV?"
KIV, почему я тебе не могу "+" поставить?
KIV, почему я тебе не могу "+" поставить?
Это защита от накруток. Знапчит вы мне недавно отзыв отправили. Нодо поблогодарить кого то ещё (не просто так размеется)...
P.S. Сейчас посмортрю код и попробую помочь.
Освобождать память нужно после использования, а не перед.
mov ah,48h ;нoмep функции
mov bx,7 ;тpeбуeм 7 пapaгpaфов, если больше 7 - то ошибка :(((((
int 21h ;пытaeмcя oтвecти блoк
jc ERROR ;oбpaбaтывaeм oшибку в cлучae нeудaчи
mov [BLOCK_SEG],AX;инaчe coxpaняeм aдpec блoкa
; ------ OPEN FILE --------
mov ax,3d00h ; ah - 3dh; al - 00 (for reading)
mov dx,filename
int 21h
jc ERROR
mov [handle16],ax
; ----- GET DATA FROM HANDLE
mov ax,[BLOCK_SEG]
mov ds,ax ; занесем данные в освобожденный сегмент
mov ah,3fh
mov bx,[handle16]
xor dx,dx ; DS:0000
mov cx,87 ; 87 bytes (мой файл размером в 87байт)
int 21h
cmp ax,cx ; обработаем ошибку
jne ERROR
; ----- CLOSE FILE -----
mov ah,3eh
mov bx,[handle16]
int 21h
; ------ WRITING MESSAGE -----
; выведем загруженный текстовый файл на экран (файл в сегменте DS:0000)
push [BLOCK_SEG]
pop ds ; указателем на адрес строки служит DS:DX
mov dx,0
mov ah,9h
int 21h
;---ocвoбoждaeм тoт жe блoк
MOV AX,[BLOCK_SEG] ;пoлучaeм cтapтoвый aдpec блoкa
MOV ES,AX ;пoмeщaeм eгo в ES
MOV AH,49H ;нoмep тpeбуeмoй функции
INT 21H ;ocвoбoждaeм блoк пaмяти
; WAIT AND EXIT ; Ожидание и выход
xor ah,ah
int 16h
int 20h
filename db 'maph.dat',0
c_err db 'error$'
BLOCK_SEG dw 0x00
handle16 dw 0x00
; Выведем сообщение, если произошла ошибка
ERROR:
push cs
pop ds
mov ah,9h
mov dx,c_err
int 21h
xor ah,ah
int 16h
int 20h
Как после? я так понимаю необходимо очистить сегмент полностью чтобы в него записать какие то данные... значит надо перед..
Хех) А программа все равно не работает... по видимому сегмент освобождается, и 48 функция делает свое дело.. но вот что касается загрузки файла туда...
; ----- GET DATA FROM HANDLE
mov ax,[BLOCK_SEG]
mov ds,ax ; занесем данные в освобожденный сегмент
Проблема в этом... Если в ds загрузить кодовый сегмент - то все нормально, файл загружается в кодовый сегмент.. но мне то нужно в полностью свободный.. И когда загружаешь в ds значение BLOCK_SEG то происходит ошибка...ax байт не совпадает с cх считанных...
P.S. Можно переформулировать мой вопрос:
Как загрузить файл (любым способом, но только в real mode) в оперативную память, который имеет размер 64Кб или более ?
для работы нужно в config.sys убрать emm*.* , а для himem.sys поставить
опции "/A20CONTROL:OFF /TESTMEM:OFF" или , если возможно, тоже убрать .
также отключи из биоса ACPI .
запускаешь flat.com , вручную или через autoexec.bat , и можешь пользовать всю верхнюю память как угодно . для варианта с himem.sys начиная с 64 мегабайта , а для варианта без himem.sys начиная со 2-го .
Только вот неразобравшись с сегментами идти мне дальше будет как то неправильно...
Вот разберусь и пойду дальше..
А вариант супер! +1