0x00000 - 0x003FF - таблица прерываний
0x00400 - 0x005FF - Область данных BIOS
0x00600 - 0x9FFFF - доступно для вас
0xA0000 - 0xAFFFF - графический видео-буфер
0xB0000 - 0xBFFFF - текстовый видео-буфер
0xC0000 - 0xEFFFF - видео-BIOS и всякие другие расширения BIOS
0xF0000 - 0xFFFFF - основной BIOS
Загрузочный сектор
У вашего покорного слуги возникла проблема следующего характера. Имеется дискета с двумя записанными секторами: загрузочный сектор содержит бинарник, который, в свою очередь, должен загружать содержимое следующего сектора в ОЗУ. Также имеется чистая виртуальная машина без какой бы то ни было ОС.
Вопрос такой: какую структуру по адресам имеет оперативка и куда в нее с дискеты можно прочитать сектор, чтобы передать впоследствии управление на загруженный код?
В качестве бинарников используются COM-программы, собираемые TASM+TLINK. Запись бинарников в секторы дискет производится при помощи самодельной программы на С++ с использованием API-процедур.
загрузочный сектор загружается в 0:7С00, а куда он загрузит второй сектор - нужно уже в нём смотреть
Код:
Адреса 0xC0000 - 0xFFFFF недоступны для записи.
Уже неоднократно было сказано, что под границей 0xA0000 присутствует область EBDA, данные которой разрушать крайне нежелательно. Да и вообще более профессиональным подходом будет определение вершины доступной базовой памяти с помощью сервиса BIOS, например, int 12h. Базовую память можно использовать, начиная с адреса 0x500, без риска повредить данные BIOS. Кто не согласен, пусть аргументируют свое мнение.
Цитата: KIV
не забудь поставить в коде загрузчика директиву org 0x7C00.
компилятор TASM запрещает транслировать COM-программу со смещением, отличным от 100h. Можно ли еще каким-то образом при помощи tasm + tlink собрать бинарник без заголовков?
Phantom-84, спасибо за рекомендацию, воспользуюсь int 12h.
Проблема заключается в том, что по какому бы я адресу в оперативку ни копировал кусочек кода (пробовал в том числе и 0000:0600h), VMWare пишет "Operating system not found" :(. Дискета смонтирована правильно, секторы записаны правильно.
Цитата:
Да и вообще более профессиональным подходом будет определение вершины доступной базовой памяти с помощью сервиса BIOS, например, int 12h
Какой вероятность сегодня, что у компьютера окажется меньше 640 КБ оперативки?
Цитата:
VMWare пишет "Operating system not found"
Может быть вы забыли в конце загрузочного сектора поставить сигнатуру 0x55,0xAA?
Проблема была не в последних двух байтах, они-то, как раз, были выставлены правильно.
В качестве компилятора, решившего все вопросы, использовал FASM 1.68. К моей великой радости, он позволяет собирать .asm исходник в бинарник .bin со смещением, отличным от 100h.
Целесообразности в применении сервисов для определения верхней границы памяти я пока не увидел. Всё остальное оказалось совсем просто. Ниже исходники обоих модулей и программы, записывающей их на дискету.
start.asm
Код:
org 7C00h
use16
jmp Main
nop
db 'bootsect' ; имя загрузочного сектора
SectSize dw 0200h ; количество байт в секторе
ClustSize db 01h ; количество секторов в кластере
ResSects dw 0001h ; число резервных секторов
FatCnt db 02h ; число таблиц FAT
RootSiz dw 00E0h
TotSecs dw 0B40h ; общее число секторов
Media db 0F0h ; media-дескриптор
FatSize dw 0009h ; число секторов в одной FAT
TrkSecs dw 0012h ; секторов на дорожку
HeadCnt dw 0002h ; число головок чтения/записи
HidnSec dw 0000h ; число скрытых секторов
Main:
cli
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0FFFCh
sti
; смещение, по которому загрузим в оперативку следующий кусок
mov bx, 600h
; читать с диска A:
mov dl, 0h
; головка #0
mov dh, 0h
; цилиндр #0
mov ch, 0
; сектор #2
mov cl, 2
; количество секторов, которые надо прочитать - 1
mov al, 1
mov ah, 2
int 13h
jmp 600h
use16
jmp Main
nop
db 'bootsect' ; имя загрузочного сектора
SectSize dw 0200h ; количество байт в секторе
ClustSize db 01h ; количество секторов в кластере
ResSects dw 0001h ; число резервных секторов
FatCnt db 02h ; число таблиц FAT
RootSiz dw 00E0h
TotSecs dw 0B40h ; общее число секторов
Media db 0F0h ; media-дескриптор
FatSize dw 0009h ; число секторов в одной FAT
TrkSecs dw 0012h ; секторов на дорожку
HeadCnt dw 0002h ; число головок чтения/записи
HidnSec dw 0000h ; число скрытых секторов
Main:
cli
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0FFFCh
sti
; смещение, по которому загрузим в оперативку следующий кусок
mov bx, 600h
; читать с диска A:
mov dl, 0h
; головка #0
mov dh, 0h
; цилиндр #0
mov ch, 0
; сектор #2
mov cl, 2
; количество секторов, которые надо прочитать - 1
mov al, 1
mov ah, 2
int 13h
jmp 600h
btldr.asm
Код:
org 600h
use16
Btldr:
; получить позицию курсора на экране
xor ax, ax
mov ah, 03h
xor bx, bx
int 10h
; вывести строчку
mov cx, EndMsg
sub cx, Msg
mov bx, 002fh
mov bp, Msg
mov ax, 1301h
int 10h
LoopEnd:
jmp LoopEnd
Msg db 'Hello from RAM!'
EndMsg:
use16
Btldr:
; получить позицию курсора на экране
xor ax, ax
mov ah, 03h
xor bx, bx
int 10h
; вывести строчку
mov cx, EndMsg
sub cx, Msg
mov bx, 002fh
mov bp, Msg
mov ax, 1301h
int 10h
LoopEnd:
jmp LoopEnd
Msg db 'Hello from RAM!'
EndMsg:
bootsector.cpp
Код:
//---------------------------------------------------------------------------
#pragma hdrstop
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
//---------------------------------------------------------------------------
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
FILE *file;
const int len = 512;
char buf[len];
unsigned long n = 0;
// открыть дискету на запись
printf("Trying to open floppy disk... ");
HANDLE disk = CreateFile("\\\\.\\A:",
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (disk == INVALID_HANDLE_VALUE)
{
printf("Failed to open floppy disk!");
return 1;
}
printf("Disk is opened successfully!\n");
// открыть файл стартера на чтение
printf("Trying to open starter.bin...\n");
file = fopen("start.bin", "rb");
if (!file)
{
printf("Error reading from starter.bin!\n");
return 1;
}
// прочитать стартер в буфер (510 байт max)
printf("File is opened successfully! Reading starter.bin...\n");
fread(buf, sizeof(char), len - 2, file);
fclose(file);
// последние два байта сектора
buf[510] = 0x55;
buf[511] = 0xaa;
// записать starter.bin в загрузочный сектор
if (!WriteFile(disk, buf, len, &n, NULL))
{
printf("Error writing starter.com to disk!");
return 1;
}
// прочитать загрузчик в буфер (max 510 байт)
printf("Trying to open btldr.bin...\n");
file = fopen("btldr.bin", "rb");
if (!file)
{
printf("Error reading from btldr.bin!\n");
return 1;
}
fread(buf, sizeof(char), len - 2, file);
fclose(file);
if (!WriteFile(disk, buf, len, &n, NULL))
{
printf("Error writing btldr.bin to disk!");
return 1;
}
CloseHandle(disk);
printf("All operations completed successfully!");
return 0;
}
//---------------------------------------------------------------------------
#pragma hdrstop
#include <tchar.h>
#include <stdio.h>
#include <windows.h>
//---------------------------------------------------------------------------
#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
FILE *file;
const int len = 512;
char buf[len];
unsigned long n = 0;
// открыть дискету на запись
printf("Trying to open floppy disk... ");
HANDLE disk = CreateFile("\\\\.\\A:",
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (disk == INVALID_HANDLE_VALUE)
{
printf("Failed to open floppy disk!");
return 1;
}
printf("Disk is opened successfully!\n");
// открыть файл стартера на чтение
printf("Trying to open starter.bin...\n");
file = fopen("start.bin", "rb");
if (!file)
{
printf("Error reading from starter.bin!\n");
return 1;
}
// прочитать стартер в буфер (510 байт max)
printf("File is opened successfully! Reading starter.bin...\n");
fread(buf, sizeof(char), len - 2, file);
fclose(file);
// последние два байта сектора
buf[510] = 0x55;
buf[511] = 0xaa;
// записать starter.bin в загрузочный сектор
if (!WriteFile(disk, buf, len, &n, NULL))
{
printf("Error writing starter.com to disk!");
return 1;
}
// прочитать загрузчик в буфер (max 510 байт)
printf("Trying to open btldr.bin...\n");
file = fopen("btldr.bin", "rb");
if (!file)
{
printf("Error reading from btldr.bin!\n");
return 1;
}
fread(buf, sizeof(char), len - 2, file);
fclose(file);
if (!WriteFile(disk, buf, len, &n, NULL))
{
printf("Error writing btldr.bin to disk!");
return 1;
}
CloseHandle(disk);
printf("All operations completed successfully!");
return 0;
}
//---------------------------------------------------------------------------
Тему можно считать закрытой.
Цитата: Lad90
...В качестве компилятора, решившего все вопросы, использовал FASM 1.68. К моей великой радости, он позволяет собирать .asm исходник в бинарник .bin со смещением, отличным от 100h...
TASM это тоже может, просто надо присвоить выходному файлу расширение отличное от com.
Например, bin:
Код:
tasm myfile.asm
tlink /t myfile.obj,myfile.bin
tlink /t myfile.obj,myfile.bin