Можно ли писать программное обеспечение на переносимом машинном языке

Обновлено: 04.07.2024

Интерпретатор переводит Вашу программу с языка высокого уровня (например, БЕЙСИКа) в машинный код последовательно строку за строкой. Он работает примерно так: прочитал строку, проверил, нет ли в ней ошибок, перевел ее в машинный код, выполнил команды машинного кода, запомнил, где нужно результат и перешел к следующей строке. Чтобы сделать, например, операцию

интерпретатор обращается к процессору несколько сот раз. Вам этого не видно, все равно результат появится на экране через доли секунды, но это так.

Если же Вам позже придется вернуться к этой строке (например, с помощью GO TO 10), то все эти действия будут повторены.

А ведь многие операции выполняются в циклах.

В отличие от интерпретатора, компилятор переводит Вашу программу с языка высокого уровня (например, Паскаля или Фортрана) в машинные коды всю целиком. После того, как программа написана, она компилируется в машинный код. Программа, написанная Вами на языке, называется исходным текстом (исходным модулем, исходным блоком, исходным файлом). То, что Вы получаете в результате компиляции, называется объектным кодом (модулем). Вы можете выгрузить объектный код на ленту, а потом снова загрузить. Можете запустить его на исполнение, но здесь у Вас уже нет возможности во время работы программы ее остановить, внести изменения и снова запустить с произвольно взятого места. Если такая необходимость возникает, надо заново загрузить исходный текст программы, внести изменения, а потом опять откомпилировать его в машинный код.

Поскольку здесь компиляция выполняется для каждой строки только один раз, а потом полученный машинный код можно использовать хоть всю жизнь, то здесь скорость работы программы гораздо выше и лишь немного уступает скорости программ, сразу написанных на Ассемблере. Те все же быстрее, т.к. как бы хорош компилятор ни был, он все же не в состоянии сделать объектный код оптимальным по быстродействию и по объему занимаемой памяти.

Итак, программирование в машинном коде (на Ассемблере) позволяет повысить скорость работы программы по сравнению с работой через интерпретатор в 50…200 раз и в 1,5…3 раза по сравнению с кодом, прошедшим компиляцию. Это бывает чрезвычайно важно, если в программе есть многочисленные вложенные друг в друга циклы, если многократно выполняются поиск и выбор данных из обширных областей памяти. Много времени занимают операции, связанные с обработкой графических изображений на экране. Эффект плавного и быстрого перемещения (и изменения формы) объектов в компьютерных видеоиграх практически всегда создается программированием в машинном коде.

Сравним расход памяти при работе на БЕЙСИКе и в машинных кодах. Программа на БЕЙСИКе размером в 30 строк занимает примерно 1К памяти.

Аналогичная ей, выполняющая те же задачи, программа в машинных кодах будет иметь примерно 150 строк (команд), но занимают они всего 200…250 байтов оперативной памяти.

В нашей стране есть еще две объективные причины, вызывающие повышенный интерес к программированию в машинных кодах.

Другая особенность состоит в том, что основная масса программ для Синклер-компьютеров написана в Англии на английском языке. Желание адаптировать эти программы на русский язык во многих случаях упирается в необходимость понимания структуры программы, а большинство лучших программ написано именно в машинных кодах.

Что же касается особой трудоемкости работ по программированию в машинных кодах, то и здесь есть ряд возражений.

· Нет необходимости сразу программировать. На первом этапе Вы уже сможете многого достичь, если будете просто разбираться в программах, а дальше все придет с набором опыта.

· Существуют ассемблирующие программы, которые имеют достаточный набор средств, чтобы освободить Вас от самой рутинной работы и снизить трудоемкость программирования.

· И, наконец, последнее. Ни один программист, работающий в машинных кодах, не пишет большую программу от начала и до конца с чистого листа. Программа представляет хитроумное сплетение больших и малых подпрограмм (процедур), из которых до 80% стали для этого программиста стандартными, т.е. он применяет их регулярно во всех своих программах без особых перемен, а Вы никогда об этом и не догадаетесь. Это могут быть арифметических и логических вычислений, обработки изображений, опроса внешних устройств (например, джойстика), вывода текста на экран, звуковых эффектов и т.д. и т.п.

Основы программирования на машинном языке

Одной из характеристик устройства вычислительной техники является набор команд(инструкций), которыми может оперировать данной устройство. Этот набор получил название система команд. Одной из важнейших характеристик системы команд является ее разрядность. В настоящее время используют без разрядные, одноразрядные, двухразрядные, трехразрядные команды и команды с переменной разрядностью. Структура команд различной разрядности приведена на рисунке 31.

Операнды команд, могут иметь и другой смысл. Так например, при вводе данных, один из операндов будет предназначен не для адресов, а для непосредственно данных.

Рассмотрим простейший пример использования машинного кода, при вводе алгоритма в устройство вычислительной техники. Допустим, что мы имеем устройство вычислительной техники, память которого, состоит из 1000 ячеек, то есть от 000 до 999. Система команд этого устройства представлена в таблице 17. Для простоты восприятия, будем использовать только трехразрядные команды.

Таблица 17. Система команд гипотетического устройства вычислительной техники.

ОперацияКОПНазначение A1Назначение A2Назначение A3
Ввод данныхЯчейка для записиНе используетсяНе используется
СложениеАдрес первого слагаемогоАдрес второго слагаемогоАдрес результата
ВычитаниеАдрес уменьшаемогоАдрес вычитаемогоАдрес результата
УмножениеАдрес первого множителяАдрес второго множителяАдрес результата
ДелениеАдрес делимогоАдрес делителяАдрес результата
ВыводАдрес выводимого значенияНе используетсяНе используется

Рассмотрим теперь использование этой системы команд, так для записи числа 123,45 в ячейку памяти 201, нам необходимо написать следующую команду:

Для сложения данных, находящихся в ячейках 201 и 202, и помещения результата в ячейку 203, необходимо написать следующую команду:

Аналогичным образом выполняются и другие операции в устройствах вычислительной техники.

Рассмотрим разработку простейшего алгоритма, и его ввод в устройство вычислительной техники на языке этого устройства. Для примера возьмем функцию:

Сначала построим алгоритм решения этой задачи. Первым делом, определимся с алгоритмической системой, для этого, разберемся с исходными данными, в заданном выражении они имеют символическое значение a,b,c,d и e, а так же с результатами вычисления, которое имеет символическое значение F. Проанализируем средства и инструменты, которые мы можем использовать, одной из проблем, связанными с программированием в машинном коде, является то, что требуется решать задачу выполняя отдельно каждое действие, то есть инструментами у нас являются простейшие арифметические операции, такие как сложение, вычитание, умножение и деление, глядя на заданное выражение, можно сделать вывод, что для решения задачи этими средствами, нам понадобиться еще один объект, для хранения промежуточного результата, придадим ему символическое название g. Теперь строим, непосредственно алгоритм решения данной задачи, рисунок 32. Для восприятия человека, не имеет значения символическое название объекта, мы воспринимаем и анализируем его суть, в отличие от нас, устройства вычислительной техники понимают только цифры.

Исполнителем алгоритма, является устройство вычислительной техники, которое не понимает, что такое символическое название, оно понимает лишь адреса и цифры. Для них символическим названием объекта является номер его ячейки памяти. Для перевода алгоритма в машинный код, первым делом надо распределить символизированные объекты по адресам, то есть определить, в каком адресе будет храниться значение того лили иного объекта. Выделим под эти нужды ячейки памяти нашего гипотетического устройства вычислительной техники с 201 по 207 и распределим их там, таблица 18 распределение символизированных объектов в памяти устройства.

Теперь рассмотрим этот алгоритм, переведенный на язык исполнителя, которым является наше гипотетическое устройство вычислительной техники, приведенный в таблице 19. Здесь следует учесть и то, что каждая команда(операция) так же располагается в памяти, как и данные, и поэтому должна иметь свой адрес. Отведем под коды операций адресное пространство начиная с 301 ячейки памяти.

Алгоритм вычисления функции в машинном коде


Так составлялись программы для вычислительных машин первого поколения, когда еще не было языков высокого уровня. Это занятие было малоэффективным и очень утомительным. Так же составляются программы сейчас для отдельных элементов устройств вычислительной техники. Но даже с появлением языков высокого уровня, где слова, более понятные человеку ассоциируются с определенным набором команд, устройства вычислительной техники понимают все тот же машинный код, просто перевод в него осуществляет уже не человек, а машина при помощи определенных программ называемых компиляторами.

Принцип выполнения программы устройством вычислительной техники остается неизменным с начала появления первых вычислительных машин рисунок 31, и состоит в следующем:

Более подробно этот процесс можно проследить на графическом отображении алгоритма работы устройства вычислительной техники (рисунок 33). Этот процесс носит название принцип программного управления, и был сформулирован американским ученым Дж. Фон Нейманом и до сих пор служит основой для построения устройств вычислительной техники.

Принцип программного управления состоит в следующем:

ü Деление информации на данные и методы их обработки;

ü Кодирование данных и программы числами;

ü Запись данных и программы в память устройства вычислительной техники;

ü Последующую автоматическую работу устройства по выполнению программы.

Тестовые и контрольные задания по алгоритмическому программированию студенты берут в учебно-практических и методических пособиях [1, 2, 3].

Литература

1. Попов А.А., Якушина Н.А., Роман О.В. Информатика. Учебно-практическое пособие. – М., МГУТУ, 2012. – 78 с.

2. Попов А.А. Программирование на алгоритмическом языке Бейсик.

Методические указания, лабораторный практикум и контрольные задания по

3. Попов А.А. Программирование на алгоритмическом языке Паскаль.

Методические указания, лабораторный практикум и контрольные задания по

Телефоны кафедры Информационных технологий

МГУТУ им. К.Г. Разумовского

Строкалов Владислав Викторович

Основы алгоритмизации и вычислений

Тираж: ____ экз., заказ № ____

Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет

Национальная библиотека им. Н. Э. Баумана
Bauman National Library

Персональные инструменты

Машинный код

Машинный код или машинный язык представляет собой набор инструкций, выполняемых непосредственно центральным процессором компьютера (CPU). Каждая команда выполняет очень конкретную задачу, например, загрузки (load), перехода (jump) или элементарной арифметической или логической операции для единицы данных в регистре процессора или памяти. Каждая программа выполняется непосредственно процессором и состоит из ряда таких инструкций.

Машинный код можно рассматривать как самое низкоуровневое представление скомпилированной или собранной компьютерной программы или в качестве примитивного и аппаратно-зависимого языка программирования. Писать программы непосредственно в машинном коде возможно, однако это утомительно и подвержено ошибкам, так как необходимо управлять отдельными битами и вычислять числовые адреса и константы вручную. По этой причине машинный код практически не используется для написания программ.

Почти все практические программы сегодня написаны на языках более высокого уровня или ассемблере. Исходный код затем транслируется в исполняемый машинный код с помощью таких утилит, как интерпретаторы, компиляторы, ассемблеры, и/или линкеры. [Источник 1]

Содержание

Инструкции машинного кода (ISA)

Системы также могут отличаться в других деталях, таких как расположение памяти, операционные системы или периферийные устройства. Поскольку программа обычно зависит от таких факторов, различные системы, как правило, не запустят один и тот же машинный код, даже если используется тот же тип процессора. [Источник 2]

Виды ISA

Выполнение инструкций

