stringtranslate.com

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

В компьютерном программировании язык ассемблера (альтернативно язык ассемблера [1] или символический машинный код ), [2] [3] [4] часто называемый просто ассемблером и обычно сокращенно обозначаемый как ASM или asm , представляет собой любой низкоуровневый язык программирования с очень строгим соответствием между инструкциями в языке и инструкциями машинного кода архитектуры . [5] Язык ассемблера обычно имеет один оператор на машинную инструкцию (1:1), но константы, комментарии , директивы ассемблера [6] символические метки , например, ячеек памяти , регистров и макросов [7] [1] обычно также поддерживаются.

Первый ассемблерный код, в котором язык используется для представления инструкций машинного кода, можно найти в работе Кэтлин и Эндрю Дональда Бута 1947 года «Кодирование для ARC» . [8] Ассемблерный код преобразуется в исполняемый машинный код с помощью служебной программы, называемой ассемблером . Термин «ассемблер» обычно приписывается Уилксу , Уиллеру и Гиллу в их книге 1951 года «Подготовка программ для электронного цифрового компьютера» , [9] которые, однако, использовали этот термин для обозначения «программы, которая собирает другую программу, состоящую из нескольких разделов, в одну программу». [10] Процесс преобразования называется сборкой , как при сборке исходного кода . Вычислительный этап, когда ассемблер обрабатывает программу, называется временем сборки .

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

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

В первые десятилетия вычислительной техники было обычным делом, когда как системное программирование , так и прикладное программирование полностью выполнялось на языке ассемблера. Хотя для некоторых целей он все еще незаменим, большая часть программирования теперь выполняется на интерпретируемых и компилируемых языках более высокого уровня. В « No Silver Bullet » Фред Брукс подытожил последствия перехода от программирования на языке ассемблера: «Безусловно, самым мощным ударом для производительности, надежности и простоты программного обеспечения стало прогрессивное использование языков высокого уровня для программирования. Большинство наблюдателей приписывают этому развитию по крайней мере пятикратный рост производительности и сопутствующий рост надежности, простоты и понятности». [14]

Сегодня типично использовать небольшие объемы кода на языке ассемблера в более крупных системах, реализованных на языке более высокого уровня, по соображениям производительности или для прямого взаимодействия с оборудованием способами, не поддерживаемыми языком более высокого уровня. Например, чуть менее 2% версии 4.9 исходного кода ядра Linux написано на ассемблере; более 97% написано на C. [15 ]

Синтаксис языка ассемблера

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

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

Терминология

Ключевые понятия

Ассемблер

Программа ассемблера создает объектный код , транслируя комбинации мнемоники и синтаксиса для операций и режимов адресации в их числовые эквиваленты. Это представление обычно включает код операцииopcode »), а также другие управляющие биты и данные. Ассемблер также вычисляет константные выражения и разрешает символические имена для ячеек памяти и других сущностей. [20] Использование символических ссылок является ключевой особенностью ассемблеров, экономящей утомительные вычисления и ручные обновления адресов после изменений программы. Большинство ассемблеров также включают макровозможности для выполнения текстовой подстановки — например, для генерации общих коротких последовательностей инструкций как встроенных , вместо вызываемых подпрограмм .

Некоторые ассемблеры также могут выполнять некоторые простые типы оптимизаций , специфичных для набора инструкций . Одним из конкретных примеров этого могут быть вездесущие ассемблеры x86 от различных поставщиков. Называемые jump-sizing , [20] большинство из них способны выполнять замены jump-instruction (длинные переходы заменяются короткими или относительными переходами) в любом количестве проходов по запросу. Другие могут даже выполнять простую перестановку или вставку инструкций, например, некоторые ассемблеры для архитектур RISC , которые могут помочь оптимизировать разумное планирование инструкций для максимально эффективного использования конвейера ЦП . [21]

Ассемблеры были доступны с 1950-х годов, как первый шаг после машинного языка и до языков программирования высокого уровня, таких как Fortran , Algol , COBOL и Lisp . Также существовало несколько классов трансляторов и полуавтоматических генераторов кода со свойствами, аналогичными как ассемблеру, так и языкам высокого уровня, причем Speedcode, возможно, является одним из наиболее известных примеров.

Может быть несколько ассемблеров с различным синтаксисом для конкретного процессора или архитектуры набора инструкций . Например, инструкция по добавлению данных памяти в регистр в процессоре семейства x86 может быть add eax,[ebx]в оригинальном синтаксисе Intel , тогда как это будет написано addl (%ebx),%eaxв синтаксисе AT&T, используемом GNU Assembler . Несмотря на разный внешний вид, различные синтаксические формы обычно генерируют один и тот же числовой машинный код . Один ассемблер может также иметь различные режимы для поддержки вариаций синтаксических форм, а также их точных семантических интерпретаций (таких как FASM -синтаксис, TASM -синтаксис, идеальный режим и т. д. в особом случае программирования ассемблера x86 ).

Количество проходов

Существует два типа ассемблеров, в зависимости от того, сколько проходов по исходному коду необходимо (сколько раз ассемблер читает исходный код) для создания объектного файла.

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

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

Пример: в следующем фрагменте кода однопроходный ассемблер сможет определить адрес обратной ссылки BKWD при сборке оператора S2 , но не сможет определить адрес прямой ссылки FWD при сборке оператора ветвления S1 ; действительно, FWD может быть неопределен. Двухпроходный ассемблер определит оба адреса в проходе 1, поэтому они будут известны при генерации кода в проходе 2.

S1 B ВПЕРЕД ...FWD EQU * ...BKWD EQU * ...S2 B BKWD

Ассемблеры высокого уровня

Более сложные высокоуровневые ассемблеры предоставляют такие языковые абстракции, как:

Более подробную информацию см. в разделе «Проектирование языка» ниже.

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

Программа, написанная на языке ассемблера, состоит из серии мнемонических инструкций процессора и мета-операторов (известных по-разному как декларативные операции, директивы, псевдоинструкции, псевдооперации и псевдооперации), комментариев и данных. Инструкции языка ассемблера обычно состоят из мнемоники кода операции , за которой следует операнд , который может быть списком данных, аргументов или параметров. [24] Некоторые инструкции могут быть «подразумеваемыми», что означает, что данные, с которыми работает инструкция, неявно определены самой инструкцией — такая инструкция не принимает операнд. Результирующий оператор транслируется ассемблером в инструкции машинного языка , которые могут быть загружены в память и выполнены.

