Generator.Mod 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. MODULE Generator;
  2. IMPORT ST := SymTable, Out, Files, Chmod;
  3. CONST fname = "Test";
  4. TYPE
  5. Item* = RECORD
  6. mode*: INTEGER; (*Режим предмета, используются константы из SymTable*)
  7. type*: ST.Type;
  8. val*: INTEGER
  9. END;
  10. VAR
  11. F: Files.File;
  12. r: Files.Rider;
  13. PROCEDURE Byte(n: INTEGER);
  14. BEGIN
  15. Files.Write(r, CHR(n))
  16. END Byte;
  17. PROCEDURE Word(n: INTEGER);
  18. BEGIN
  19. Files.Write(r, CHR(n MOD 100H));
  20. Files.Write(r, CHR(n DIV 100H))
  21. END Word;
  22. PROCEDURE DWord(n: INTEGER);
  23. BEGIN
  24. Files.Write(r, CHR(n MOD 100H));
  25. Files.Write(r, CHR(n DIV 100H MOD 100H));
  26. Files.Write(r, CHR(n DIV 10000H MOD 100H));
  27. Files.Write(r, CHR(n DIV 1000000H))
  28. END DWord;
  29. (* Выводит в файл первые 16 байтов заголовка ELF-файла *)
  30. PROCEDURE WriteElfIdent;
  31. BEGIN
  32. Byte(7FH); (* Магическое значение - ASCII DEL *)
  33. Byte(ORD("E")); (* Магические значения - слово "ELF" *)
  34. Byte(ORD("L"));
  35. Byte(ORD("F"));
  36. Byte(1); (* Класс ELF-файла: 32-разрядный (бывает ещё 64) *)
  37. Byte(1); (* Способ кодирования данных: порядок от младшего к старшему (LSB) *)
  38. Byte(1); (* Версия ELF-файла: бывает только 1 *)
  39. Byte(0); DWord(0); DWord(0) (* Набивка: просто 9 нулевых байтов *)
  40. END WriteElfIdent;
  41. (* Выводит в файл заголовок ELF-файла *)
  42. PROCEDURE WriteElfHeader;
  43. BEGIN
  44. WriteElfIdent; (* Выводит первые 16 байтов *)
  45. Word(2); (* Тип файла: исполнимый файл (бывает ещё .o и .so) *)
  46. Word(3); (* Архитектура процессора: Intel 386 *)
  47. DWord(1); (* Версия ELF-файла (ещё раз) *)
  48. DWord(08040054H); (* Вход в программу. Виртуальный адрес начала исполнения *)
  49. DWord(52); (* Смещение на начало таблицы программных заголовков *)
  50. DWord(0); (* Смещение на начало таблицы секций (в исполнимом - не нужны) *)
  51. DWord(0); (* Флаги процессора (для Intel 386 отсутствуют) *)
  52. Word(52); (* Размер заголовка ELF-файла в байтах *)
  53. Word(32); (* Размер одного программного заголовка *)
  54. Word(1); (* Количество программных заголовков *)
  55. Word(0); (* Размер заголовка секции (в исполнимом файле они не нужны) *)
  56. Word(0); (* Количество заголовков секций *)
  57. Word(0) (* Номер секции с таблицей строк (в исполнимом файле не нужны) *)
  58. END WriteElfHeader;
  59. PROCEDURE WriteProgramHeader;
  60. BEGIN
  61. DWord(1); (* Вид данного сегмента - сегмент для загрузки *)
  62. DWord(54H); (* Смещение на начало данного сегмента = 84 *)
  63. DWord(08040054H); (* Виртуальный адрес первого байта в сегменте *)
  64. DWord(08040054H); (* Физический адрес - не используется !FIXME Проверить, нужен ли здесь 0 *)
  65. DWord(38); (* Сколько сегмент занимает в файле *)
  66. DWord(38); (* Сколько сегмент занимает в файле *)
  67. DWord(5); (* Флаги сегмента: 4 + 1 = чтение + исполнение *)
  68. DWord(1000H) (* Выравнивание для виртуального адреса и смещения в файле *)
  69. END WriteProgramHeader;
  70. PROCEDURE WriteTextSegment;
  71. BEGIN
  72. Byte(0B9H); (* MOV ECX, DWORD ... *)
  73. DWord(08040054H + 34); (* Откуда брать строку *)
  74. Byte(0BAH); (* MOV EDX, DWORD ... *)
  75. DWord(04H); (* Длина строки *)
  76. Byte(0BBH); (* MOV EBX, DWORD ... *)
  77. DWord(01H); (* Куда писать: стандартное устройство вывода STDOUT *)
  78. Byte(0B8H); (* MOV EAX, DWORD ... *)
  79. DWord(04H); (* Системный вызов: write *)
  80. Byte(0CDH); (* Прерывание: INT *)
  81. Byte(080H); (* Номер прерывания *)
  82. Byte(0BBH); (* MOV EBX, DWORD ... *)
  83. DWord(01H); (* Код возврата (exit code) *)
  84. Byte(0B8H); (* MOV EAX, DWORD ... *)
  85. DWord(01H); (* Системный вызов: exit *)
  86. Byte(0CDH); (* Прерывание: INT *)
  87. Byte(080H); (* Номер прерывания *)
  88. Byte(ORD("H")); (* Строка *)
  89. Byte(ORD("i"));
  90. Byte(ORD("!"));
  91. Byte(0AH)
  92. END WriteTextSegment;
  93. PROCEDURE WriteElf;
  94. BEGIN
  95. WriteElfHeader;
  96. WriteProgramHeader;
  97. WriteTextSegment
  98. END WriteElf;
  99. PROCEDURE WriteDummy*;
  100. BEGIN
  101. F := Files.New(fname);
  102. IF F # NIL THEN
  103. Files.Set(r, F, 0);
  104. WriteElf;
  105. Files.Register(F);
  106. Files.Close(F);
  107. IF Chmod.MakeExecutable(fname) = 0 THEN END
  108. ELSE
  109. Out.String("Не могу создать файл ");
  110. Out.String(fname); Out.Ln
  111. END
  112. END WriteDummy;
  113. PROCEDURE MakeItem*(VAR x: Item; o: ST.Object);
  114. BEGIN
  115. x.mode := o.class;
  116. x.type := o.type;
  117. x.val := o.val
  118. END MakeItem;
  119. PROCEDURE Call*(VAR x: Item);
  120. BEGIN
  121. Out.String("Вызвана процедура ");
  122. Out.Int(x.val, 0); Out.Ln
  123. END Call;
  124. END Generator.