Компьютерная программа представляет собой последовательность команд, которые выполняются процессором. В то время как простые процессоры выполняют инструкции один за другим, суперскалярные процессоры способны выполнять несколько команд одновременно.

Программа может содержать специальные инструкций, которые передают выполнение инструкции, не идущей по порядку вслед за предыдущей. Условные переходы принимаются (выполнение продолжается по другому адресу) или нет (выполнение продолжается на следующей инструкции) в зависимости от некоторых условий.

Абсолютный и позиционно-независимый код

Позиционно-независимый код — программа, которая может быть размещена в любой области памяти, так как все ссылки на ячейки памяти в ней относительные (например, относительно счётчика команд). Такую программу можно переместить в другую область памяти в любой момент, в отличие от перемещаемой программы, которая хотя и может быть загружена в любую область памяти, но после загрузки должна оставаться на том же месте.

Возможность создания позиционно-независимого кода зависит от архитектуры и системы команд целевой платформы. Например, если во всех инструкциях перехода в системе команд должны указываться абсолютные адреса, то код, требующий переходов, практически невозможно сделать позиционно-независимым. В архитектуре x86 непосредственная адресация в инструкциях работы с данными представлена только абсолютными адресами, но поскольку адреса данных считаются относительно сегментного регистра, который можно поменять в любой момент, это позволяет создавать позиционно-независимый код со своими ячейками памяти для данных. Кроме того, некоторые ограничения набора команд могут сниматься с помощью самомодифицирующегося кода или нетривиальных последовательностей инструкций.

Хранение в памяти

Гарвардская архитектура представляет собой компьютерную архитектуру с физически разделенным хранением сигнальных путей для инструкций и данных. На сегодняшний день, в большинстве процессоров реализованы отдельные сигнальные пути для повышения производительности. Модифицированная Гарвардская архитектура поддерживает такие задачи, как загрузка исполняемой программы из дисковой памяти в качестве данных, а затем её выполнение. Гарвардская архитектура контрастирует с архитектурой фон Неймана, где данные и код хранятся в памяти вместе, и считываются процессором, позволяя компьютеру выполнять команды.

С точки зрения процесса, кодовое пространство является частью его адресного пространства, в котором код сохраняется во время исполнения. В многозадачных системах оно включает в себя сегмент кода программы и, как правило, совместно используемые библиотеки. В многопоточной среде различные потоки одного процесса используют кодовое пространство и пространство данных совместно, что повышает скорость переключения потока.

Связь с языками программирования

Ассемблерные языки

Гораздо более читаемым представлением машинного языка называется язык ассемблера, использующий мнемонические коды для обозначения инструкций машинного кода, а не с помощью числовых значений. Например, на процессоре Zilog Z80, машинный код 00000101, который дает указание процессору декрементировать регистр процессора B, будет представлен на языке ассемблера как DEC B.

Связь с микрокодом

В некоторых компьютерных архитектурах, машинный код реализуется с помощью более фундаментального базового слоя программ, называемых микропрограммами, обеспечивающими общий интерфейс машинного языка для линейки различных моделей компьютеров с самыми различными базовыми потоками данных. Это делается для облегчения портирования программ на машинном языке между различными моделями. Примером такого использования являются компьютеры IBM System/360 и их наследники. Несмотря на то, что ширина потоков данных разнится от 8 до 64 бит и более, тем не менее они представляют общую архитектуру на уровне машинного языка по всей линейке.

Использование микрокода для реализации эмулятора позволяет компьютеру симулировать совершенно другую архитектуру. Семейство System / 360 использовало это для портирования программ с более ранних машин IBM на новые семейства компьютеров, например на IBM 1401/1440/1460.

Связь с байткодом

Машинный код, как правило, отличается от байт-кода (также известного как р-код), который либо выполняется интерпретатором, или сам компилируется в машинный код для более быстрого исполнения. Исключением является ситуация, когда процессор предназначен для использования конкретного байт-кода как машинного, например, как в случае с процессорами Java. Машинный и ассемблерный код иногда называют собственным (внутренним) кодом ЭВМ, когда ссылаются на платформо-зависимые части свойств или библиотек языка. [Источник 4]

Примеры

Пример MIPS 32-bit инструкции

Набор инструкций MIPS – пример машинного кода с инструкциями фиксированной длины – 32 бита. Тип инструкции содержится в поле op (поле операции) – первые 6 бит. Например типы инструкций перехода или немедленных операций полностью определяются этим полем. Инструкции регистров включают дополнительное поле funct, для определения конкретной операции. Все поля, использущиеся в данных типах инструкций:

Rs,rt и rd – индикаторы задействования регистров, shamt – параметр сдвига,а поле address/immediate явно содержит операнд.

Пример: сложение значений в регистрах 1 и 2 и запись результата в регистр 6:

Пример: загрузка значения в регистр 8, взятое из ячейки памяти, находящейся на 68 ячеек дальше, чем адрес, находящийся в регистре 3:

Пример: переход к адресу 1024:

Пример для x86 (MS DOS) – “Hello, World!”

BB 11 01 B9 0D 00 B4 0E 8A 07 43 CD 10 E2 F9 CD 20 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21

Данная программа работает при её размещении по смещению 10016. Отдельные инструкции выделены цветом:

Современные компьютеры невероятно быстры и постоянно становятся еще быстрее. Однако они также имеют некоторые существенные ограничения: они изначально понимают только ограниченный набор команд, и им нужно точно сказать, что делать.

Компьютерная программа (также обычно называемая приложением) – это набор инструкций, которые компьютер может выполнить для выполнения некоторой задачи. Процесс создания программы называется программированием. Программисты обычно создают программы, создавая исходный код (обычно сокращено говорят просто код), который представляет собой список команд, введенных в один или несколько текстовых файлов.