Например, инструкция ниже сообщает процессору x86 / IA-32 о необходимости немедленного перемещения 8-битного значения в регистр . Двоичный код этой инструкции — 10110, за которым следует 3-битный идентификатор регистра, который следует использовать. Идентификатор регистра AL — 000, поэтому следующий машинный код загружает регистр AL данными 01100001. [24]

10110000 01100001

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

Б0 61

Здесь B0означает "Переместить копию следующего значения в AL ", и 61является шестнадцатеричным представлением значения 01100001, что равно 97 в десятичной системе счисления . Язык ассемблера для семейства 8086 предоставляет мнемонику MOV (сокращение от move ) для таких инструкций, поэтому машинный код выше можно записать следующим образом на языке ассемблера, дополнив его пояснительным комментарием, если требуется, после точки с запятой. Это гораздо легче читать и запоминать.

MOV AL , 61h ; Загрузка AL с 97 десятичными (61 шестнадцатеричными)   

В некоторых языках ассемблера (включая этот) одна и та же мнемоника, например MOV, может использоваться для семейства связанных инструкций для загрузки, копирования и перемещения данных, будь то непосредственные значения, значения в регистрах или ячейки памяти, на которые указывают значения в регистрах или непосредственные (т.е. прямые) адреса. Другие ассемблеры могут использовать отдельные мнемоники опкодов, например L для «переместить память в регистр», ST для «переместить регистр в память», LR для «переместить регистр в регистр», MVI для «переместить непосредственный операнд в память» и т.д.

Если одна и та же мнемоника используется для разных инструкций, это означает, что мнемоника соответствует нескольким разным двоичным кодам инструкций, за исключением данных (например, 61hв этом примере), в зависимости от операндов, следующих за мнемоникой. Например, для процессоров x86/IA-32 синтаксис языка ассемблера Intel MOV AL, AHпредставляет собой инструкцию, которая перемещает содержимое регистра AH в регистр AL . Шестнадцатеричная форма [nb 3] этой инструкции выглядит так:

88 Э0

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

В таком случае, когда одна и та же мнемоника может представлять более одной двоичной инструкции, ассемблер определяет, какую инструкцию сгенерировать, проверив операнды. В первом примере операнд 61hявляется допустимой шестнадцатеричной числовой константой и не является допустимым именем регистра, поэтому B0применима может быть только инструкция. Во втором примере операнд AHявляется допустимым именем регистра, а не допустимой числовой константой (шестнадцатеричной, десятичной, восьмеричной или двоичной), поэтому 88применима может быть только инструкция.

Языки ассемблера всегда разрабатываются таким образом, чтобы такое отсутствие двусмысленности повсеместно обеспечивалось их синтаксисом. Например, в языке ассемблера Intel x86 шестнадцатеричная константа должна начинаться с цифры, так что шестнадцатеричное число 'A' (равное десятичному десяти) будет записано как 0Ahили 0AH, а не AH, специально для того, чтобы оно не могло показаться именем регистра AH . (То же правило также предотвращает двусмысленность с именами регистров BH , CH и DH , а также с любым определяемым пользователем символом, который заканчивается буквой H и в противном случае содержит только символы, которые являются шестнадцатеричными цифрами, например, слово "BEACH".)

Возвращаясь к исходному примеру, в то время как код операции x86 10110000 ( B0) копирует 8-битное значение в регистр AL , 10110001 ( B1) перемещает его в CL , а 10110010 ( B2) делает это в DL . Ниже приведены примеры на языке ассемблера для них. [24]

MOV AL , 1h ; Загрузка AL с немедленным значением 1 MOV CL , 2h ; Загрузка CL с немедленным значением 2 MOV DL , 3h ; Загрузка DL с немедленным значением 3         

Синтаксис MOV также может быть более сложным, как показывают следующие примеры. [25]

MOV EAX , [ EBX ] ; Переместить 4 байта из памяти по адресу, содержащемуся в EBX, в EAX MOV [ ESI + EAX ], CL ; Переместить содержимое CL в байт по адресу ESI+EAX MOV DS , DX ; Переместить содержимое DX в сегментный регистр DS         

В каждом случае мнемоника MOV транслируется непосредственно в один из кодов операций 88-8C, 8E, A0-A3, B0-BF, C6 или C7 ассемблером, и программисту обычно не нужно знать или помнить, какой именно. [24]

Преобразование языка ассемблера в машинный код является работой ассемблера, а обратное может быть, по крайней мере, частично достигнуто дизассемблером . В отличие от языков высокого уровня , существует однозначное соответствие между многими простыми операторами ассемблера и инструкциями машинного языка. Однако в некоторых случаях ассемблер может предоставлять псевдоинструкции (по сути макросы), которые расширяются в несколько инструкций машинного языка для предоставления обычно необходимой функциональности. Например, для машины, в которой отсутствует инструкция «переход, если больше или равно», ассемблер может предоставлять псевдоинструкцию, которая расширяется до машинных «установить, если меньше» и «переход, если ноль (по результату инструкции набора)». Большинство полнофункциональных ассемблеров также предоставляют богатый макроязык (обсуждается ниже), который используется поставщиками и программистами для генерации более сложного кода и последовательностей данных. Поскольку информация о псевдоинструкциях и макросах, определенных в среде ассемблера, отсутствует в объектной программе, дизассемблер не может реконструировать вызовы макросов и псевдоинструкций, а может только дизассемблировать фактические машинные инструкции, которые ассемблер сгенерировал из этих абстрактных сущностей языка ассемблера. Аналогично, поскольку комментарии в исходном файле языка ассемблера игнорируются ассемблером и не оказывают никакого влияния на генерируемый им объектный код, дизассемблер всегда полностью не может восстановить исходные комментарии.

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

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

