| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- MODULE Generator;
- IMPORT ST := SymTable, Out, Files, Chmod;
- CONST fname = "Test";
- TYPE
- Item* = RECORD
- mode*: INTEGER; (*Режим предмета, используются константы из SymTable*)
- type*: ST.Type;
- val*: INTEGER
- END;
- VAR
- F: Files.File;
- r: Files.Rider;
- PROCEDURE Byte(n: INTEGER);
- BEGIN
- Files.Write(r, CHR(n))
- END Byte;
- PROCEDURE Word(n: INTEGER);
- BEGIN
- Files.Write(r, CHR(n MOD 100H));
- Files.Write(r, CHR(n DIV 100H))
- END Word;
- PROCEDURE DWord(n: INTEGER);
- BEGIN
- Files.Write(r, CHR(n MOD 100H));
- Files.Write(r, CHR(n DIV 100H MOD 100H));
- Files.Write(r, CHR(n DIV 10000H MOD 100H));
- Files.Write(r, CHR(n DIV 1000000H))
- END DWord;
- (* Выводит в файл первые 16 байтов заголовка ELF-файла *)
- PROCEDURE WriteElfIdent;
- BEGIN
- Byte(7FH); (* Магическое значение - ASCII DEL *)
- Byte(ORD("E")); (* Магические значения - слово "ELF" *)
- Byte(ORD("L"));
- Byte(ORD("F"));
- Byte(1); (* Класс ELF-файла: 32-разрядный (бывает ещё 64) *)
- Byte(1); (* Способ кодирования данных: порядок от младшего к старшему (LSB) *)
- Byte(1); (* Версия ELF-файла: бывает только 1 *)
- Byte(0); DWord(0); DWord(0) (* Набивка: просто 9 нулевых байтов *)
- END WriteElfIdent;
- (* Выводит в файл заголовок ELF-файла *)
- PROCEDURE WriteElfHeader;
- BEGIN
- WriteElfIdent; (* Выводит первые 16 байтов *)
- Word(2); (* Тип файла: исполнимый файл (бывает ещё .o и .so) *)
- Word(3); (* Архитектура процессора: Intel 386 *)
- DWord(1); (* Версия ELF-файла (ещё раз) *)
- DWord(08040054H); (* Вход в программу. Виртуальный адрес начала исполнения *)
- DWord(52); (* Смещение на начало таблицы программных заголовков *)
- DWord(0); (* Смещение на начало таблицы секций (в исполнимом - не нужны) *)
- DWord(0); (* Флаги процессора (для Intel 386 отсутствуют) *)
- Word(52); (* Размер заголовка ELF-файла в байтах *)
- Word(32); (* Размер одного программного заголовка *)
- Word(1); (* Количество программных заголовков *)
- Word(0); (* Размер заголовка секции (в исполнимом файле они не нужны) *)
- Word(0); (* Количество заголовков секций *)
- Word(0) (* Номер секции с таблицей строк (в исполнимом файле не нужны) *)
- END WriteElfHeader;
- PROCEDURE WriteProgramHeader;
- BEGIN
- DWord(1); (* Вид данного сегмента - сегмент для загрузки *)
- DWord(54H); (* Смещение на начало данного сегмента = 84 *)
- DWord(08040054H); (* Виртуальный адрес первого байта в сегменте *)
- DWord(08040054H); (* Физический адрес - не используется !FIXME Проверить, нужен ли здесь 0 *)
- DWord(38); (* Сколько сегмент занимает в файле *)
- DWord(38); (* Сколько сегмент занимает в файле *)
- DWord(5); (* Флаги сегмента: 4 + 1 = чтение + исполнение *)
- DWord(1000H) (* Выравнивание для виртуального адреса и смещения в файле *)
- END WriteProgramHeader;
- PROCEDURE WriteTextSegment;
- BEGIN
- Byte(0B9H); (* MOV ECX, DWORD ... *)
- DWord(08040054H + 34); (* Откуда брать строку *)
- Byte(0BAH); (* MOV EDX, DWORD ... *)
- DWord(04H); (* Длина строки *)
- Byte(0BBH); (* MOV EBX, DWORD ... *)
- DWord(01H); (* Куда писать: стандартное устройство вывода STDOUT *)
- Byte(0B8H); (* MOV EAX, DWORD ... *)
- DWord(04H); (* Системный вызов: write *)
- Byte(0CDH); (* Прерывание: INT *)
- Byte(080H); (* Номер прерывания *)
- Byte(0BBH); (* MOV EBX, DWORD ... *)
- DWord(01H); (* Код возврата (exit code) *)
- Byte(0B8H); (* MOV EAX, DWORD ... *)
- DWord(01H); (* Системный вызов: exit *)
- Byte(0CDH); (* Прерывание: INT *)
- Byte(080H); (* Номер прерывания *)
- Byte(ORD("H")); (* Строка *)
- Byte(ORD("i"));
- Byte(ORD("!"));
- Byte(0AH)
- END WriteTextSegment;
- PROCEDURE WriteElf;
- BEGIN
- WriteElfHeader;
- WriteProgramHeader;
- WriteTextSegment
- END WriteElf;
- PROCEDURE WriteDummy*;
- BEGIN
- F := Files.New(fname);
- IF F # NIL THEN
- Files.Set(r, F, 0);
- WriteElf;
- Files.Register(F);
- Files.Close(F);
- IF Chmod.MakeExecutable(fname) = 0 THEN END
- ELSE
- Out.String("Не могу создать файл ");
- Out.String(fname); Out.Ln
- END
- END WriteDummy;
- PROCEDURE MakeItem*(VAR x: Item; o: ST.Object);
- BEGIN
- x.mode := o.class;
- x.type := o.type;
- x.val := o.val
- END MakeItem;
- PROCEDURE Call*(VAR x: Item);
- BEGIN
- Out.String("Вызвана процедура ");
- Out.Int(x.val, 0); Out.Ln
- END Call;
- END Generator.
|