Набор физических компонентов компьютера, из которых состоит компьютер, и которые выполняют программы, называется аппаратным обеспечением. Когда компьютерная программа загружается в память и аппаратное обеспечение последовательно выполняет каждую инструкцию, это называется запуском или выполнением программы.

Машинный язык

Центральный процессор (CPU) компьютера не понимает язык C++. Ограниченный набор инструкций, которые CPU может понимать напрямую, называется машинным кодом (или машинным языком, или набором инструкций).

Вот пример инструкции машинного языка: 10110000 01100001 .

Когда были изобретены первые компьютеры, программистам приходилось писать программы непосредственно на машинном коде, что было очень трудно и отнимало много времени.

Как организованы эти инструкции, выходит за рамки данного введения, но интересно отметить две вещи.

Язык ассемблера

Поскольку людям трудно читать и понимать машинный код, был изобретен ассемблер. В языке ассемблера каждая инструкция идентифицируется коротким сокращением (а не набором битов), и могут использоваться имена и другие числа.

Вот та же инструкция, что и выше, но на языке ассемблера: mov al, 061h .

Это сделало разработку намного проще для чтения и записи, чем машинный код. Однако CPU не понимает ассемблер напрямую. Вместо этого программа на ассемблере, прежде чем она сможет быть выполнена компьютером, должна быть переведена на машинный код. Это делается с помощью программы, называемой ассемблером. Программы, написанные на языках ассемблера, обычно бывают очень быстрыми, и ассемблер всё еще используется сегодня, когда очень важна скорость выполнения программы.

Однако у ассемблера всё же есть недостатки. Во-первых, языки ассемблера по-прежнему требуют использования множества инструкций даже для простых задач. Хотя отдельные инструкции в некоторой степени удобочитаемы, понимание того, что делает вся программа, может быть сложной задачей (это немного похоже на попытку понять предложение, рассматривая каждую букву по отдельности). Во-вторых, язык ассемблера по-прежнему не очень портируем – программа, написанная на ассемблере для одного процессора, скорее всего, не будет работать на аппаратном обеспечении, использующем другой набор инструкций, и ее придется переписывать или сильно модифицировать.

Высокоуровневые языки

Чтобы решить проблемы удобочитаемости и переносимости, были разработаны новые языки программирования, такие как C, C++, Pascal (и более поздние языки, такие как Java, Javascript и Perl). Эти языки называются языками высокого уровня, поскольку они разработаны, чтобы позволить программисту писать программы, не беспокоясь о том, на каком компьютере будет выполняться программа.

Вот всё та же инструкция, что и выше, на C/C++: a = 97;

Как и программы на ассемблере, программы, написанные на языках высокого уровня, прежде чем их можно будет запустить, должны быть переведены в формат, понятный компьютеру. Это можно сделать двумя основными способами: компиляция и интерпретация.

Компилятор – это программа, которая читает исходный код и создает автономную исполняемую программу, которую затем можно запустить. После того, как ваш код был преобразован в исполняемый файл, вам не нужен компилятор для запуска программы. Вначале компиляторы были примитивными и создавали медленный, неоптимизированный код. Однако с годами компиляторы стали очень хороши в создании быстрого, оптимизированного кода и в некоторых случаях могут делать его лучше, чем люди, пишущие на ассемблере!

Ниже показано упрощенное представление процесса компиляции:

Рисунок 1 – Пример сборки приложения

Рисунок 1 – Пример сборки приложения

Поскольку программы на C++ обычно компилируются, мы вскоре рассмотрим компиляторы более подробно.

Интерпретатор – это программа, которая непосредственно выполняет инструкции в исходном коде, не требуя их предварительной компиляции в исполняемый файл. Интерпретаторы, как правило, более гибки, чем компиляторы, но менее эффективны при запуске программ, потому что при запуске программы каждый раз должен выполняться процесс интерпретации. Это означает, что при каждом запуске программы требуется интерпретатор.

Ниже показано упрощенное представление процесса интерпретации:

Рисунок 2 – Пример интерпретации

Рисунок 2 – Пример интерпретации

Дополнительная информация

Ни один из подходов не имеет перед другим явного преимущества – если бы один подход всегда был лучше, велика вероятность, что мы стали бы использовать его повсюду!

В целом, компиляторы имеют следующие преимущества:

В целом, у компиляторов есть следующие недостатки:

В целом, у интерпретаторов есть следующие преимущества:

  1. Поскольку они могут читать код в том виде, в каком он написан, и им не нужно выполнять дорогостоящие операции для генерации или оптимизации кода, они, как правило, запускаются быстрее, чем компиляторы.
  2. Поскольку интерпретаторы могут видеть, что делает программа во время ее выполнения, интерпретаторы могут использовать ряд динамических оптимизаций, которые компиляторы могут не видеть.

В целом, у интерпретаторов есть следующие недостатки:

  1. Интерпретаторы обычно используют больше памяти, чем компиляторы, потому, что интерпретатору необходимо хранить больше информации о программе, доступной во время выполнения.
  2. Интерпретаторы обычно тратят некоторое время процессора внутри кода для интерпретатора, что может замедлить выполнение программы.

Многие современные реализации JavaScript используют аналогичные приемы. Большая часть кода JavaScript короткая и не так уж много чего делает, поэтому обычно начинают с интерпретатора. Однако если станет ясно, что код запускается неоднократно, многие JS-движки скомпилируют код (или, по крайней мере, скомпилируют его отдельные части) и оптимизируют его, используя стандартные методы. В конечном итоге код работает быстро при запуске (полезно для быстрой загрузки веб-страниц), а также быстрее работает и при дальнейшем выполнении.