Два примера ЦП, которые имеют два разных набора мнемоник, — это семейство Intel 8080 и Intel 8086/8088. Поскольку Intel заявила авторские права на мнемонику своего языка ассемблера (на каждой странице своей документации, опубликованной в 1970-х и начале 1980-х годов, по крайней мере), некоторые компании, которые независимо производили ЦП, совместимые с наборами инструкций Intel, изобрели свои собственные мнемоники. ЦП Zilog Z80 , усовершенствованный Intel 8080A , поддерживает все инструкции 8080A и многие другие; Zilog изобрел совершенно новый язык ассемблера не только для новых инструкций, но и для всех инструкций 8080A. Например, там, где Intel использует мнемоники MOV , MVI , LDA , STA , LXI , LDAX , STAX , LHLD и SHLD для различных инструкций по передаче данных, язык ассемблера Z80 использует мнемонику LD для всех них. Аналогичный случай — процессоры NEC V20 и V30 , улучшенные копии Intel 8086 и 8088 соответственно. Как и Zilog с Z80, NEC изобрела новую мнемонику для всех инструкций 8086 и 8088, чтобы избежать обвинений в нарушении авторских прав Intel. (Сомнительно, могут ли такие авторские права быть действительными, и более поздние компании-производители процессоров, такие как AMD [nb 4] и Cyrix, переиздали мнемонику инструкций Intel x86/IA-32 в точности без разрешения или юридических санкций.) Сомнительно, что на практике многие люди, программировавшие V20 и V30, действительно писали на языке ассемблера NEC, а не Intel; поскольку любые два языка ассемблера для одной и той же архитектуры набора инструкций изоморфны (в некотором роде как английский и Pig Latin ), нет необходимости использовать собственный опубликованный производителем язык ассемблера с продуктами этого производителя.

Языковой дизайн

Основные элементы

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

Мнемоника кодов операций и расширенная мнемоника

Инструкции (операторы) на языке ассемблера, как правило, очень просты, в отличие от таковых в языках высокого уровня . Как правило, мнемоника — это символическое имя для одной исполняемой инструкции машинного языка ( кода операции ), и для каждой инструкции машинного языка определена как минимум одна мнемоника кода операции. Каждая инструкция обычно состоит из операции или кода операции плюс ноль или более операндов . Большинство инструкций ссылаются на одно значение или пару значений. Операнды могут быть непосредственными (значение, закодированное в самой инструкции), регистрами, указанными в инструкции или подразумеваемыми, или адресами данных, расположенных в другом месте хранилища. Это определяется базовой архитектурой процессора: ассемблер просто отражает, как работает эта архитектура. Расширенные мнемоники часто используются для указания комбинации кода операции с определенным операндом, например, ассемблеры System/360 используют Bв качестве расширенной мнемоники для BCс маской 15 и NOP(«NO OPeration» — ничего не делать для одного шага) для BCс маской 0.

Расширенные мнемоники часто используются для поддержки специализированного использования инструкций, часто для целей, не очевидных из названия инструкции. Например, многие процессоры не имеют явной инструкции NOP, но имеют инструкции, которые могут быть использованы для этой цели. В процессорах 8086 инструкция используется для , причем является псевдокодом операции для кодирования инструкции . Некоторые дизассемблеры распознают это и декодируют инструкцию как . Аналогично, ассемблеры IBM для System/360 и System/370 используют расширенные мнемоники и для и с нулевыми масками. Для архитектуры SPARC они известны как синтетические инструкции . [26]xchg ax,axnopnopxchg ax,axxchg ax,axnopNOPNOPRBCBCR

Некоторые ассемблеры также поддерживают простые встроенные макро-инструкции, которые генерируют две или более машинных инструкций. Например, с некоторыми ассемблерами Z80 инструкция ld hl,bcраспознается как генерирующая, ld l,cза которой следует ld h,b. [27] Иногда их называют псевдо-кодами операций .

Мнемоники — это произвольные символы; в 1985 году IEEE опубликовал стандарт 694 для единого набора мнемоник, которые должны использоваться всеми ассемблерами. С тех пор стандарт был отозван.

Директивы по данным

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

Директивы по сборке

Директивы сборки, также называемые псевдокодами операций, псевдооперациями или псевдооперациями, — это команды, данные ассемблеру, «предписывающие ему выполнять операции, отличные от инструкций сборки». [20] Директивы влияют на работу ассемблера и «могут влиять на объектный код, таблицу символов, файл листинга и значения внутренних параметров ассемблера». Иногда термин псевдокод операции зарезервирован для директив, которые генерируют объектный код, например, те, которые генерируют данные. [28]

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

Символические ассемблеры позволяют программистам связывать произвольные имена ( метки или символы ) с ячейками памяти и различными константами. Обычно каждой константе и переменной дается имя, чтобы инструкции могли ссылаться на эти ячейки по имени, тем самым способствуя самодокументированию кода . В исполняемом коде имя каждой подпрограммы связано с ее точкой входа, поэтому любые вызовы подпрограммы могут использовать ее имя. Внутри подпрограмм назначениям GOTO даются метки. Некоторые ассемблеры поддерживают локальные символы , которые часто лексически отличаются от обычных символов (например, использование «10$» в качестве назначения GOTO).

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

Языки ассемблера, как и большинство других компьютерных языков, позволяют добавлять комментарии к исходному коду программы , которые будут игнорироваться во время сборки. Разумное комментирование необходимо в программах на языке ассемблера, поскольку значение и цель последовательности двоичных машинных инструкций может быть трудно определить. «Сырой» (незакомментированный) язык ассемблера, сгенерированный компиляторами или дизассемблерами, довольно трудно читать, когда необходимо внести изменения.

Макросы

Многие ассемблеры поддерживают предопределенные макросы , а другие поддерживают определяемые программистом (и многократно переопределяемые) макросы, включающие последовательности текстовых строк, в которые встроены переменные и константы. Определение макроса чаще всего [nb 5] представляет собой смесь операторов ассемблера, например, директив, символических машинных инструкций и шаблонов для операторов ассемблера. Эта последовательность текстовых строк может включать коды операций или директивы. После определения макроса его имя может использоваться вместо мнемоники. Когда ассемблер обрабатывает такой оператор, он заменяет оператор текстовыми строками, связанными с этим макросом, а затем обрабатывает их так, как если бы они существовали в файле исходного кода (включая, в некоторых ассемблерах, расширение любых макросов, существующих в заменяющем тексте). Макросы в этом смысле относятся к автокодерам IBM 1950-х годов. [29]

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

