diff options
Diffstat (limited to 'doc/src/libmcpu-bytecode-architecture-ru.tex')
| -rw-r--r-- | doc/src/libmcpu-bytecode-architecture-ru.tex | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/doc/src/libmcpu-bytecode-architecture-ru.tex b/doc/src/libmcpu-bytecode-architecture-ru.tex new file mode 100644 index 0000000..cbf9268 --- /dev/null +++ b/doc/src/libmcpu-bytecode-architecture-ru.tex @@ -0,0 +1,230 @@ +\documentclass[10pt,a4paper,oneside,openany]{memoir} +\newcommand{\DocShortTitle}{LibMCPU: архитектура машинного кода и ABI} +\input{libmcpu-doc-common.tex} +\hypersetup{pdftitle={LibMCPU: архитектура машинного кода, памяти и ABI вызовов},pdfsubject={Технический справочник по архитектуре LibMCPU}} +\begin{document} +\DocTitlePage{LibMCPU: архитектура машинного кода,\\памяти и ABI вызовов}{Регистровая модель, ISA, PTR64, CALL ABI, lifecycle и runtime}{Техническое справочное руководство} + +\ManualIntro{Документ фиксирует текущий архитектурный контракт LibMCPU: register model, ISA, memory spaces, PTR64, CALL ABI, MELF lifecycle, syscall/error ABI, dynamic startup linking и подписанный HLL Runtime ABI между mcpu-ld, CRT и MCPU Libc. Документ намеренно не связан с номером выпуска пакета. Для бинарного формата MELF действует отдельное руководство \code{libmcpu-melf-abi-ru.pdf}.} + +\begin{principle} +\textbf{Главный принцип.} Физический регистр LibMCPU нетипизирован. \REG{} задаёт только физическую ширину и байтовый адрес в едином register file. Integer/Real/Complex смысл определяется opcode; запись \code{c<bits>@addr} является semantic view того же физического регистра. Архитектурный \PTR{} также является обычным 64-битным значением, но его декодирование и права доступа задаются ABI. +\end{principle} + +\tableofcontents +\clearpage + +\part{Базовая архитектура, ISA и CALL ABI} +\input{libmcpu-architecture-core-ru.tex} + +\part{Memory backing, представление объектов и assembler} +\input{libmcpu-architecture-runtime-ru.tex} +\input{libmcpu-isa-coverage-ru.tex} +\input{libmcpu-assembler-details-ru.tex} + +\part{Program Model ABI, runtime и динамическая загрузка} +\section{Program Model Lifecycle ABI} +Каждый исполняемый MELF-файл имеет обязательные lifecycle symbols \code{_start} и \code{_life}; \code{e_entry} всегда указывает на \code{_start}. Секция \code{.init} и символ \code{_fini} необязательны. Эти точки входа принадлежат MELF/runtime ABI и не должны смешиваться с функциями будущего языка высокого уровня. + +\subsection{С отдельным INIT} +\begin{lstlisting} +.init +_start: + ... one-time startup ... + END + +.text +_life: + ... resumable LIFE phase ... + END +\end{lstlisting} +Тогда \code{e_init_entry=_start}, а \code{e_life_entry=_life}. Первый \code{END} завершает INIT; runtime устанавливает PC в \code{_life} и начинает LIFE. Последующие LIFE \code{END} возвращают управление supervisor-у, а следующий resume продолжается с инструкции после соответствующего \code{END}. + +\subsection{Без INIT} +\begin{lstlisting} +.text +_start_life: + ... startup / ordinary program trampoline ... +\end{lstlisting} +Псевдометка \code{_start_life:} эквивалентна двум последовательным labels \code{_start:} и \code{_life:} по одному адресу. В final executable \code{e_init_entry=0} и \code{e_entry == e_life_entry}. Эта форма особенно естественна для обычной PROGRAM, которая заканчивается через \code{EXIT} и не создаёт LIFE boundaries. + +\subsection{FINI, END и EXIT} +\code{END} завершает текущую управляемую фазу и возвращает управление supervisor-у. Graceful \code{EXIT(status)} завершает normal execution; если имеется \code{.fini}/\code{_fini}, runtime сохраняет status, входит в FINI и требует завершить FINI инструкцией \code{END}. Второй \code{EXIT} внутри FINI не является нормальным контрактом. Diagnostic stop по \code{--steps} не симулирует graceful \code{EXIT} и потому сам по себе FINI не запускает. + +\input{libmcpu-hll-crt-contract-ru.tex} + +\section{McpuStartup и argc/argv} +Перед первой guest-инструкцией загрузчик создаёт постоянную область запуска (startup area) в верхней части STACK. Заголовок имеет размер 32 байта и выравнивание 16 байт: +\par\medskip +\noindent\begin{tabularx}{\textwidth}{@{}L{20mm}L{30mm}L{24mm}Y@{}} +\toprule +\textbf{Смещение} & \textbf{Поле} & \textbf{Размер} & \textbf{Значение}\\ +\midrule +0x00 & version & 4 & \code{MCPU_STARTUP_VERSION_1}\\ +0x04 & size & 4 & 32\\ +0x08 & argc & 8 & число аргументов guest-программы\\ +0x10 & argv & 8 & \PTR(STACK, массив argv)\\ +0x18 & reserved & 8 & ноль\\ +\bottomrule +\end{tabularx} +После заголовка расположен массив \code{argv[0..argc]} из PTR64, завершающий NULL, затем NUL-terminated строки аргументов. Эта область остаётся действительной всё время жизни executable. Начальное состояние: \code{PC=e_entry}, \code{SP=startup_base}, \code{FP=stack_size}. + +\section{HEAP и program break} +HEAP --- отдельный runtime-сегмент SEG=0x7. Он не расширяет DATA и не имеет assembler payload. Определяемый компоновщиком неподменяемый символ \code{_end} равен \PTR(HEAP,16); это начальный и минимальный program break. + +Runtime хранит \code{_heap_brk}, \code{_heap_size}, \code{_heap_capacity}, immutable \code{_heap_limit}. Запрос ниже 16 или выше limit отклоняется и возвращает прежний break. Shrink не обязан уменьшать host mapping/capacity; освобождённый range немедленно zeroes. Regrow в уже существующий backing снова открывает deterministic zero memory. При backing relocation guest pointers остаются valid, потому что содержат segment+offset. + +\section{SYSCALL ABI и SYS_brk} +Zero-operand instruction \code{SYSCALL} использует fixed overlapping register area в верхней части register file. +\par\medskip +\noindent\begin{tabularx}{\textwidth}{@{}L{32mm}L{32mm}Y@{}} +\toprule +\textbf{Role} & \textbf{Address/view} & \textbf{Meaning}\\ +\midrule +SYSNO & \code{r32@0x7fffc} & syscall number\\ +NARGS & \code{r32@0x7fff8} & argument count\\ +RET & \code{r64@0x7fff8} & return value; overlaps NARGS\\ +ARG0..ARG5 & \code{r64@0x7fff0} ... \code{r64@0x7ffc8} & up to six arguments\\ +\bottomrule +\end{tabularx} + +Первый syscall --- \code{SYS_brk}, number 10. Он требует один argument: NULL означает query, HEAP PTR64 requests absolute new break. Общее правило syscall ABI использует стабильные host-independent MCPU errno: неуспех возвращает отрицательное \code{-MCPU_errno}, а host errno преобразуется на sysdeps boundary и наружу не выходит. \code{SYS_brk} является специальным исключением: он возвращает фактический/current HEAP PTR64 и при accepted, и при rejected request. Unsupported syscall number возвращает \code{-ENOSYS} из MCPU errno namespace. + +\begin{lstlisting} +; query current break +MOV r32@0x7fff8, 1 +LDI r32@0x7fffc, 10 +CLR r64@0x7fff0 +SYSCALL +; result: r64@0x7fff8 +\end{lstlisting} + +\section{Startup dynamic linking: архитектурный взгляд} +Текущий normal dynamic contract --- frozen MELF ABI v3. \code{mcpu-ld --dynamic} создаёт ABI-v3 ET_EXEC, а \code{mcpu-ld --shared --soname=NAME} --- ABI-v3 ET_DYN. В отличие от исторического ABI v2, normal dependencies записываются в canonical non-ALLOC \code{.dynamic} как \code{DT_NEEDED}, а shared object имеет обязательный \code{DT_SONAME}. ABI v2 остаётся читаемым как historical explicit-preload input format. + +\code{mcpu-run} обнаруживает NEEDED graph до исполнения guest-кода, проверяет SONAME identity, загружает dependencies breadth-first/left-to-right и завершает symbol resolution/RELA до первой инструкции \code{_start}. Явный \code{--ldpreload} и \code{MCPU_LD_PRELOAD} остаются override/interposition mechanisms. PLT/GOT, lazy binding, \code{dlopen()}, \code{dlsym()} и runtime lookup после старта отсутствуют. + +ET_DYN содержит только загружаемое PROGRAM/DATA содержимое \code{.text/.data/.bss} плюс non-ALLOC metadata; lifecycle, CONTROL/INPUT/OUTPUT/TRACE, STACK и HEAP принадлежат главному executable. + +\subsection{GLOBAL/WEAK interposition} +Сильный GLOBAL имеет приоритет над WEAK. Для equal-strength definitions highest scope имеет explicit preload с установленным rightmost priority, затем main executable, затем normal NEEDED graph в breadth-first/left-to-right order. Lifecycle symbols \code{_start/_life/_fini} остаются частными для executable и не участвуют в interposition. + +\subsection{LOCAL ET_DYN runtime rebasing} +\begin{normative} +LOCAL symbol остаётся private и non-preemptible, но ссылка на него внутри ET_DYN \textbf{не может быть окончательно превращена в process address при static link}: final PROGRAM/DATA base shared object ещё неизвестна. Поэтому такая ссылка сохраняется как LOCAL runtime RELA. Startup linker разрешает её строго против originating module и добавляет runtime segment base. LOCAL symbols не попадают в GLOBAL/WEAK winner namespace. +\end{normative} + +Правило возникло как исправление runtime-address contract ещё в ABI v2 и является нормативной частью frozen ABI v3. Оно не открывает LOCAL symbol для interposition. + +\section{mcpu-run как host-side test bench} +Помимо one-shot inspection options, runtime поддерживает четыре lifecycle stages: +\par\medskip +\noindent\begin{tabularx}{\textwidth}{@{}L{36mm}Y@{}} +\toprule +\textbf{Опция} & \textbf{Граница выполнения}\\ +\midrule +\code{--before-run=<action>} & after load/preload/relocations/startup, before first guest instruction\\ +\code{--after-init=<action>} & after INIT END; при отсутствии .init --- один раз на logical empty INIT boundary\\ +\code{--on-step=<action>} & after every LIFE END\\ +\code{--after-run=<action>} & after final normal stop; graceful FINI уже завершён\\ +\bottomrule +\end{tabularx} + +Stage-опции можно повторять; они выполняются слева направо. Фильтры по номеру шага намеренно отсутствуют. + +\subsection{Typed actions} +\begin{lstlisting}[language={}] +print-int-regs:r64@0x100,r64@0x108 +print-real-regs:r128@0x200,r256@0x300 +set-int-regs:r64@0x100=123,r64@0x108=-17 +set-real-regs:r128@0x200=1.25,r128@0x220=-2.5 + +print-int-<memory>:64@16,64@24 +print-real-<memory>:128@32,128@48 +set-int-<memory>:64@16=123,64@24=456 +set-real-<memory>:128@32=1.25,128@48=2.5 +\end{lstlisting} +\code{<memory>} --- data, control, heap, input, output, trace. Один scalar print-action печатает comma-list одной строкой через spaces. Set values разбираются через LibMPUIO \code{mpu_sscanf()}; whole action валидируется до первой записи, а guest PSW сохраняется вокруг host-side numeric parsing. + +\subsection{Raw actions} +\code{print-raw-<memory>:<bytes>@<addr>} read-only и описывает ровно один dump. Comma-list запрещён; для нескольких dumps повторяется stage option. \code{set-raw-*} не существует. Size принимает raw bytes и K/KiB, M/MiB, G/GiB с binary multipliers. DATA raw view ограничен linked \code{.data} и не перелезает в \code{.bss}; HEAP host view ограничен prepared backing, тогда как guest access ограничен current break. + +\subsection{Двойной дефис как разделитель} +Preferred CLI: +\begin{lstlisting}[language={}] +mcpu-run [runtime-options] -- executable [program-args...] +\end{lstlisting} +После separator \lstinline|--| tokens не интерпретируются как runner options. Первый token становится executable spelling и guest \code{argv[0]}. Legacy form без separator сохранена. + + +\section{Бинарные утилиты toolchain} +Системные инструменты MELF используют единый public format contract и не вводят альтернативного представления машинного кода. +\par\medskip +\noindent\begin{tabularx}{\textwidth}{@{}L{36mm}Y@{}} +\toprule +\textbf{Команда} & \textbf{Назначение}\\ +\midrule +\code{mcpu-readelf} & Структурный read-only просмотр MELF headers, sections, symbols, RELA, dynamic и MCPU metadata.\\ +\code{mcpu-ar} & Deterministic UNIX static archives из MELF ET\_REL с System-V/GNU-style symbol index.\\ +\code{mcpu-nm} & Symbol-table inspection для объектов, executables, shared objects и archives.\\ +\code{mcpu-objdump} & Section/relocation inspection и дизассемблирование через тот же decoder, который используется CPU runtime.\\ +\code{mcpu-strip} & Консервативное удаление только non-runtime symbol metadata; link/runtime-critical sections сохраняются.\\ +\code{mcpu-objcopy} & MELF-to-MELF structural copy и safe editing non-ALLOC metadata; runtime-visible image защищён.\\ +\bottomrule +\end{tabularx} + +\begin{principle} +MELF уже является native object/executable container виртуальной MCPU. Поэтому \code{mcpu-objcopy} не имеет режимов flat binary, Intel HEX, S-record, VMA/LMA или подготовки firmware image для SPI NOR. Metadata-only edit обязан сохранять guest-visible allocated image и frozen ABI v3 execution semantics. +\end{principle} + +Английские и русские manual pages устанавливаются как section 1 для каждой команды; обзор архитектуры и toolchain доступен как \code{libmcpu(7)}. + +\section{Инварианты реализации} +\begin{enumerate} +\item PROGRAM machine fields всегда MSB-first; data representation не смешивается с code representation. +\item Register address и PTR64 offset не являются host pointers. +\item Bounds/permission validation precedes guest-visible writes, где instruction contract требует atomicity. +\item DATA имеет один process-owned 16-byte NULL guard; ET_DYN не получает собственного guard. +\item HEAP имеет immutable configured limit и minimum break 16; released bytes zeroed on shrink. +\item ABI-v1 static executable полностью linked; ordinary loader его не relink-ит. +\item ABI-v2/v3 startup linking завершается до \code{_start}; после старта symbol lookup отсутствует. +\item LOCAL ET_DYN references runtime-rebased, но никогда не interpose. +\item Lifecycle boundaries определяются guest \code{END/EXIT}; stage actions лишь наблюдают/модифицируют state на host side. +\end{enumerate} + + +\appendix +\section{Полный справочник директив mcpu-as} +Этот appendix перечисляет assembler directives и специальные формы, которые являются частью текущего source contract. Детальная grammar выражений и ограничения sections приведены в основной части документа. +\input{libmcpu-assembler-directives-table.tex} + +\section{Полная таблица OPCODE16} +Таблица перечисляет все значения public \code{cpu_opcode}. Каждый opcode однозначно задаёт число и тип последующих operands; PROGRAM machine fields сериализуются MSB-first. Operand spellings показаны в терминах assembler ABI. +\input{libmcpu-opcode-table.tex} + +\section{PSW selectors и RCONST} +\subsection{PSW bit selectors} +\input{libmcpu-psw-table.tex} +\subsection{RCONST selectors} +\input{libmcpu-rconst-table.tex} + +\section{Краткая памятка ABI} +\par\medskip +\noindent\begin{tabularx}{\textwidth}{@{}L{42mm}Y@{}} +\toprule +Register file & 512 KiB, overlapping REG24 views\\ +Return Value Area & top 8192 bytes, scalar result at \code{0x80000-size}\\ +PTR64 & SEG4:OFF60; DATA=0, STACK=1, PROGRAM=2, CONTROL=3, INPUT=4, OUTPUT=5, TRACE=6, HEAP=7\\ +CALL alignment & 16 bytes; CALL pushes 8-byte return PC; caller owns argument block\\ +PSW & bits 0..15 volatile across call; TF/IF/MODE preserved if changed\\ +DATA guard & process offsets 0..15 zero\\ +HEAP & begin/break minimum 16; \code{_end=HEAP:16}\\ +Startup & 32-byte McpuStartup + argv PTR64 array + strings; persistent\\ +Low-level lifecycle & mandatory \code{_start}, \code{_life}; optional \code{_fini}; \code{e_entry=_start}\\ +HLL PROGRAM & defining ET_REL: \code{main+fini}; automatic \code{crt0.o+crti.o+crtn.o}\\ +HLL MODEL & defining ET_REL: \code{init+life+fini}; automatic \code{crt1.o+crti.o+crtn.o}\\ +Dynamic & frozen normal ABI v3 with SONAME/NEEDED; ABI v2 remains historical explicit-preload input format\\ +\bottomrule +\end{tabularx} + +\end{document} |
