как называется промежуточный исполняемый код который выполняется виртуальной машиной
Информатика 10 класса Системы программирования
1. Отметьте все языки программирования высокого уровня.
Паскаль
Си
Python
2. Отметьте языки программирования, которые используются для создания Web-сайтов в Интернете.
Javascript
PHP
Perl
3. Как называется программа, которая переводит в машинные
коды тексты программ, написанных на языке высокого уровня?
компилятор
4. Как называется программа, которая переводит в машинные
коды символьную запись машинных команд?
5. В чем преимущества трансляторов-интерпретаторов в сравнении с компиляторами?
программы легче отлаживать
программы переносимы на любую платформу, для которой есть интерпретатор
6. Назовите тип транслятора, который переводит в машинный код сразу всю программу и строит исполняемый файл.
однопроходный компилятор (??)
7. Как называется промежуточный исполняемый код, который выполняется виртуальной машиной?
байт-код
8. Как называется программа, которая собирает разные части (модули) создаваемой программы и функции из стандартных библиотек в единый исполняемый файл?
линковщик (linker)
9. Как называется программа для поиска ошибок в других программах?
отладчик
10. Как называется программа, позволяющая оценить время работы каждой процедуры и функции во время выполнения программы?
профайлер (profiler)
11. Каким термином называется набор стандартных структур данных и функций операционной системы или сервиса, которые программисты могут использовать в своих программах?
интерфейс программирования приложений
12. Отметьте все программы, которые обычно входят в состав интегрированной среды разработки программ (IDE).
текстовый редактор
компоновщик
отладчик
профилировщик (??)
13. Как называются среды программирования, нацеленные на высокую скорость и низкую стоимость разработки программ?
среды быстрой разработки приложений
14. Отметьте языки программирования, программа на которых может быть переведена в псевдокод, выполняемый в виртуальной машине.
Компиляция. 6: промежуточный код
Первый этап — разбор синтаксиса нашего джей-скрипа — пройден; подбираемся к генерации кода.
Далее в посте:
Выбор кода
Часто п-код делают стековым (например, MSIL): вообразим себе процессор, внутри которого нет пронумерованных регистров, а есть один большой стек, и все действия выполняются с верхними значениями на стеке. (Те, кому довелось программировать для х87, с такой моделью знакомы.) Стековый код действительно удобно генерировать и удобно выполнять, но не слишком удобно обрабатывать — например, в нём тяжело отслеживать зависимости между командами.
О выборе между стековым и регистровым промежуточным кодом выразительно отзывается создатель языка Beep:
Регистровый без вариантов:
Упрощение рантайма. Меньше манипуляций с указателями. Отсутствует понятие переполнения стека. Меньше кода, меньше работы с памятью — меньше места для критических ошибок.
Увеличивается сложность компиляции: появляется фаза выделения регистров. В случе исполнения на виртуальной машине нам не важно количество регистров, можем сделать их достаточное количество для того, что бы вообще не делать аллокацию, а просто маппить все параметры и переменные функции на регистры (см. Lua). Если количество параметров будет превышать количество регистров, то можно выделять часть activation record в хипе, но проще сделать так, что бы компилятор предлагал автору такого кода лечить голову.
В любом случае, если стоит вопрос упрощения рантайма ценой усложнения компилятора, так и следует поступать.
Возможность оптимизации: маппинг N регистров виртуальной машины на регистры процессора. На стековой машине это сделать значительно сложнее.
Работа с памятью для нас пока не актуальна: если не все переменные удастся разместить в регистрах, значит программисту не повезло. Операции, которых в джей-скрипе пока нет, вроде вызова функций, тем более не закладываем в п-код.
Упорядочим опкоды так, чтобы команды похожей структуры (в плане используемых регистров) шли подряд, и вынесем определение структуры команды в отдельный файл jsk.h : она потребуется и компилятору, и интерпретатору.
typedef unsigned char regnum;
struct command <
enum opcodes <
hlt,
store, // dst>
jz, // dst>
echo, // dst>
mov, // >dst
load, // >dst
input, // >dst
add, // src>dst
sub, // src>dst
mul, // src>dst
div, // src>dst
eq, // src>dst
ne, // src>dst
ge, // src>dst
le, // src>dst
gt, // src>dst
lt // src>dst
>;
opcodes opcode;
regnum dest;
union <
struct <
regnum src1, src2;
>;
short imm;
>;
command(opcodes opcode, regnum dest, regnum src1, regnum src2) :
opcode(opcode), dest(dest), src1(src1), src2(src2) <>
command(opcodes opcode, regnum dest, short imm) :
opcode(opcode), dest(dest), imm(imm) <>
>;
Чтобы под опкод действительно выделялся один байт, при компиляции придётся указывать ключ
Компиляция
Строки для echo будем хранить вместе с кодом программы, в самом конце; одинаковые строки объединим, чтобы хранилась только одна копия. Для этого будем хранить map всех строк, где значением будет «идентификатор» строки (её порядковый номер в программе).
Все переменные в джей-скрипе — глобальные. В отдельном map будем хранить по имени переменной номер выделенного ей регистра.
В общем, идея та же, что с форматированной распечаткой; только теперь в каждом узле дерева храним не текст, а список команд. Для элементов выражения также храним номер регистра, в котором результат вычисления.
(340 строк кода вынесены на http://tyomitch.net.ru/jsk.y.html, чтобы сохранить размер поста в пределах допустимого.)
Как видим, понадобилось «расщепить» узел value на три разных типа: литерал-число, литерал-строка, и ссылка на переменную. При форматировании кода различия между ними были несущественны, но при генерации уже понадобилось их различать.
Выполнение
#include
#include
#include
#include
#include
#include «jsk.h»
int pc = 0 ; // индекс команды (не смещение)
bool halted = false ;
int mem[ 1000 ]; // размер не важен: всё равно пока не пользуемся
typedef int (*op)( int src1, int src2, int dest, int imm); // все возможные входные значения
const char * fdata = NULL ; // весь прочитанный п-код
extern op ops[]; // объявлен ниже
int main( int argc, char ** argv) <
if (argc!= 2 ) <
printf( «Missing pcode file name. \n » );
exit( 1 );
>
const command* pcode = ( const command*) fdata;
int r[ 256 ] = < 0 >; // registers
while (!halted) <
command next = pcode[pc++];
r[next.dest] = ops[next.opcode](r[next.src1], r[next.src2], r[next.dest], next.imm);
>
munmap(( void *)fdata, finfo.st_size);
close(fd);
return 0 ;
>
Фанфары! Запускаем первую в мире программу на джей-скрипе:
]$ bison jsk.y
[tyomitch@home
]$ ./jskc pcode
[tyomitch@home
]$ ./jsk pcode
Задумай число от 0 до 1000, а я буду угадывать
Это 500? (1=меньше, 2=больше, 3=попал) 2
Это 750? (1=меньше, 2=больше, 3=попал) 2
Это 875? (1=меньше, 2=больше, 3=попал) 2
Это 938? (1=меньше, 2=больше, 3=попал) 1
Это 906? (1=меньше, 2=больше, 3=попал) 1
Это 890? (1=меньше, 2=больше, 3=попал) 2
Это 898? (1=меньше, 2=больше, 3=попал) 2
Это 902? (1=меньше, 2=больше, 3=попал) 1
Это 900? (1=меньше, 2=больше, 3=попал) 1
Это 899? (1=меньше, 2=больше, 3=попал) 1
Врёшь, так не бывает!
Если приглядеться к дампу, то можно заметить, что первые 0xa0 байт занимает п-код (четвёрки байтов), а остаток файла — строки в UTF-8.
Backpatching
Сейчас в каждом узле дерева хранится список всех соответствующих ему команд, и каждая реализация emit включает в себя объединение команд из дочерних узлов — в том самом порядке (слева направо), в котором эти узлы создавались во время парсинга. Можно сэкономить и память на хранение команд, и код на их объединение, если все генерируемые команды сразу же сваливать в результат, а в символах хранить только «метаинформацию» типа номеров регистров.
Самая резкая разница — что теперь нам вообще не потребуется дерево: для каждого символа оказывается достаточно хранить один скаляр. Более того: у символов операторов теперь вовсе нет значения — весь результат их разбора немедленно сваливается в вектор готового п-кода; поэтому свёртках, где не генерируется код, даже наследовать ничего не нужно.
Дополнительное преимущество новой системы — что для каждой генерируемой команды сразу известен её адрес, так что для строк сможем хранить не временные «идентификаторы», а списки всех ссылок. Это упростит подстановку адресов строк на заключительном этапе генерации п-кода.
std::vector command > pcode;
std::map vars;
std::map int > > strings;
regnum lastreg = 0 ;
inline regnum newreg() <
if (!++lastreg)
yyerror( «Too many registers used.» );
return lastreg;
>
inline int emit( const command& cmd) <
pcode.push_back(cmd);
return pcode.size()- 1 ;
>
inline int emit(command::opcodes opcode, regnum dest, regnum src1, regnum src2) <
return emit(command(opcode, dest, src1, src2));
>
inline int emit(command::opcodes opcode, regnum dest, short imm) <
return emit(command(opcode, dest, imm));
>
inline void fix( int index, command::opcodes opcode, regnum dest, short imm) <
pcode[index] = command(opcode, dest, imm);
>
%>
%token IF ELSE WHILE EXIT
%token EQ LE GE NE
%token STRING NUM ID
%type str > ID NUM STRING
%type dest > EXPR EXPR1 EXPR2 TERM VAL
%type arg > ARG
%type args > ARGS
%type null > OPS OP1 OP2 OP
%type addr > M N
OPS: OP // no action
| OPS OP // no action
;
OP: OP1 | OP2 ; // no action
>
Код компилятора сократился почти вдвое, а компилирует он точно так же, как и прежде.
Если нет разницы, зачем писать больше?
Байт-код
Байт-код или байтко́д (англ. byte-code ), иногда также используется термин псевдоко́д — машинно-независимый код низкого уровня, генерируемый транслятором и исполняемый интерпретатором. Большинство инструкций байт-кода эквивалентны одной или нескольким командам ассемблера. Трансляция в байт-код занимает промежуточное положение между компиляцией в машинный код и интерпретацией.
Байт-код называется так, потому что длина каждого кода операции — один байт, но длина кода команды различна. Каждая инструкция представляет собой однобайтовый код операции от 0 до 255, за которым следуют такие параметры, как регистры или адреса памяти. Это в типичном случае, но спецификация байт-кода значительно различается в разных языках.
Программа на байт-коде обычно выполняется интерпретатором байт-кода (обычно он называется виртуальной машиной, поскольку подобен компьютеру). Преимущество — в портируемости, т. е. один и тот же байт-код может исполняться на разных платформах и архитектурах. То же самое преимущество дают интерпретируемые языки. Однако, поскольку байт-код обычно менее абстрактный, более компактный и более «компьютерный», чем исходный код, эффективность байт-кода обычно выше, чем чистая интерпретация исходного кода, предназначенного для правки человеком. По этой причине многие современные интерпретируемые языки на самом деле транслируют в байт-код и запускают интерпретатор байт-кода. К таким языкам относятся Perl, PHP, Ruby (начиная с версии 1.9) и Python. Программы на Java обычно передаются на целевую машину в виде байт-кода, который перед исполнением транслируется в машинный код «на лету» — с помощью JIT-компиляции. В стандарте открытых загрузчиков Open Firmware фирмы Sun Microsystems байт-код представляет операторы языка Forth.
В то же время возможно создание процессоров, для которых данный байт-код является непосредственно машинным кодом (такие процессоры существуют, например, для Java и Forth).
Также некоторый интерес представляет p-код (p-code), который похож на байт-код, но физически может быть менее лаконичным и сильно варьироваться по длине инструкции. Он работает на очень высоком уровне, например «напечатать строку» или «очистить экран». P-код повсеместно используется в СУБД и некоторых реализациях BASIC и Паскаля.
Языки и среды программирования, использующие байткод
См. также
Полезное
Смотреть что такое «Байт-код» в других словарях:
БАЙТ-КОД — Иногда используется термин псевдокод машинно независимый код низкого уровня, генерируемый транслятором и исполняемый интерпретатором (англ. byte code) Словарь бизнес терминов. Академик.ру. 2001 … Словарь бизнес-терминов
байт-код — Машинно независимый код, генерируемый Java компилятором. [ГОСТ Р 54456 2011] Тематики телевидение, радиовещание, видео EN byte codeJava byte code … Справочник технического переводчика
Байт-код Java — Байт код Java набор инструкций, исполняемых виртуальной машиной Java. Каждый код операции байт кода один байт. Используются не все 256 возможных значений кодов операций. 51 из них зарезервированы для использования в будущем.… … Википедия
Код (значения) — Код (фр. code, от лат. codex): В Викисловаре есть статья «код» … Википедия
Код операции — Эта статья об инструкциях; о системе команд в целом см.: Машинный код. Код операции, операционный код, опкод часть машинного языка, называемая инструкцией и определяющая операцию, которая должна быть выполнена. Определение и формат кодов… … Википедия
Байт — в запоминающих устройствах наименьшая адресуемая единица данных в памяти ЭВМ, обрабатываемая как единое целое. По умолчанию байт считается равным 8 битам. Обычно в системах кодирования данных байт представляет собой код одного печатного или… … Финансовый словарь
БАЙТ — (англ. byte) набор из стандартного числа (обычно 8) битов (двоичных единиц), используемый как единица количества информации при её передаче, хранении и обработке на ЭВМ. В международных системах кодирования данных (ASCII, EBCDIC) Б. представляет… … Юридическая энциклопедия
Байт — У этого термина существуют и другие значения, см. Byte. Байт (англ. byte) единица хранения и обработки цифровой информации; совокупность битов, обрабатываемая компьютером одномоментно. В современных вычислительных системах байт… … Википедия
Код операции (информатика) — Эта статья об инструкциях; о системе команд в целом см.: Машинный код. В комьютерной отрасли под кодом операции (также операционный код, опкод англ. operation code) понимают часть машинного языка, называемую инструкцией, определяющую операцию,… … Википедия
Промежуточный код — Байт код или байткод (англ. byte code), иногда также используется термин псевдокод машинно независимый код низкого уровня, генерируемый транслятором и исполняемый интерпретатором. Большинство инструкций байт кода эквивалентны одной или нескольким … Википедия
Как объяснить, что такое байткод? [закрыт]
Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы на него можно было дать ответ, основанный на фактах и цитатах.
7 ответов 7
Легко будет объяснить и переносимость. Если человек (секретарша) выучит все коды операций, то она сможет выполнить любую работу, главное, что бы была последовательность кодов. А инженеры могут попробовать спаять-сконструировать устройство, которое будет это исполнять.
@vanyamelikov по-моему вы сами не понимаете что такое байткод Java 🙂
Байткод Java это машинные инструкции для несуществующей Java машины, которую часто называют Java Virtual Machine.
В чем сила брат? А сила брат в том, что вы пишете для некоей Java машины (когда-нибудь кто-нибудь сделает таки физическую Java машину). Что такое портабельность Java кода: это всего лишь вопрос реализации Java машины на какой-то реальной машине ну и т.д.
Я бы попытался объяснить как-то так:
Компьютеры «думают» простейшими инструкциями, и когда вы пишете программу допустим на С то она преобразуется в набор примитивных машинных инструкций. Например было выражение на языке программирования
Оно грубо говоря преобразуется в последовательность инструкций
Так как компьютеры бывают разные то и инструкции которые они используют тоже не всегда одни и те же.
Буду рад услашать критику по поводу подобного объяснения^_^
Я так понимаю, вопрос в том, как объяснить, что такое байт-код, не прибегая к объяснению остального контекста. Мне кажется, что не получится объяснить, что такое байт-код, не объяснив, что такое машинный язык и язык программирования, потому что он ведь не сам по себе, он прослойка между ними — т.е. чтобы понять, что делает прослойка, нужно понять, между чем она лежит.
Самый лучший способ практический:
Зачем придумали байт-код? В начале были интерпретаторы которые просто выполняли код из текста, но так как эффективность в постоянном разборе строк не есть хорошо, придумали работать с байтами, а не как с исходным кодом строк, то есть программа преобразует исходный синтаксис ЯП-а в байт-код где есть инструкции и метки и т.п. почти как в ASM, отсюда и происходит название виртуальная машина, а не интерпретатор, к примеру в Java это JVM. Так что тут всё просто, виртуальная машина при загрузке байт-кода исполняет его. Но это ещё не всё, для большей производительности ввели JIT, то есть компиляции байт-кода в нативный код на ходу исполнения, тем самым не много получаем конкурентоспособность программ к компилируемым ЯП-ам.
Всё ещё ищете ответ? Посмотрите другие вопросы с метками c# c java байткод c++ или задайте свой вопрос.
Похожие
дизайн сайта / логотип © 2021 Stack Exchange Inc; материалы пользователей предоставляются на условиях лицензии cc by-sa. rev 2021.10.12.40432
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Промежуточный код
Многие современные языки программирования, особенно интерпретируемые, используют байт-код для облегчения и ускорения работы интерпретатора. Трансляция в байт-код является методом, промежуточным по эффективности между прямой интерпретацией и компиляцией в машинный код.
Байт-код называется так, потому что длина каждого кода операции традиционно составляет один байт. Каждая инструкция обычно представляет собой однобайтовый код операции (от 0 до 255), за которым могут следовать различные параметры, например, номер регистра или адрес в памяти.
Содержание
Исполнение
Программа на байт-коде обычно выполняется интерпретатором байт-кода. Преимущество байт-кода в большей эффективности и портируемости, то есть один и тот же байт-код может исполняться на разных платформах и архитектурах, для которых реализован интерпретатор. То же самое преимущество дают непосредственно интерпретируемые языки, однако, поскольку байт-код обычно менее абстрактен и более компактен, чем исходный код, эффективность интерпретации байт-кода обычно выше, чем чистая интерпретация исходного кода или интерпретация АСД. Кроме того, интерпретатор байт-кода зачастую проще интерпретатора исходного кода и его проще перенести (портировать) на другую аппаратную платформу.
В высокопроизводительных реализациях виртуальных машин может применяться комбинация интерпретатора и JIT-компилятора, который во время исполнения программы транслирует часто используемые фрагменты байт-кода в машинный код, применяя при этом различные оптимизации. Вместо JIT-компиляции может применяться AOT-компилятор, транслирующий байт-код в машинный код предварительно, до исполнения.
В то же время возможно создание процессоров, для которых данный байт-код является непосредственно машинным кодом (такие экспериментальные процессоры создавались, например, для языков Java и Форт).
История
Варианты p-кода широко использовались в различных реализациях языка Pascal, например, в UCSD p-System (UCSD Pascal). [8]
Применение
К интерпретируемым языкам, использующим байт-код, относятся Perl, PHP (например Zend Engine), Ruby (начиная с версии 1.9), Python, Erlang и многие другие.
Широко распространённые платформы, использующие байт-код [9] :
Компилятор Clipper создает исполняемый файл, в который включен байт-код, транслированный из исходного текста программы, и виртуальная машина, исполняющая этот байт-код.
В ранних реализациях Visual Basic (до версии 6) использовался высокоуровневый Microsoft p-code [9]
Высокоуровневые p-коды и байт коды применялись в СУБД, некоторых реализациях Бейсика и Паскаля.
В стандарте открытых загрузчиков Open Firmware фирмы Sun Microsystems байт-код представляет операторы языка Форт.
Примеры
Python
Критика
Ошибки верификации байт-кода стековых машин приводили к появлению множества экстремально опасных уязвимостей, в частности десятков в виртуальной машине AVM2, используемой в Adobe Flash для исполнения скриптов ActionScript [14] [15] [16] и нескольких в ранних популярных системах исполнения Java (JVM) [17] [18]
В конце 2000-х — начале 2010-х авторы компиляторов V8 (для языка JavaScript, часто реализуемого через байт-код) [19] и Dart [20] усомнились в том, что промежуточные байткоды обязательны для быстрых и эффективных виртуальных машин. В этих проектах была реализована непосредственная JIT-компиляция (компиляция во время исполнения) из исходных кодов сразу в машинный код. [21]