В языке ассемблера термин «макрос» представляет собой более всеобъемлющее понятие, чем в некоторых других контекстах, таких как препроцессор в языке программирования C , где его директива #define обычно используется для создания коротких однострочных макросов. Инструкции макросов ассемблера, такие как макросы в PL/I и некоторых других языках, могут быть сами по себе длинными «программами», выполняемыми ассемблером путем интерпретации во время сборки.

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

Макроассемблеры часто позволяют макросам принимать параметры . Некоторые ассемблеры включают довольно сложные макроязыки, включающие такие элементы языка высокого уровня, как необязательные параметры, символьные переменные, условные операторы, манипуляции со строками и арифметические операции, которые можно использовать во время выполнения данного макроса, и позволяющие макросам сохранять контекст или обмениваться информацией. Таким образом, макрос может генерировать многочисленные инструкции языка ассемблера или определения данных на основе аргументов макроса. Это может использоваться для генерации структур данных в стиле записей или « развернутых » циклов, например, или может генерировать целые алгоритмы на основе сложных параметров. Например, макрос «сортировки» может принимать спецификацию сложного ключа сортировки и генерировать код, созданный для этого конкретного ключа, не нуждаясь в тестах времени выполнения, которые потребовались бы для общей процедуры, интерпретирующей спецификацию. Организация, использующая язык ассемблера, который был значительно расширен с помощью такого набора макросов, может считаться работающей на языке более высокого уровня, поскольку такие программисты не работают с концептуальными элементами самого низкого уровня компьютера. Подчеркивая этот момент, макросы использовались для реализации ранней виртуальной машины в SNOBOL4 (1967), которая была написана на языке SNOBOL Implementation Language (SIL), языке ассемблера для виртуальной машины. Целевая машина переводила это в свой собственный код с помощью макроассемблера . [ 30] Это обеспечивало высокую степень переносимости для того времени.

Макросы использовались для настройки крупномасштабных программных систем для конкретных клиентов в эпоху мэйнфреймов, а также использовались персоналом клиентов для удовлетворения потребностей своих работодателей путем создания определенных версий операционных систем производителей. Это делалось, например, системными программистами, работающими с IBM Conversational Monitor System / Virtual Machine ( VM/CMS ) и с дополнениями IBM "обработки транзакций в реальном времени", Customer Information Control System CICS и ACP / TPF , системой для авиакомпаний/финансов, которая появилась в 1970-х годах и до сих пор управляет многими крупными системами компьютерного бронирования (CRS) и системами кредитных карт.

Также возможно использовать исключительно возможности обработки макросов ассемблера для генерации кода, написанного на совершенно разных языках, например, для генерации версии программы на COBOL с использованием чистой программы макроассемблера, содержащей строки кода COBOL внутри операторов времени ассемблера, инструктирующих ассемблер о генерации произвольного кода. IBM OS/360 использует макросы для выполнения генерации системы . Пользователь указывает параметры, кодируя серию макросов ассемблера. Сборка этих макросов генерирует поток заданий для сборки системы, включая язык управления заданиями и операторы управления утилитами .

Это потому, что, как было осознано в 1960-х годах, концепция «макрообработки» независима от концепции «ассемблирования», первая из которых в современных терминах больше является обработкой текста, обработкой текста, чем генерацией объектного кода. Концепция макрообработки появилась и появляется в языке программирования C, который поддерживает «инструкции препроцессора» для установки переменных и выполнения условных проверок их значений. В отличие от некоторых предыдущих макропроцессоров внутри ассемблеров, препроцессор C не является полным по Тьюрингу, поскольку ему не хватает возможности зацикливаться или «переходить», последнее позволяет программам зацикливаться.

Несмотря на мощь макрообработки, она вышла из употребления во многих языках высокого уровня (за исключением C , C++ и PL/I), оставаясь при этом неизменной для ассемблеров.

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

foo: макрос анагрузка а*б

Намерение состояло в том, что вызывающий должен был предоставить имя переменной, а «глобальная» переменная или константа b использовалась бы для умножения «a». Если foo вызывается с параметром a-c, происходит макрорасширение load a-c*b. Чтобы избежать любой возможной двусмысленности, пользователи макропроцессоров могут заключать в скобки формальные параметры внутри определений макросов, или вызывающие могут заключать в скобки входные параметры. [31]

Поддержка структурного программирования

Были написаны пакеты макросов, предоставляющие структурированные программные элементы для кодирования потока выполнения. Самый ранний пример этого подхода был в наборе макросов Concept-14 [32] , первоначально предложенном Харланом Миллсом (март 1970 г.) и реализованном Марвином Кесслером в Федеральном системном подразделении IBM, который предоставлял IF/ELSE/ENDIF и аналогичные блоки управления потоком для программ на ассемблере OS/360. Это был способ сократить или исключить использование операций GOTO в коде ассемблера, одного из основных факторов, вызывающих спагетти-код в языке ассемблера. Этот подход был широко принят в начале 1980-х годов (последние дни широкомасштабного использования языка ассемблера). Набор инструментов High Level Assembler Toolkit от IBM [33] включает такой пакет макросов.

Другой проект был A-Natural, [34] «потоковый» ассемблер для процессоров 8080/ Z80 от Whitesmiths Ltd. (разработчиков Unix -подобной операционной системы Idris , и того, что, как сообщалось, было первым коммерческим компилятором C ). Язык был классифицирован как ассемблер, потому что он работал с сырыми машинными элементами, такими как коды операций , регистры и ссылки на память; но он включал синтаксис выражений для указания порядка выполнения. Скобки и другие специальные символы, наряду с блочно-ориентированными структурными программными конструкциями, контролировали последовательность сгенерированных инструкций. A-natural был построен как объектный язык компилятора C, а не для ручного кодирования, но его логический синтаксис завоевал некоторых поклонников.

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

Ассемблеры с мощным макродвижком позволяют осуществлять структурное программирование с помощью макросов, таких как макрос switch, поставляемый с пакетом Masm32 (этот код представляет собой законченную программу):

