diff options
Diffstat (limited to 'doc/src/libmcpu-assembler-details-ru.tex')
| -rw-r--r-- | doc/src/libmcpu-assembler-details-ru.tex | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/doc/src/libmcpu-assembler-details-ru.tex b/doc/src/libmcpu-assembler-details-ru.tex new file mode 100644 index 0000000..75a5c4a --- /dev/null +++ b/doc/src/libmcpu-assembler-details-ru.tex @@ -0,0 +1,233 @@ +\section{Ассемблер: UTF-8 source, строки, .equ и arithmetic expressions} +Низкоуровневый mcpu-as обязан уметь описывать binary images data-like sections, labels и relocation-like address expressions без обязательного текстового препроцессора. Текстовая метапрограмма (\#define, \#include, conditional compilation, parameterized macros) остаётся отдельным будущим слоем. В assembler входят только механизмы, непосредственно связанные с machine/data representation и разрешением символов. + +\subsection{Кодировка assembler source} +Исходный файл mcpu-as всегда UTF-8. Результат сборки не зависит от LANG, LC\_CTYPE или другой locale host-системы. Перед разбором assembler проверяет source как well-formed UTF-8 через LibMPUIO. + +Это особенно важно для строковых директив: одинаковый .s обязан создавать одинаковые image bytes на любых build hosts при одинаковом LibMCPU target profile. + +\subsection{Командная строка mcpu-as} +Ассемблер всегда создаёт один перемещаемый объект MELF ET\_REL, поэтому отдельный переключатель режима сборки не нужен. Выходной файл задаётся обычной UNIX-опцией \code{-o}, а единственный исходный файл является позиционным аргументом: + +\begin{lstlisting}[language={}] +mcpu-as -o file.o file.s +mcpu-as file.s -o file.o +\end{lstlisting} + +Обе формы полностью эквивалентны: порядок \code{-o} и входного файла свободный. Ровно один входной файл и ровно один выходной файл обязательны. Опции \code{-h} и \code{--help} печатают справку. Историческая форма \code{mcpu-as -c input.s output.o} удалена: \code{-c} больше не является опцией, поскольку другого режима работы у assembler нет. + +\subsection{.utf8 - NUL-terminated UTF-8 byte string} +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .data +\end{lstlisting} + +name\_utf8: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .utf8 "Андрей" +\end{lstlisting} + +.utf8 записывает UTF-8 payload буквально как bytes и добавляет один завершающий 0x00. Никакого target endian преобразования и никакой locale conversion нет. + +"Андрей" -> D0 90 D0 BD D0 B4 D1 80 D0 B5 D0 B9 00 + +Поддерживаются escapes \textbackslash{}\textbackslash{}, \textbackslash{}", \textbackslash{}n, \textbackslash{}r, \textbackslash{}t, \textbackslash{}b, \textbackslash{}f, \textbackslash{}v, \textbackslash{}a, byte escape \textbackslash{}xHH, а также Unicode scalar escapes \textbackslash{}uXXXX и \textbackslash{}UXXXXXXXX. Результирующая последовательность снова проверяется как UTF-8. + +Встроенный NUL внутри .utf8/.ucs2 намеренно не поддерживается: эти директивы определяют C-style NUL-terminated strings. Для произвольного binary layout с внутренними нулями используется .byte или .integer/.int. + +\subsection{.ucs2 - UTF-8 source literal в strict UCS-2 target objects} +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .data +\end{lstlisting} + +name\_ucs2: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .ucs2 "Андрей" +\end{lstlisting} + +Assembler сначала получает UTF-8 literal, затем использует strict LibMPUIO UTF-8 -> UCS-2 conversion. Каждый UCS-2 code unit записывается как отдельный 16-bit architectural data object с помощью target data byte order; в конце добавляется U+0000. + +U+0410 U+043D U+0434 U+0440 U+0435 U+0439 U+0000 + +current little-endian target bytes: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + 10 04 3D 04 34 04 40 04 35 04 39 04 00 00 +\end{lstlisting} + +Strict UCS-2 допускает scalar values U+0000..U+FFFF, кроме surrogate range U+D800..U+DFFF. UTF-8 characters выше U+FFFF (например emoji) не раскладываются на UTF-16 surrogate pairs, а дают assembler error. Таким образом .ucs2 точно соответствует принятой в LibMCPU/LibMPUIO модели UCS-2, а не UTF-16. + +\subsection{.byte, .integer и .int} +.byte создаёт raw bytes без implicit terminator, alignment или endian conversion: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .byte 0x4c, 0x43, 0x50, 0x55 + .byte 1, 2+3, BLOCK_SIZE/512 +\end{lstlisting} + +Каждый элемент должен находиться в диапазоне 0..255. .integer сохраняет прежний смысл typed integer object, а .int является полным синонимом. Обе директивы принимают список значений одной ширины: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .integer 16, 0x0410, 0x043d, 0x0000 + .int 8, 65, 66, 0 +\end{lstlisting} + +Каждое значение формирует отдельный object указанной width непосредственно в текущей data-like section position; hidden padding отсутствует. + +\subsection{.equ - абсолютные assembler symbols} +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .equ table_ptr, 0x03000 + .equ block_size, 4 * 512 + .equ next_reg, table_ptr + 8 +\end{lstlisting} + +.equ section-independent и не создаёт bytes. Имена symbols case-sensitive. Все .equ definitions собираются до emission, поэтому разрешены forward references между .equ symbols. + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .equ является absolute constant symbol. В текущем low-level assembler выражение +\end{lstlisting} + +справа может ссылаться на integer literals и другие .equ, но не на DATA/CODE labels. Это сохраняет различие между absolute assembler symbols и section-relative labels/relocations MELF. + +Имя label не может совпадать с именем .equ. + +\subsection{Integer expression grammar и precedence} +primary := integer | symbol | '(' expression ')' + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + unary := ['+' | '-'] unary | primary +\end{lstlisting} + +product := unary \{ ('*' | '/' | '\%') unary \} expression := product \{ ('+' | '-') product \} + +Операции имеют обычный arithmetic precedence: unary, затем multiply/divide/remainder, затем add/subtract. Division by zero, overflow internal expression domain и значение вне требуемой width дают assembler error. + +Expressions используются для absolute numeric operands: register byte address, LDI, stack/pointer signed offsets, BMOVI count, .align, .byte, integer widths/values и других соответствующих immediate fields. + +\subsection{Label expressions и fixups} +Address expressions дополнительно получают labels тех sections, которые допустимы для конкретного operand class. Поэтому assembler непосредственно поддерживает: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + LEA r64@table_ptr, input_vector+8 ; selector follows label section + LOAD r64@next_reg, data_object+16 ; direct LOAD remains DATA-relative + JMP loop+0 ; PROGRAM CODE64 + CALL function + .cptr handler+0 +\end{lstlisting} + +LEA принимает labels из DATA/CONTROL/INPUT/OUTPUT/TRACE и code sections и создаёт полный PTR64 selector+offset. Direct LOAD/STORE остаются в namespace DATA labels + .equ. CODE64 operands и .cptr используют PROGRAM labels + .equ. Forward labels работают через fixups. CPU по-прежнему не хранит instruction-boundary metadata: arithmetic CODE expression обязано использоваться программистом осмысленно. + +\subsection{Symbolic register addresses} +REG24 byte address может быть integer expression из absolute .equ symbols: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .equ table_ptr, 0x03000 + .equ temp_ptr, table_ptr + 8 + + LEA r64@table_ptr, table + LDI r64@temp_ptr, 42 + LDI r64@(table_ptr + 16), 7 +\end{lstlisting} + +После вычисления expression assembler выполняет обычную проверку register width, natural alignment и границ 512 KiB register file. DATA/CODE labels в register-address expression не участвуют: label address и register-file byte address являются разными namespaces. + +\subsection{Граница mcpu-as и будущего препроцессора} +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + Механизм Уровень Причина + + .init/.text/.fini/.data/.control/.input/.output/.trace, mcpu-as определяют layout + labels, .align executable/data + images + + .integer/.int/.real/.complex/.byte/.utf8/.ucs2/.cptr mcpu-as создают data-like + objects/bytes + + + + + + .equ, arithmetic expressions, symbol fixups mcpu-as необходимы для + адресов и будущих + relocations + + #define/#undef/#include/#if/#ifdef отдельный текстовая + preprocessor metaprogramming не + является machine + encoding + + parameterized macros / repetition отдельный source transformation + preprocessor до mcpu-as +\end{lstlisting} + +Таким образом обычный symbolic assembler остаётся самодостаточным, а будущая схема .S -> cpu-cpp -> mcpu-as может добавляться независимо и не усложняет binary semantics cpu-as. + +\subsection{Полный пример} +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .equ table_ptr, 0x03000 + .equ next_reg, table_ptr + 8 + .equ block_size, 4 * 512 + + .data +\end{lstlisting} + +name16: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .ucs2 "Андрей" +\end{lstlisting} + +name8: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .utf8 "Андрей" +\end{lstlisting} + +header: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .byte 0x4c, 0x43, 0x50, 0x55, block_size/512 +\end{lstlisting} + +letters: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .int 16, 0x0410, 0x043d, 0x0434, 0 + .align 16 +\end{lstlisting} + +answer: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + .integer 64, 42 + + .text +\end{lstlisting} + +start: + +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] + LEA r64@table_ptr, name16 + LOAD r64@next_reg, answer + HALT +\end{lstlisting} + +Здесь ни один identifier не требует textual macro substitution: table\_ptr/next\_reg - absolute assembler symbols, name16/answer - DATA labels, а arithmetic expression вычисляется самим assembler. + + +\subsection{Маркеры строк препроцессора и логические координаты diagnostics} +После появления \code{mcpu-cpp} assembler не использует собственную директиву \code{\#line} для управления source coordinates. Вместо неё \code{mcpu-as} распознаёт маркеры строк, оставляемые препроцессором в выходном потоке: +\begin{lstlisting}[language={}] +# digit-sequence +# digit-sequence "filename" +# digit-sequence "filename" flags... +\end{lstlisting} +\code{digit-sequence} содержит как минимум одну decimal digit и всегда разбирается в основании 10, даже при leading zeroes. Допустимый диапазон - 0..2147483647. Значение задаёт logical line number для physical source line, непосредственно следующей за marker. Filename optional; при его отсутствии сохраняется предыдущий logical filename. Всё после закрывающей кавычки filename считается полем flags препроцессора и полностью игнорируется assembler. + +Marker не создаёт bytes, symbols, \code{__LINE__} или \code{__FILE__}, не участвует в expression evaluation и влияет только на source coordinates последующих diagnostics. Empty и comment-only ordinary lines увеличивают logical counter обычным образом. + +Строки \code{\#pragma} и \code{\#lang} предназначены для других участников toolchain: \code{mcpu-as} полностью игнорирует их и не увеличивает logical line counter. Любая другая строка, начинающаяся с \code{\#}, также удаляется из assembler token stream, но учитывается как одна ordinary logical source line. + +\begin{normative} +\textbf{Историческая форма \#line.} Запись \code{\#line N "file"} больше не является source-location directive \code{mcpu-as}. Она обрабатывается как обычная неизвестная строка \code{\#...}: игнорируется как assembler syntax и учитывается при продвижении logical counter. Координаты source задаются только preprocessing line marker формой \code{\# N "file" flags...}. Это diagnostics contract и не часть MELF ABI. +\end{normative} |