И последняя деталь: языки не компилируются и не интерпретируются. Обычно код C компилируется, но доступны и интерпретаторы C, которые упрощают отладку или визуализацию выполняемого кода (они часто используются при вводном изучении программирования – или, по крайней мере, они использовались раньше). JavaScript считался интерпретируемым языком, пока некоторые JS-движки не начали его компилировать. Некоторые реализации Python являются чисто интерпретаторами, но вы можете найти компиляторы Python, которые генерируют нативный код. Некоторые языки легче компилировать или интерпретировать, чем другие, но ничто не мешает вам создать компилятор или интерпретатор для любого конкретного языка программирования. Теоретический результат, называемый проекциями Футамуры, показывает, что всё, что можно интерпретировать, можно и скомпилировать.

Высокоуровневые языки обладают многими необходимыми свойствами.

Во-первых, на языках высокого уровня намного легче читать и писать, потому что команды ближе к естественному языку, который мы используем каждый день.

Во-вторых, высокоуровневые языки требуют меньшего количества инструкций, чем низкоуровневые языки, для выполнения одной и той же задачи, что делает программы более краткими и легкими для понимания. В C++ вы можете сделать что-то вроде a = b * 2 + 5; в одну строку. На ассемблере для этого потребуется 5 или 6 разных инструкций.

В-третьих, программы можно компилировать (или интерпретировать) для многих различных систем, и вам не нужно изменять программу для работы на разных процессорах (вы просто перекомпилируете ее для конкретного процессора). В качестве примера:

Рисунок 3 – Пример портируемости приложения

Рисунок 3 – Пример портируемости приложения

В портируемости есть два общих исключения. Во-первых, многие операционные системы, такие как Microsoft Windows, содержат специфичные для платформы возможности, которые вы можете использовать в своем коде. Это может значительно упростить написание программы для конкретной операционной системы, но за счет усложнения портируемости. В данной серии статей мы избегаем кода, специфичного для какой-либо платформы.

Некоторые компиляторы также поддерживают специфичные для компилятора расширения – если вы их используете, ваши программы без изменений не смогут компилироваться другими компиляторами, которые не поддерживают те же расширения. Мы поговорим об этом позже, когда вы установите компилятор.

Правила, рекомендации и предупреждения

По мере изучения этих руководств мы будем выделять важные моменты в следующих трех категориях:

Правило

Правила – это инструкции, которые вы должны выполнять в соответствии с требованиями языка. Несоблюдение правил обычно приводит к тому, что ваша программа не работает.

Лучшая практика

Лучшие практики – это то, что вам следует делать, потому что такой способ обычно считается стандартным или настоятельно рекомендуется. То есть либо так поступают все (а если вы поступите иначе, то вы будете делать не то, что ожидают), либо это лучше других альтернатив.

Предупреждение

Предупреждения – это то, чего делать не следует, поскольку они обычно приводят к неожиданным результатам.

1.2 Второе поколение ЭВМ (1955-1965гг)- эра космонавтики - транзисторы и системы пакетной обработки

В Киеве была создана машина Бесселя, которая рассчитывала траектории полёта. Машины обслуживались целой группой людей. Пакетная обработка осуществлялась с помощью пакетов перфокарт.

Компилятор - приложение, которое транслирует исходный код на языке высокого уровня в машинный код.

Задача - совокупность работ, которая должна быть выполнена компьютером.

Транзистор - миниатюрный полупроводниковый переключатель, который пропускает или не пропускает ток, позволяя процессорам выполнять операции, а в памяти ЭВМ хранить данные по битам.

Замечание: транзистор изобретён в США в 1948 году.

Основная дорогостоящая деятельность работы машины - деятельность центрального процессора, т.к. он наиболее сложно организован, эффективен. Для того чтобы увеличить эффективность работы машины, придумали систему пакетной обработки.
Однопоточная система обработки пакетных данных - разновидность ранних компьютерных систем, которая последовательно выполняет ряд неинтерактивных задач (по одной за раз)
Для второго поколения ЭВМ характерно:

- системы ввода-вывода достаточно неэффективные

- для того чтобы повысить эффективность работы ЭВМ, была разработана однопоточная система пакетной обработки

-первая операционная система для компьютера IBM701 (середина 50 годов)

-первые языки программирования (Язык ассемблера, Фортран)

Язык ассемблера – язык низкого уровня, который представляет основные операции компьютера в виде английских сокращений названий команд.

Ассемблер- программа- транслятор, которая переводит программы с языка ассемблера на машинный язык.

Язык программирования высокого уровня - язык программирования, использующий английские идентификаторы и простой синтаксис для написания программы с применением меньшего количества операторов, чем при программировании на языках ассемблера.

Компилятор – приложение, которое транслирует исходный код на языке высокого уровня в машинный код.

Язык Фортран – язык программирования высокого уровня, разработанный компанией IBM в середине 1950- х годов для научных приложений, которые требовали сложных математических вычислений.

Вопросы для самопроверки:
1) Выполняют ли компьютеры программу непосредственно на языке ассемблера?

Нет, не выполняют. Программы – трансляторы осуществляют перевод программы с языка ассемблера на машинный язык, прежде чем её можно будет выполнять.

2) Можно ли писать программное обеспечение на переносимом машинном языке?

Нет, машинные языки являются машинно-зависимыми. Программное обеспечение, написанное на определённом машинном языке, воспринимается только компьютерами одного типа.

1.3 Третье поколение ЭВМ (1965-1980гг)- интегральные схемы и многозадачность

В этот период были разработаны интегральные схемы (это был прорыв)

Интегральная схема - электронное устройство, состоящее из множества транзисторов.

Большие интегральные схемы, на основе которых создавались ЭВМ, повысили производительность вычислений.

Основным представителем того поколения машин- IBM 360.
IBM 360:

- первая линия компьютеров на интегральных схемах, 1964 год

- серия программно совместимых машин разной производительности

- ОС 360 состояла из миллиона строк, написанных на ассемблере тысячами программистов, и содержала тысячи ошибок