include \ masm32 \ include \ masm32rt.inc ; использовать библиотеку Masm32 .code demomain: REPEAT 20 switch rv ( nrandom , 9 ) ; сгенерировать число от 0 до 8 mov ecx , 7 case 0 print "case 0" case ecx ; в отличие от большинства других языков программирования, print "case 7" ; переключатель Masm32 допускает "переменные случаи" case 1 .. 3 .if eax == 1 print "case 1" .elseif eax == 2 print "case 2" .else print "cases 1 to 3: other" .endif case 4 , 6 , 8 print "cases 4, 6 or 8" default mov ebx , 19 ; print 20 stars .Repeat print "*" dec ebx .Until Sign? ; цикл до установки флага знака endsw print chr$ ( 13 , 10 ) ENDM exit end demomain                                  

Использование языка ассемблера

Историческая перспектива

Языки ассемблера не были доступны в то время, когда был представлен компьютер с хранимой программой . Программы писались в абсолютном машинном коде и загружались в компьютер с перфоленты или напрямую в память с помощью консольных переключателей. [ необходима ссылка ] Кэтлин Бут «приписывают изобретение языка ассемблера» [37] [38] на основе теоретической работы, которую она начала в 1947 году, работая над ARC2 в Биркбеке, Лондонский университет, после консультации Эндрю Бута (впоследствии ее мужа) с математиком Джоном фон Нейманом и физиком Германом Голдстайном в Институте перспективных исследований . [38] [39]

В конце 1948 года электронный автоматический калькулятор с задержкой хранения (EDSAC) имел ассемблер (названный «начальными заказами»), интегрированный в его программу начальной загрузки . Он использовал однобуквенную мнемонику, разработанную Дэвидом Уилером , которого IEEE Computer Society считает создателем первого «ассемблера». [20] [40] [41] Отчеты по EDSAC ввели термин «ассемблирование» для процесса объединения полей в командное слово. [42] SOAP ( Symbolic Optimal Assembly Program ) был языком ассемблера для компьютера IBM 650, написанным Стэном Поли в 1955 году. [43]

Языки ассемблера устраняют большую часть подверженного ошибкам, утомительного и трудоемкого программирования первого поколения , необходимого для самых первых компьютеров, освобождая программистов от такой скуки, как запоминание числовых кодов и вычисление адресов. Когда-то они широко использовались для всех видов программирования. Однако к концу 1950-х годов [44] их использование в значительной степени было вытеснено языками более высокого уровня в поисках повышения производительности программирования . [ необходима цитата ] Сегодня язык ассемблера по-прежнему используется для прямой манипуляции оборудованием, доступа к специализированным инструкциям процессора или для решения критических проблем производительности. [45] Типичными применениями являются драйверы устройств , низкоуровневые встроенные системы и системы реального времени (см. § Текущее использование).

Многочисленные программы были написаны полностью на языке ассемблера. Burroughs MCP (1961) был первым компьютером, для которого операционная система была разработана не полностью на языке ассемблера; он был написан на Executive Systems Problem Oriented Language (ESPOL), диалекте Algol. Многие коммерческие приложения также были написаны на языке ассемблера, включая большую часть программного обеспечения для мэйнфреймов IBM, написанного крупными корпорациями. COBOL , FORTRAN и некоторые PL/I в конечном итоге вытеснили большую часть этой работы, хотя ряд крупных организаций сохранили инфраструктуры приложений на языке ассемблера вплоть до 1990-х годов.

Язык ассемблера долгое время был основным языком разработки для 8-битных домашних компьютеров, таких как Apple II , Atari 8-битные компьютеры , MSX , ZX Spectrum и Commodore 64. Интерпретируемые диалекты BASIC на этих системах предлагают недостаточную скорость выполнения и недостаточные возможности для полного использования имеющегося оборудования. Эти системы имеют серьезные ограничения по ресурсам, идиосинкразическую архитектуру памяти и отображения и предоставляют ограниченные системные службы. Также существует несколько компиляторов языков высокого уровня, подходящих для использования микрокомпьютеров. Аналогично, язык ассемблера является выбором по умолчанию для 8-битных консолей, таких как Atari 2600 и Nintendo Entertainment System .

Ключевое программное обеспечение для IBM PC-совместимых компьютеров было написано на языке ассемблера, например, MS-DOS , Turbo Pascal и Lotus 1-2-3 . По мере экспоненциального роста скорости компьютеров язык ассемблера стал инструментом для ускорения частей программ, например, рендеринга Doom , а не доминирующим языком разработки. В 1990-х годах язык ассемблера использовался для повышения производительности таких систем, как Sega Saturn [46], и в качестве основного языка для аркадного оборудования на основе интегрированного ЦП/ГП TMS34010, например, Mortal Kombat и NBA Jam .

Текущее использование

Ведутся споры о полезности и производительности языка ассемблера по сравнению с языками высокого уровня. [47]

Хотя язык ассемблера имеет определенные нишевые применения, где он важен (см. ниже), существуют и другие инструменты для оптимизации. [48]

По состоянию на июль 2017 года индекс популярности языков программирования TIOBE ставит язык ассемблера на 11 место, опережая, например, Visual Basic . [49] Ассемблер можно использовать для оптимизации скорости или оптимизации размера. В случае оптимизации скорости современные оптимизирующие компиляторы , как утверждается, [50] преобразуют языки высокого уровня в код, который может работать так же быстро, как рукописный ассемблер, несмотря на контрпримеры, которые можно найти. [51] [52] [53] Сложность современных процессоров и подсистем памяти делает эффективную оптимизацию все более сложной для компиляторов, а также для программистов ассемблера. [54] [55] Более того, рост производительности процессора привел к тому, что большинство ЦП простаивают большую часть времени, [56] с задержками, вызванными предсказуемыми узкими местами, такими как промахи кэша, операции ввода-вывода и подкачка . Это сделало скорость выполнения сырого кода не проблемой для многих программистов.

Существуют некоторые ситуации, в которых разработчики могут выбрать использование языка ассемблера:

