Learning Platform
Глоссарий Troubleshooting
Урок 03.05 · 25 мин
Средний
TVMStack MachineOpcodesCellsSlicesBuilders

TVM: Стековая Машина

TVM (TON Virtual Machine) — это движок, исполняющий код каждого смарт-контракта в сети TON. Понимание стековой архитектуры TVM помогает писать более эффективный код и отлаживать сложные ошибки. Это как знание устройства двигателя для автогонщика: можно ездить и без этого знания, но для победы в гонке (оптимизации газа) оно необходимо.

TVM (TON Virtual Machine) — виртуальная машина TON, исполняющая смарт-контракты. Как и EVM в Ethereum, TVM — стековая машина, но с ключевыми отличиями в типах данных.


Основы стековой машины

TVM оперирует стеком — структурой данных LIFO (Last In, First Out). Инструкции берут аргументы с вершины стека и помещают результат обратно.

Пример: сложение 3 + 5

PUSH 3     стек: [3]
PUSH 5     стек: [3, 5]
ADD        стек: [8]      ← результат на вершине

Элементы стека в TVM нумеруются от вершины: s0 (вершина), s1 (следующий), s2 и т.д.


Интерактивная визуализация

Рассмотрим реальную TVM-программу: отправка TON с контракта.

TVM Stack Machine
Программа: Отправка TON с контракта
ИнструкцияPUSHINT 1000000000
Помещаем на стек сумму для отправки: 1 TON = 10^9 нано-TON
Все инструкции
PUSHINT 1000000000
PUSHINT 0
NEWC
STSLICE addr
STGRAMS
ENDC
PUSHINT 64
SENDRAWMSG
DROP
Стек (1 элемент)
s0
1000000000
bottomtop (s0)
Шаг 1 / 9

Типы данных TVM

В отличие от EVM (только 256-бит слова), TVM поддерживает несколько типов:

ТипОписаниеПример
Integer257-бит знаковое целоеБалансы, счётчики, адреса
CellНеизменяемая ячейка данных (до 1023 бит + 4 ссылки)Хранение данных контракта
SliceКурсор для чтения данных из CellРазбор входящего сообщения
BuilderБуфер для создания новой CellФормирование исходящего сообщения
Continuation”Замороженное” вычислениеУсловия, циклы, обработка ошибок
TupleУпорядоченная коллекция значенийВозврат нескольких значений
NullПустое значениеОтсутствие данных
TIP

TON vs Ethereum: Типы данных виртуальной машины

EVM работает только с 256-битными словами. Все данные (адреса, числа, байты) — это 32-байтные значения. TVM богаче: поддерживает ячейки, слайсы, билдеры, продолжения. Это делает TVM мощнее, но и сложнее.

EVM: Stack, Memory, Storage

Основные инструкции TVM

Стековые операции

ИнструкцияДействие
PUSH sNКопирует элемент sN на вершину стека
POP sNУдаляет вершину и помещает в позицию sN
XCHG s0, sNМеняет местами вершину и элемент sN
DROPУдаляет вершину стека
DUPДублирует вершину стека
NIPУдаляет s1 (второй элемент)

Арифметика

ИнструкцияДействие
ADDs0 = s1 + s0
SUBs0 = s1 - s0
MULs0 = s1 * s0
DIVs0 = s1 / s0
MODs0 = s1 % s0
INCs0 = s0 + 1

Работа с ячейками

ИнструкцияДействие
NEWCСоздаёт новый Builder
ENDCЗавершает Builder → Cell
STSLICEЗаписывает Slice в Builder
STGRAMSЗаписывает количество TON (VarUInteger)
STU NЗаписывает N-битное беззнаковое число
CTOSПреобразует Cell → Slice
LDU NЧитает N бит из Slice как unsigned int

Отправка сообщений

ИнструкцияДействие
SENDRAWMSGОтправить raw message (Cell + mode)
RAWRESERVEЗарезервировать TON на балансе

Cell, Slice, Builder: рабочий цикл

Работа с данными в TVM следует паттерну:

1. CTOS — Cell → Slice (для чтения)
2. LDU, LDSLICE, LDGRAMS — читаем данные из Slice
3. NEWC — создаём Builder (для записи)
4. STU, STSLICE, STGRAMS — записываем данные в Builder
5. ENDC — Builder → Cell (готово)

Это похоже на сериализацию/десериализацию: Slice для чтения (десериализация), Builder для записи (сериализация).


TVM и языки высокого уровня

Разработчики не пишут TVM-инструкции вручную. Компиляторы Tact и FunC генерируют TVM bytecode:

Tact код:                    TVM инструкции:
────────────                 ────────────────
send(SendParameters{         PUSHINT 1000000000
  to: addr,                  PUSHINT 0
  value: ton("1"),           NEWC
  bounce: true,              STSLICE addr
  body: ...                  STGRAMS
});                          ENDC
                             PUSHINT 64
                             SENDRAWMSG

Понимание TVM помогает оптимизировать gas и отлаживать контракты на низком уровне.


Частые ошибки

  1. Путают стек TVM со стеком вызовов: TVM использует стек для хранения операндов и результатов операций, а не для управления вложенными вызовами функций.
  2. Не понимают разницу между stack и registers (c0-c7): регистры TVM хранят контекст исполнения (код, данные, газ), а стек используется для вычислений.
  3. Забывают, что TVM работает с 257-битными целыми числами, а не с 256-битными как в EVM, что влияет на диапазон значений и совместимость.
  4. Игнорируют газовую стоимость стековых операций при оптимизации, хотя перестановки элементов стека (SWAP, XCHG) тоже стоят газ.

Проверка знанийKnowledge check
Чем TVM принципиально отличается от EVM в плане типов данных на стеке?
ОтветAnswer
EVM работает только с 256-битными словами — все данные (числа, адреса, байты) представлены как 32-байтные значения. TVM поддерживает множество типов: 257-бит целые числа, Cell (неизменяемые ячейки), Slice (курсоры чтения), Builder (буферы записи), Continuation (замороженные вычисления), Tuple и Null. Это делает TVM более выразительным, но и более сложным.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. После выполнения инструкций PUSH 3, PUSH 5, ADD, что окажется на вершине стека TVM?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 7