Впервые для этих машин был применён принцип многозадачности, т.е. в оперативную память загружалось несколько программ. Другими словами, процессор занимался несколько квантов времени первой программой, а затем запоминал текущее задание, сохранял, переходил ко второй программе, занимался второй программой, запоминал текущее состояние, выгружал и т.д.

Многозадачность - возможность одновременного хранения в памяти большого количества программ таким образом, что они могут выполняться одновременно.
Замечание:

За счёт того, что больше интегральные схемы резко увеличили производительность центральных процессоров, создавалось ощущение, что все это делалось одновременно.

- каждому человеку выдавался доступ на отдельные машины

- изменение ОС, которые должны были делить ресурсы

Многозадачность ОС третьего поколения:

- в разных разделах оперативной памяти одновременно находится ОС и несколько задач, одни из которых ориентированы на вычисления, а другие на ввод-вывод

- пока одна задача ожидает завершения операции ввода-вывода, другая использует центральный процессор

Спулинг- подкачка данных в оперативную память на фоне вычислений процессора.
Спулинг третьего поколения:

- ОС считывает задания с перфокарт на диск в фоновом режиме

- когда текущее состояние задание заканчивается, ОС загружает новое задание с диска в освободившийся раздел оперативной памяти.

1.4 Четвёртое поколение ЭВМ (c 1980)- микросхемы и персональные компьютеры


Микросхема - большая интегральная схема – кремниевое микроминиатюрное электронное устройство, содержащее тысячи транзисторов на одном квадратном сантиметре.

Впервые с 80-х годов была разработана серия персональных компьютеров, концепция ПК.

Это была гениальная система. Она послужила основой для MS-DOS и занимала много места. Те принципы файловой системы и принципы системных вызовов используются до сих пор.

Гэри Килдалл запатентовал эту ОС, организовал фирму, которая называлась Digital Research. По тем временам конкурентов у этой фирмы не было. Это была единственная ОС для ПК.

В 1977 году компания Intel разработала 16-разрядный процессор. Его нужно было протестировать. Опять-таки обратились Гэри Килдаллу. Он на встречу с представителем не пришёл, а отправил своего юриста. Юрист отказался подписывать соглашение о неразглашении коммерческой тайны. В результате договор не был подписан. Фирма обратилась тогда к Биллу Гейтсу, который на тот момент был студентом Гарварда. На тот момент Гейтс создал интерпретатор языка Basic. Фактически, этот интерпретатор послужил основой ОС Microsoft Windows.

Билл Гейтс предложил продавать машины с уже установленными ОС. Это гениальное маркетинговое решение разрушило компанию Гэри Килдалла.

Система использования икон и джойстиков (мышей) была использована при Гейтсе. Компания Apple разработала систему GUID (система интерфейс пользователей с помощью джойстиков). Тогда в Apple решили, что эта система не является эффективной. Именно поэтому все разработки отдали компании Билла Гейтса.

В 1995 году вышла ОС Windows 95. После этого вышла первая ОС, которая полностью была приспособлена под работу в ИНТЕРНЕТЕ.

Возможный Дубликат : Какие языки программирования я могу использовать на Android Dalvik? Я был разработчиком Java в течение 3 лет, теперь я хочу оставить свои навыки Java на некоторое время и перейти на некоторые другие языки (я уже развиваюсь более чем на 8 языках), которые могут быть.

Я собираюсь показать свое невежество здесь, но в свою защиту скажу, что я специализируюсь на бухгалтерском учете и никогда не посещал занятия по информатике. Я собираюсь начать новый проект и подумываю о том, чтобы использовать Python вместо PHP, хотя я гораздо лучше разбираюсь в PHP, потому что.

Переносимость-это не черно-белое, да или нет. Переносимость-это то, как легко можно взять программу и запустить ее на всех платформах, которые вас интересуют.

Есть несколько вещей, которые влияют на это. Один из них-сам язык. Спецификация языка Java обычно оставляет гораздо меньше до "the implementation". Например, "i = i++" не определен в C и C++, но имеет определенное значение в Java. Более практично говоря, такие типы, как "int", имеют определенный размер в Java (например, int всегда 32-битный), в то время как в C и C++ размер варьируется в зависимости от платформы и компилятора. Эти различия сами по себе не мешают вам писать переносимый код в C и C++, но вам нужно быть намного более усердным.

Другой - библиотеки. Java имеет кучу стандартных библиотек, которых нет у C и C++. Например, потоковые, сетевые и библиотеки GUI. Библиотеки такого рода существуют для C и C++, но они не являются частью стандарта, и соответствующие доступные библиотеки могут сильно варьироваться от платформы к платформе.

Наконец, есть целый вопрос о том, можете ли вы просто взять исполняемый файл, перенести его на другую платформу и заставить его работать там. Обычно это работает с Java, предполагая, что для целевой платформы есть JVM. (и есть JVMs для многих/большинства платформ, о которых заботятся люди) Как правило, это неверно для C и C++. Обычно вам, по крайней мере , потребуется перекомпиляция, и это при условии, что вы уже позаботились о предыдущих двух пунктах.

Да, если бы "CVM" существовал для нескольких платформ, это сделало бы C и C++ более переносимыми-вроде того. Вам все равно нужно будет написать код C либо переносимым способом (например, не предполагая ничего о размере int, кроме того, что указано в стандарте), либо вы напишете в CVM (предполагая, что он принял единое решение для всех подобных вещей на всех целевых платформах). Вам также нужно будет отказаться от использования нестандартных библиотек (без сетей, потоков или GUI) или писать в библиотеки, специфичные для CVM, для этих целей. Таким образом, на самом деле мы говорим не о том, чтобы сделать C и C++ более портативными, а о специальном CVM-C/C++, который является портативным.