Язык ассемблера по-прежнему преподается в большинстве программ по информатике и электронной инженерии . Хотя сегодня немногие программисты регулярно работают с языком ассемблера в качестве инструмента, его основные концепции остаются важными. Такие фундаментальные темы, как двоичная арифметика , распределение памяти , обработка стека , кодирование набора символов , обработка прерываний и проектирование компилятора , было бы трудно изучить подробно без понимания того, как работает компьютер на аппаратном уровне. Поскольку поведение компьютера в основном определяется его набором инструкций, логичным способом изучения таких концепций является изучение языка ассемблера. Большинство современных компьютеров имеют схожие наборы инструкций. Поэтому изучение одного языка ассемблера достаточно, чтобы изучить: I) основные концепции; II) распознавать ситуации, в которых использование языка ассемблера может быть уместным; и III) увидеть, как эффективный исполняемый код может быть создан из языков высокого уровня. [23]

Типичные применения

Смотрите также

Примечания

  1. ^ Помимо метаассемблеров
  2. ^ Однако это не означает, что ассемблерные программы, реализующие эти языки, универсальны.
  3. ^ Это одна из двух избыточных форм этой инструкции, которые работают идентично. 8086 и несколько других ЦП конца 1970-х/начала 1980-х годов имеют избыточность в своих наборах инструкций, поскольку инженерам было проще спроектировать эти ЦП (чтобы они помещались на кремниевых чипах ограниченных размеров) с избыточными кодами, чем устранять их (см. термины don't care ). Каждый ассемблер обычно генерирует только одну из двух или более кодировок избыточных инструкций, но дизассемблер обычно распознает любую из них.
  4. ^ AMD производила процессоры Intel 8086, 8088 и 80286, а также, возможно, процессоры 8080A и 8085A по лицензии Intel, но, начиная с 80386, Intel отказалась делиться своими разработками процессоров x86 с кем-либо — AMD подала в суд по этому поводу за нарушение контракта — и AMD проектировала, производила и продавала 32- и 64-разрядные процессоры семейства x86 без помощи или одобрения Intel.
  5. ^ В 7070 Autocoder определение макроса представляет собой программу-генератор макросов 7070, которую вызывает ассемблер; Autocoder предоставляет специальные макросы для использования макрогенераторами.

Ссылки

  1. ^ ab "Язык ассемблера". High Level Assembler for z/OS & z/VM & z/VSE Language Reference Version 1 Release 6. IBM . 2014 [1990]. SC26-4940-06.
  2. ^ "Assembly: Review" (PDF) . Компьютерные науки и инженерия. Инженерный колледж, Университет штата Огайо . 2016. Архивировано (PDF) из оригинала 2020-03-24 . Получено 2020-03-24 .
  3. ^ Арчер, Бенджамин (ноябрь 2016 г.). Язык ассемблера для студентов. Северный Чарльстон, Южная Каролина, США: CreateSpace Independent Publishing . ISBN 978-1-5403-7071-6. Язык ассемблера также можно назвать символическим машинным кодом.
  4. ^ Streib, James T. (2020). "Руководство по языку ассемблера". Темы бакалавриата по информатике . Cham: Springer International Publishing. doi : 10.1007/978-3-030-35639-2. ISBN 978-3-030-35638-5. ISSN  1863-7310. S2CID  195930813. Программирование на языке ассемблера имеет те же преимущества, что и программирование на машинном языке, за исключением того, что оно проще.
  5. ^ Саксон, Джеймс А.; Плетт, Уильям С. (1962). Программирование IBM 1401, самоучитель программирования. Энглвуд Клиффс, Нью-Джерси, США: Prentice-Hall . LCCN  62-20615.(Примечание. Использование термина «программа на ассемблере» .)
  6. ^ Корнелис, А. Ф. (2010) [2003]. "High Level Assembler – Opcodes Overview, Assembler Directives". Архивировано из оригинала 2020-03-24 . Получено 2020-03-24 .
  7. ^ "Макроинструкции". High Level Assembler for z/OS & z/VM & z/VSE Language Reference Version 1 Release 6. IBM . 2014 [1990]. SC26-4940-06.
  8. ^ Бут, Эндрю Д.; Бриттен, Кэтлин Х.В. (1947). Кодирование для ARC (PDF) . Институт перспективных исследований, Принстон . Получено 04.11.2022 .
  9. ^ Уилкс, Морис Винсент ; Уилер, Дэвид Джон ; Гилл, Стэнли Дж. (1951). Подготовка программ для электронного цифрового компьютера (Переиздание 1982 г.). Tomash Publishers . ISBN 978-0-93822803-5. OCLC  313593586.
  10. ^ Фэрхед, Гарри (2017-11-16). "История компьютерных языков - Классическое десятилетие, 1950-е". Я Программист . Архивировано из оригинала 2020-01-02 . Получено 2020-03-06 .
  11. ^ "Как языки ассемблера зависят от операционных систем?". Stack Exchange . Stack Exchange Inc. 2011-07-28. Архивировано из оригинала 2020-03-24 . Получено 2020-03-24 .(Примечание. Системные вызовы часто различаются, например, для MVS , VSE и VM/CMS; двоичные/исполняемые форматы для разных операционных систем также могут различаться.)
  12. ^ Austerlitz, Howard (2003). «Языки программирования компьютеров». Методы сбора данных с использованием ПК . Elsevier. стр. 326–360. doi :10.1016/b978-012068377-2/50013-9. ISBN 9780120683772. Язык ассемблера (или ассемблер) — это компилируемый низкоуровневый компьютерный язык. Он зависит от процессора, поскольку он в основном транслирует мнемоники ассемблера непосредственно в команды, которые понимает конкретный процессор, на основе один к одному. Эти мнемоники ассемблера являются набором инструкций для этого процессора.
  13. ^ Карнс, Бо (2022-04-27). "Изучайте программирование на языке ассемблера с помощью ARM". freeCodeCamp.org . Получено 2022-06-21 . Язык ассемблера часто специфичен для конкретной компьютерной архитектуры, поэтому существует несколько типов языков ассемблера. ARM становится все более популярным языком ассемблера.
  14. ^ Брукс, Фредерик П. (1986). «Серебряной пули нет — сущность и случайность в программной инженерии». Труды Десятой всемирной компьютерной конференции IFIP . С. 1069–1076.
  15. ^ Ангиано, Рикардо. "linux kernel mainline 4.9 sloccount.txt". Gist . Получено 2022-05-04 .
  16. ^ Daintith, John, ed. (2019). "мета-ассемблер". Словарь вычислительной техники . Архивировано из оригинала 2020-03-24 . Получено 2020-03-24 .
  17. ^ Xerox Data Systems (октябрь 1975 г.). Xerox Meta-Symbol Sigma 5-9 Computers Language and Operations Reference Manual (PDF) . стр. vi. Архивировано (PDF) из оригинала 2022-10-09 . Получено 2020-06-07 . Используемый как метаассемблер, он позволяет пользователю разрабатывать собственные языки программирования и генерировать процессоры для таких языков с минимальными усилиями.
  18. ^ Sperry Univac Computer Systems (1977). Sperry Univac Computer Systems Meta-Assembler (MASM) Programmer Reference (PDF) . Архивировано (PDF) из оригинала 2022-10-09 . Получено 2020-06-07 .
  19. ^ "Как использовать встроенный язык ассемблера в коде C". gnu.org . Получено 2020-11-05 .
  20. ^ abcd Salomon, David (февраль 1993) [1992]. Написано в Калифорнийском государственном университете, Нортридж, Калифорния, США. Chivers, Ian D. (ред.). Assemblers and Loaders (PDF) . Ellis Horwood Series In Computers And Their Applications (1-е изд.). Чичестер, Западный Суссекс, Великобритания: Ellis Horwood Limited / Simon & Schuster International Group . стр. 7, 237–238. ISBN 0-13-052564-2. Архивировано (PDF) из оригинала 2020-03-23 ​​. Получено 2008-10-01 .(xiv+294+4 страницы)
  21. ^ Финлейсон, Ян; Дэвис, Брэндон; Гэвин, Питер; Ух, Ганг-Рюнг; Уолли, Дэвид; Шеландер, Магнус; Тайсон, Гэри (2013). «Повышение эффективности процессора путем статической конвейеризации инструкций». Труды 14-й конференции ACM SIGPLAN/SIGBED по языкам, компиляторам и инструментам для встраиваемых систем . стр. 33–44. doi :10.1145/2465554.2465559. ISBN 9781450320856. S2CID  8015812.
  22. ^ Бек, Леланд Л. (1996). "2". Системное программное обеспечение: Введение в системное программирование . Эддисон Уэсли .
  23. ^ ab Hyde, Randall (сентябрь 2003 г.) [1996-09-30]. "Предисловие ("Зачем кому-то изучать эту ерунду?") / Глава 12 – Классы и объекты". Искусство языка ассемблера (2-е изд.). No Starch Press . ISBN 1-886411-97-2. Архивировано из оригинала 2010-05-06 . Получено 2020-06-22 .Опечатки: [1] (928 страниц) [2][3]
  24. ^ abcd Руководство разработчика программного обеспечения для архитектуры Intel, том 2: Справочник по набору инструкций (PDF) . Том 2. Корпорация Intel . 1999. Архивировано из оригинала (PDF) 2009-06-11 . Получено 2010-11-18 .
  25. ^ Феррари, Адам; Батсон, Алан; Лэк, Майк; Джонс, Анита (19.11.2018) [Весна 2006]. Эванс, Дэвид (ред.). "Руководство по сборке x86". Компьютерные науки CS216: Представление программ и данных. Университет Вирджинии . Архивировано из оригинала 24.03.2020 . Получено 18.11.2010 .
  26. ^ "The SPARC Architecture Manual, Version 8" (PDF) . SPARC International . 1992. Архивировано из оригинала (PDF) 2011-12-10 . Получено 2011-12-10 .
  27. ^ Moxham, James (1996). "ZINT Z80 Interpreter". Коды операций Z80 для ZINT . Архивировано из оригинала 2020-03-24 . Получено 2013-07-21 .
  28. ^ Хайд, Рэндалл . "Глава 8. MASM: Директивы и псевдокоды операций" (PDF) . Искусство программирования компьютеров . Архивировано (PDF) из оригинала 2020-03-24 . Получено 2011-03-19 .
  29. ^ 1401 Autocoder System, программа № 1401-AU-037, версия 3, уровень модификации 11 (PDF) . 1965-12-07 . Получено 2024-01-21 . В отношении использования 1401 Autocoder при кодировании макрокоманд действуют следующие незначительные ограничения...
  30. ^ Грисволд, Ральф Э. (1972). "Глава 1". Макрореализация SNOBOL4 . Сан-Франциско, Калифорния, США: WH Freeman and Company . ISBN 0-7167-0447-1.
  31. ^ "Макросы (C/C++), библиотека MSDN для Visual Studio 2008". Microsoft Corp. 2012-11-16. Архивировано из оригинала 2020-03-24 . Получено 2010-06-22 .
  32. ^ Кесслер, Марвин М. (1970-12-18). "*Концепция* Отчет 14 - Реализация макросов для разрешения структурного программирования в OS/360". MVS Software: Макросы концепции 14. Гейтерсберг, Мэриленд, США: International Business Machines Corporation . Архивировано из оригинала 24.03.2020 . Получено 25.05.2009 .
  33. ^ "High Level Assembler Toolkit Feature Increases Programmer Productivity". Письма-объявления . IBM . 1995-12-12. A95-1432. Архивировано из оригинала 2023-03-07.
  34. ^ Whitesmiths Ltd (1980-07-15). Справочное руководство по естественному языку.
  35. ^ "язык ассемблера: определение и многое другое из Answers.com". answers.com . Архивировано из оригинала 2009-06-08 . Получено 2008-06-19 .
  36. ^ Провинчиано, Брайан (17.04.2005). "NESHLA: The High Level, Open Source, 6502 Assembler for the Nintendo Entertainment System". Архивировано из оригинала 24.03.2020 . Получено 24.03.2020 .
  37. ^ Дюфрен, Стивен (21.08.2018). «Кэтлин Бут: сборка ранних компьютеров с изобретением сборки». Архивировано из оригинала 24.03.2020 . Получено 10.02.2019 .
  38. ^ ab Booth, Andrew Donald ; Britten, Kathleen Hylda Valerie (сентябрь 1947 г.) [август 1947 г.]. Общие соображения по проектированию универсального электронного цифрового компьютера (PDF) (2-е изд.). Институт перспективных исследований, Принстон, Нью-Джерси, США: Биркбек-колледж, Лондон . Архивировано (PDF) из оригинала 2020-03-24 . Получено 2019-02-10 . Неоригинальные идеи, содержащиеся в следующем тексте, были получены из ряда источников, ... Однако считается, что следует выразить признательность профессору Джону фон Нейману и доктору Герману Гольдштейну за множество плодотворных обсуждений ...
  39. ^ Кэмпбелл-Келли, Мартин (апрель 1982 г.). «Развитие компьютерного программирования в Великобритании (1945–1955 гг.)». IEEE Annals of the History of Computing . 4 (2): 121–139. doi :10.1109/MAHC.1982.10016. S2CID  14861159.
  40. ^ Кэмпбелл-Келли, Мартин (1980). «Программирование EDSAC: ранняя программная деятельность в Кембриджском университете». IEEE Annals of the History of Computing . 2 (1): 7–36. doi :10.1109/MAHC.1980.10009.
  41. ^ "Премия "Пионер компьютерных наук" 1985 года "За программирование на языке ассемблера" Дэвид Уилер". 2018-03-27.
  42. ^ Уилкс, Морис Винсент (1949). «EDSAC – электронная вычислительная машина». Журнал научных приборов . 26 (12): 385–391. Bibcode : 1949JScI...26..385W. doi : 10.1088/0950-7671/26/12/301.
  43. ^ da Cruz, Frank (2019-05-17). "Магнитный барабанный калькулятор IBM 650". История вычислений - хронология вычислений. Колумбийский университет . Архивировано из оригинала 2020-02-15 . Получено 2012-01-17 .
  44. ^ Эйбелл, Джон К. "15 октября 1956 г.: Fortran навсегда меняет судьбу вычислений". Wired . ISSN  1059-1028 . Получено 2024-03-02 .
  45. ^ Коллен, Моррис Ф. (март–апрель 1994 г.). «Истоки информатики». Журнал Американской ассоциации медицинской информатики . 1 (2): 96–97. doi :10.1136/jamia.1994.95236152. PMC 116189. PMID  7719803 . 
  46. ^ Pettus, Sam (2008-01-10). "SegaBase Volume 6 - Saturn". Архивировано из оригинала 2008-07-13 . Получено 2008-07-25 .{{cite web}}: CS1 maint: неподходящий URL ( ссылка )
  47. ^ Каулер, Барри (1997-01-09). Windows Assembly Language и системное программирование: 16- и 32-битное низкоуровневое программирование для ПК и Windows. CRC Press . ISBN 978-1-48227572-8. Получено 24.03.2020 . Всегда ведутся споры о применимости языка ассемблера в нашем современном мире программирования.
  48. ^ Hsieh, Paul (2020-03-24) [2016, 1996]. "Programming Optimization". Архивировано из оригинала 2020-03-24 . Получено 2020-03-24 . ... изменения в конструкции, как правило, влияют на производительность больше, чем ... не следует переходить сразу к языку ассемблера, пока ...
  49. ^ "TIOBE Index". TIOBE Software . Архивировано из оригинала 2020-03-24 . Получено 2020-03-24 .
  50. ^ Rusling, David A. (1999) [1996]. "Глава 2. Основы программного обеспечения". Ядро Linux . Архивировано из оригинала 2020-03-24 . Получено 2012-03-11 .
  51. ^ ab Markoff, John Gregory (28.11.2005). «Writing the Fastest Code, by Hand, for Fun: A Human Computer Keeps Speeding Up Chips». The New York Times . Сиэтл, Вашингтон, США. Архивировано из оригинала 23.03.2020 . Получено 04.03.2010 .
  52. ^ "Bit-field-badness". hardwarebug.org . 2010-01-30. Архивировано из оригинала 2010-02-05 . Получено 2010-03-04 .
  53. ^ "GCC создает беспорядок". hardwarebug.org . 2009-05-13. Архивировано из оригинала 2010-03-16 . Получено 2010-03-04 .
  54. ^ Хайд, Рэндалл . "Великий спор". Архивировано из оригинала 2008-06-16 . Получено 2008-07-03 .
  55. ^ "Code sourcery снова дает сбой". hardwarebug.org . 2010-01-30. Архивировано из оригинала 2010-04-02 . Получено 2010-03-04 .
  56. ^ Клик, Клифф; Гетц, Брайан. «Ускоренный курс по современному оборудованию». Архивировано из оригинала 2020-03-24 . Получено 2014-05-01 .
  57. ^ "Программирование 68K в Fargo II". Архивировано из оригинала 2008-07-02 . Получено 2008-07-03 .
  58. ^ "BLAS Benchmark-August2008". eigen.tuxfamily.org. 2008-08-01. Архивировано из оригинала 2020-03-24 . Получено 2010-03-04 .
  59. ^ "x264.git/common/x86/dct-32.asm". git.videolan.org. 2010-09-29. Архивировано из оригинала 2012-03-04 . Получено 2010-09-29 .
  60. ^ "rav1e/README.md в v0.6.3". GitHub . Архивировано из оригинала 2023-02-22 . Получено 2023-02-21 .
  61. ^ "README.md · 1.1.0 · VideoLAN / dav1d". 2023-02-13. Архивировано из оригинала 2023-02-22 . Получено 2023-02-21 .
  62. ^ Босворт, Эдвард (2016). «Глава 1 – Зачем изучать язык ассемблера». www.edwardbosworth.com . Архивировано из оригинала 2020-03-24 . Получено 2016-06-01 .
  63. ^ "z/OS Version 2 Release 3 DFSMS Macro Instructions for Data Sets" (PDF) . IBM. 2019-02-15. Архивировано (PDF) из оригинала 2021-06-25 . Получено 2021-09-14 .
  64. ^ Пол, Маттиас Р. (2001) [1996], "Спецификация и справочная документация для NECPINW", NECPINW.CPI - драйвер переключения кодовой страницы DOS для NEC Pinwriters (ред. 2.08), FILESPEC.TXT, NECPINW.ASM, EUROFONT.INC из NECPI208.ZIP, заархивировано из оригинала 2017-09-10 , извлечено 2013-04-22
  65. ^ Пол, Маттиас Р. (2002-05-13). "[fd-dev] mkeyb". freedos-dev . Архивировано из оригинала 2018-09-10 . Получено 2018-09-10 .

Дальнейшее чтение

Внешние ссылки

Смотрите также