
- •Лекция № 1
- •Тема 1.1. Сущность и роль технологии программирования, языки и системы программирования.
- •Учебные вопросы:
- •Тема 1.1. Сущность и роль технологии программирования, языки и системы программирования.
- •Введение
- •1. История программирования от первых автоматов до первых эвм
- •1.1. О терминах
- •1.2. Ранняя история программирования автоматов
- •1.3. Станки с числовым программным управлением
- •1.4. Вычислительные машины
- •1.5. Двоичная система
- •1.6. Архитектура фон Неймана
- •1.7. Машинный код
- •2. Сущность, роль и основные принципы технологии программирования
- •2.1. Этапы решения задач на эвм
- •2.2. Задачи технологии программирования
- •2.3. Основные принципы технологии программирования
- •3. Основные понятия программирования
- •4. Языки и системы программирования, язык JavaScript
- •4.1. Классификация языков программирования
- •4.2. Характеристика систем программирования на языкахJavaScript/Jscript
1.7. Машинный код
Машинный кодилимашинный язык– это язык, на котором записываются программы для данной машины или данного семейства машин. Этот код определяется набором кодов операций и форматом команд процессора, типом адресации ячеек, форматом представления данных в памяти и пр.
Для примера рассмотрим программу, которая выводит на консоль текст «Hello,world!», для процессора архитектуры x86 фирмыIntelc16-разрядной адресацией. В этой архитектуре адресуемой ячейкой памяти является каждый 8‑разрядный байт. Поле КОП команды занимает первый байт (т.е. допускается не более 28= 256 различных команд), поле адреса – 2 байта (т.е. можно адресовать 216 байтов = 65536 байтов = 64 КБ – длинный адрес) или 1 байт (можно адресовать только 256 байт – короткий адрес).
Первая команда этой программы занимает 3 байта и выглядит в двоичном коде следующим образом:
10111011 |
00010001 |
00000001 |
Для удобства чтения программ программисты записывают их в шестнадцатеричном(16-ричном) коде, заменяя каждую четвёрку битов одной 16-ричной цифрой (всего этих цифр 16), как показано в следующей таблице:
16-ричная цифра |
Двоичное число |
Десятичное число |
0 |
0000 |
0 |
1 |
0001 |
1 |
2 |
0010 |
2 |
3 |
0011 |
3 |
4 |
0100 |
4 |
5 |
0101 |
5 |
6 |
0110 |
6 |
7 |
0111 |
7 |
8 |
1000 |
8 |
9 |
1001 |
9 |
A |
1010 |
10 |
B |
1011 |
11 |
C |
1100 |
12 |
D |
1101 |
13 |
E |
1110 |
14 |
F |
1111 |
15 |
10 |
10000 |
16 |
В любой системе счисления число, следующее за последней цифрой, равно 10, т.е. изображается двумя цифрами (см. в таблице 102, 1010и 1016).
Таким образом, эта команда в 16-ричной системе имеет вид ВВ 11 01. Байты 11 01 образуют здесь двухбайтовое поле адреса. Адрес, указанный в этом поле, – 011116, а не 110116. Чтобы записать правильный адрес, нужно поменять местами байты адресного поля! В десятичной системе этот адрес равен 273.
Вся программа в 16-ричном коде выглядит следующим образом (за программой последует её комментарий):
№ |
Адрес первого байта |
Команды и данные25 | ||
1 |
25610 |
010016 |
BB 11 01 | |
2 |
25910 |
010316 |
B9 0D 00 | |
3 |
26210 |
010616 |
B4 0E | |
4 |
26410 |
010816 |
8A 07 | |
5 |
26610 |
010А16 |
CD 10 | |
6 |
26710 |
010B16 |
43 | |
7 |
26910 |
010D16 |
E2 F9 | |
8 |
27110 |
010F16 |
CD 20 | |
9 |
27310 |
011116 |
48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 |
Программа размещена, начиная с ячейки с адресом 010016, и состоит из 8 команд, занимающих первые 17 байтов. После команд в неё включена выдаваемая строка текста «Hello,world!» – 13 символов (включая пробел). Каждый символ представлен своим 8‑разряднымASCII-кодом (см. любую таблицу символов). Вся строка занимает 1310=D16байтов:
Символы |
H |
e |
l |
l |
o |
, |
|
w |
o |
r |
l |
d |
! |
Их коды |
48 |
65 |
6C |
6C |
6F |
2C |
20 |
57 |
6F |
72 |
6C |
64 |
21 |
Таким образом, вся программа с данными занимает 30 байтов.
Команды с номерами 4 – 7 (выделены жирным шрифтом) повторяются столько раз, сколько символов в выводимой строке (13 раз). Это – цикл.
Комментарии к программе
В программе для передачи данных используются регистры: 8-разрядные – AL,AH(это байты 16-разрядного регистра АХ), 16‑разрядные –BX,CX. РегистрыCXиIP(адрес следующей команды) используются для организации цикла. Команды «знают», какие регистры они используют.
Вывод символа на консоль осуществляется операционной системой (BIOS) с помощью прерывания с номером 1016. Останов программы (возврат управления операционной системеMSDOSпосле завершения программы) осуществляется с помощью прерывания 2016. Команда останова необходима, иначе процессор начнёт следующий байт (4816– символ «Н») рассматривать как код операции, и это может привести к тяжёлым последствиям.
Адрес |
Команды и данные |
Комментарии |
010016 |
BB 11 01 |
Поместить в BX адрес строки (байт с символом «Н» становится текущим) |
010316 |
B9 0D 00 |
Поместить в CX длину строки (000D) |
010616 |
B4 0E |
Поместить в AH номер функции 0E16 прерывания 1016 |
010816 |
8A 07 |
Поместить в AL значение ячейки памяти, адрес которой находится в BX (т.е. текущий символ) |
010А16 |
CD 10 |
Вызов прерывания 1016, которое с помощью регистра АХ выведет текущий символ |
010B16 |
43 |
Увеличить значение ВХ на 1 (сделать текущим следующий байт) |
010D16 |
E2 F9 |
Если CX≠0, то уменьшить CX на 1 и увеличить IP (равный 010F) на F9 (равносильно уменьшению на 7, т.к. F9 – дополнительный код числа -7), т.е. перейти по адресу 010816 – на начало цикла |
010F16 |
CD 20 |
Вызвать прерывание 2016: завершить программу |
011116 |
48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 |
«Hello, world!» |
Этот пример показывает, насколько сложно писать, читать (понимать) и отлаживать программу в машинном коде. Производительность программиста, программирующего в цифровом машинном коде, – всего несколько команд в день. В первых ЭВМ архитектура процессоров была гораздо проще, но пользоваться самим компьютером было значительно сложнее. Но именно такие языки позволяют максимально использовать возможности конкретной машинной архитектуры при создании максимально эффективных программ.
Поэтому уже в начале 1950-х годов стали появляться языки программирования, позволявшие записывать машинные команды и данные не в цифровом виде, в символическом, используя мнемонические имена команд, регистров, ячеек памяти. Эти языки называют языками символического кодирования.Для них создавались программы-трансляторы, преобразующие команды из символической записи в цифровую. Эти трансляторы, а вместе с ними и языки символического кодирования, назывались сначалаавтокодами, а позже ассемблерами(по-русски – «сборщиками»). Появление таких языков и трансляторов стало возможным лишь на машинах с архитектурой фон Неймана благодаря принципу хранимой программы (они и были созданы для первых таких машин26).
Приведём код той же программы на языке ассемблера:
mov bx, HW ; move - переместить
mov cx, 000Dh
mov ah, 0Eh
L: mov al, [bx]
int 10h ; interruption - прерывание
inc bx ; increment – увеличить на 1
loop L ; loop - цикл
int 20h
HW: db 'Hello, World!'
Кроме расшифровки смысла команд, здесь происходит автоматическое определение адресов команд и данных с помощью меток (LиHW). В целом, использование языков символического кодирования увеличило производительность программистов на порядок, сохраняя возможность использования всех особенностей архитектуры вычислительной системы. Таким образом, языки символического кодирования и программы-трансляторы автокоды и ассемблеры стали первым шагомавтоматизации программирования– одной из важнейших составляющих технологии программирования.
Однако, языки ассемблера и написанные на них программы привязаны к конкретной архитектуре вычислительной системы и не годятся для других систем. Кроме того, производительность программистов на ассемблере слишком низкая для написания того объёма программного кода, который требуется в современных условиях. Для удовлетворения этой потребности разрабатываются языки программирования высокого и сверхвысокого уровня – следующие шаги автоматизации программирования. На таких языках предыдущая программа превращается в один простой оператор:
write('Hello, World!')