Опять же, переносимость-это не черно - белая вещь. Даже с Java все еще могут быть несовместимости. Библиотеки GUI (особенно AWT) были печально известны своим непоследовательным поведением, и все, что связано с потоками, может вести себя по-другому, если вы будете небрежны. Однако в целом гораздо проще взять нетривиальную программу Java, написанную на одной платформе, и запустить ее на другой, чем сделать то же самое с программой, написанной на C или C++.

Как уже говорили другие, переносимость-это несколько расплывчатое понятие. С определенной точки зрения C на самом деле более портативен, чем Java. C делает очень мало предположений о базовом оборудовании. Он даже не предполагает, что в байте есть 8 бит или что отрицательные числа должны быть представлены с использованием дополнения два. Теоретически, пока у вас есть машина на основе Фон Неймана и компилятор, вы можете использовать C.

На самом деле программа "Hello world", написанная на C, будет работать на гораздо большем количестве платформ, чем программа "Hello world", написанная на Java. Вероятно, вы могли бы заставить одну и ту же программу "hello world" работать на PDP-11 и iPhone.

Однако реальность такова, что большинство реальных программ делают намного больше , чем вывод "Hello world". Java имеет репутацию более переносимого, чем C, потому что на практике требуется гораздо больше усилий для переноса реальных программ C на разные платформы, чем реальных программ Java.

Это происходит потому, что язык C на самом деле является ANSI-C, который является чрезвычайно универсальным языком с голыми костями. Он не поддерживает сетевое программирование, потоковую обработку или разработку GUI. Поэтому, как только вы напишете программу, которая включает в себя любую из этих вещей, вам придется вернуться к менее переносимому расширению до C, например Win32 или POSIX или что-то еще.

Но в случае Java инструменты сетевого программирования, потоковой обработки и GUI определяются языком и встроены в каждую реализацию VM.

Тем не менее, я думаю, что многие программисты также недооценивают прогресс, достигнутый modern C/C++ в отношении переносимости в наши дни. POSIX имеет большое значение для обеспечения кросс-платформенной потоковой передачи, и когда дело доходит до C++, Boost предоставляет сетевые и потоковые библиотеки, которые в основном так же переносимы, как и все в Java. У этих библиотек есть некоторые специфические для платформы причуды, но и у Java тоже.

На первый взгляд вопрос может показаться глупым, но, возможно, это вовсе не так. Java-это не язык Java, большинство людей знают это, так как вы можете программировать Java с большим количеством других языков , таких как Scala или Groovy Java не является конкретной реализацией VM, поскольку.

Я поражен тем, как Expect (TCL) может автоматизировать множество вещей, которые я обычно не мог сделать. Я думал, что смогу копнуть глубже в Expect, прочитав книгу, но прежде чем я это сделаю, я хочу спросить, есть ли другие решения/языки, которые могли бы делать то, что делает Expect? Например, я.

Когда вы пишете программу Java, она работает на всех платформах, для которых написаны JVM - Windows, Linux, MacOS и т. Д.

Если вы пишете программу C++, вам придется скомпилировать ее специально для каждой платформы.

Теперь говорят, что девиз Java "write once, run everywhere"-это миф. Это не совсем верно для настольных приложений, которые нуждаются во взаимодействии со многими собственными ресурсами, но каждое приложение JavaEE может быть запущено на любой платформе. В настоящее время я работаю над windows, а другие коллеги работают над Linux - без каких-либо проблем.

(Еще одна вещь, связанная с переносимостью, - это JavaEE (enterprise edition). Говорят, что приложения, написанные с использованием технологий JavaEE, запускаются на любом сертифицированном сервере приложений JavaEE. Это, однако, неверно, по крайней мере, до JavaEE6. ( см. Здесь ))

Переносимость-это мера усилий, затрачиваемых на выполнение программы в другой среде, чем та, в которой она была создана.

Теперь вы можете спорить, является ли JVM на Linux другой средой, чем на Windows (я бы сказал, да), но факт остается фактом, что во многих случаях нет никаких усилий, если вы позаботитесь о том, чтобы избежать нескольких ошибок.

CVM, о котором вы говорите, - это во многом то, что пытаются предоставить библиотеки POSIX и библиотеки времени выполнения, однако существуют большие различия в реализации, которые делают препятствия высокими для преодоления. Конечно, в случае Microsoft и Apple это, вероятно, намеренно, чтобы разработчики не выпускали продукты на конкурирующих платформах.

Вы правы, JVM зависит от платформы (это должно быть!), Но когда вы говорите, что Java переносим, вы говорите об этом с точки зрения разработчика, а стандартные разработчики Java не пишут JVM, они используют его: -).

Отредактируйте @Raze2Dust, чтобы ответить на ваш вопрос. Да, вы могли бы. На самом деле, вы можете сделать Java специфичным для платформы, написав компилятор, который будет генерировать машинный код, а не байт-код. Но, как предполагают некоторые другие комментарии, зачем вам это делать? Вам придется создать интерпретатор, который сопоставляет скомпилированный код с операциями таким же образом, как работает JVM. Короче говоря, вы определенно могли бы это сделать, но зачем вам это делать?

Java обеспечивает три различных типа переносимости:

Переносимость исходного кода: Данная программа Java должна давать идентичные результаты независимо от базового компилятора CPU, операционной системы или Java.

переносимость архитектуры CPU: текущие компиляторы Java создают объектный код (называемый байт-кодом) для CPU, который еще не существует. Для каждого реального CPU, на котором должны выполняться Java программ, интерпретатора Java или виртуальной машины "executes" J-код. Этот несуществующий CPU позволяет запускать один и тот же объектный код на любом CPU, для которого существует интерпретатор Java.

Переносимость ОС/графического интерфейса: Java решает эту проблему, предоставляя набор библиотечных функций (содержащихся в библиотеках, поставляемых Java, таких как awt, util и lang), которые взаимодействуют с воображаемым OS и воображаемым GUI. Точно так же, как JVM представляет виртуальный CPU, библиотеки Java представляют виртуальный OS/GUI., каждая реализация Java предоставляет библиотеки, реализующие эти виртуальные программы OS/GUI. Java, которые используют эти библиотеки для обеспечения необходимого порта функциональности OS и GUI довольно легко.

Вы спрашиваете, можно ли написать "C VM". Не совсем. "Java" - это большой термин, используемый Sun для обозначения многих вещей, включая как язык программирования, так и виртуальную машину. "C"-это просто язык программирования: компилятор и OS и CPU должны решить, в каком формате должен быть полученный двоичный файл.

C иногда называют переносимым, потому что он не указывает время выполнения. Люди, написавшие ваш компилятор, смогли выбрать вещи, которые имеют смысл для этой платформы. Недостатком является то, что C достаточно низкоуровневый, а платформы достаточно разные, поэтому для программ C обычно нормально работать в одной системе, а не в другой.

Если вы объедините язык C с конкретным ABI, вы можете определить для него VM, аналогично JVM. Например, уже есть несколько таких вещей, как это:

  • "Intel Binary Compatibility Specification" является примером такого ABI (который сегодня почти никто не использует)
  • "Microsoft Windows" также может быть таким ABI (хотя и огромным и недостаточно определенным), для которого Wine-это один VM, который запускает программы, написанные для него
  • "MS-DOS", для которого dosemu является одним VM
  • "Linux" является одним из наиболее популярных сегодня, чьи программы могут запускаться самим Linux, NetBSD или FreeBSD
  • "PA-RISC", для которого Динамо HP было JIT-подобным VM

Все эти C VMs на самом деле являются реальной машиной-никто, AFAIK, никогда не создавал C виртуальных машин, которые были бы чисто виртуальными. Это неудивительно, поскольку C был разработан для эффективной работы на аппаратном обеспечении, поэтому вы можете также заставить его нормально работать в одной системе. Как показал HP, вы все еще можете сделать JIT для более эффективного выполнения кода, даже на той же платформе.

Вам нужен JVM для разных архитектур, но, конечно, ваши программы Java работают на этом JVM . Поэтому, как только у вас есть JVM для архитектуры, ваши Java программы доступны для этой архитектуры.

Таким образом, я могу написать программу Java, скомпилировать ее до байт-кода Java (который не зависит от архитектуры), и это означает, что я могу запустить ее на любом JVM на любой архитектуре. JVM абстрагирует базовую архитектуру, и моя программа работает на виртуальной машине.

Идея заключается в том, что язык Java переносим (или, точнее, скомпилированный байт-код переносим). Вы правы, что каждый VM требует определенной реализации для данного профиля оборудования. Однако, как только эти усилия будут предприняты, весь байт-код java будет работать на этой платформе. Вы пишете байт-код java/один раз, и он работает на любом JVM.

.NET очень похоже, но с гораздо меньшим акцентом на принципе. CLR аналогичен JVM и имеет свой собственный байт-код. Mono существует на *nix,, но вы правы, что это не "official".

Переносимость или, как написано в Википедии, Переносимость программного обеспечения-это возможность повторного использования одного и того же программного обеспечения (кода) в нескольких средах (OSes). java JVM-это JVM, который может быть запущен в любых операционных системах, для которых он был разработан: Windows, Linux, Mac OSes и т. Д.

Для таких языков, как C++, Pascal и т. Д. вам придется перейти к каждому OS и построить его на этой платформе, чтобы запустить его на этой платформе. Файл EXE в Windows не совпадает с файлом .so в linux (машинный код), поскольку оба используют разные библиотеки для общения с kernel, и каждый OS имеет свой собственный kernel.

НОСИЛ - Пиши Один Раз, Беги Везде

На самом деле это ограничено платформами, у которых есть JVM, но это охватывает большинство платформ, на которых вы хотели бы развернуть. Это почти половина пути между интерпретируемым языком и компилируемым языком, получая преимущества от обоих.

Похожие вопросы:

Я новичок в Java. Меня смущает переносимость Java. Если язык Java переносим, то почему enum неизвестен в J2ME? Я программист C++. В C++ не важно, какая платформа или библиотека используется. C++.

Я смотрел на L.in.oleum и был заинтригован его сочетанием конструкций более высокого уровня (циклы, динамические переменные) с низкоуровневой мощностью ассемблера (регистры). Существуют ли другие.

Возможный Дубликат : Какие языки программирования я могу использовать на Android Dalvik? Я был разработчиком Java в течение 3 лет, теперь я хочу оставить свои навыки Java на некоторое время и.

Я собираюсь показать свое невежество здесь, но в свою защиту скажу, что я специализируюсь на бухгалтерском учете и никогда не посещал занятия по информатике. Я собираюсь начать новый проект и.

На первый взгляд вопрос может показаться глупым, но, возможно, это вовсе не так. Java-это не язык Java, большинство людей знают это, так как вы можете программировать Java с большим количеством.

Я поражен тем, как Expect (TCL) может автоматизировать множество вещей, которые я обычно не мог сделать. Я думал, что смогу копнуть глубже в Expect, прочитав книгу, но прежде чем я это сделаю, я.

Я узнал некоторые java во-первых, и сейчас я учусь PHP. Мне не нравится, как free это, с такими вещами, как свободный набор текста. Мне очень понравилось, как java принуждает вас к хорошей практике.

Я заметил, что такие языки, как Java, имеют примитив char и класс string. Другие языки, такие как Python и Ruby, просто имеют класс string. Вместо этого эти языки используют строку длиной 1 для.

CodenameOne поддерживает компиляцию кода Java вплоть до собственных двоичных файлов iOS. Поддерживает ли он другие языки на основе JVM, такие как Clojure или Jruby ?

Читайте также: