Собранный нами компьютер состоит из реле, проводов, переключателей и лампочек. Все это — аппаратное обеспечение (hardware, или хард) компьютера. Напротив, содержащиеся в памяти коды команд и числа называются программным обеспечением (software, или софт).
Когда мы говорим о компьютерах, термин «программное обеспечение» практически идентичен термину «компьютерная программа» (или просто «программа»). Написание программного обеспечения называется программированием. Именно этим я занимался, когда определял серию команд, позволяющих нашему компьютеру перемножить два числа.
Как правило, в компьютерных программах мы можем различать код (который относится к самим командам) и данные, то есть числа, которыми манипулирует код. Иногда это различие не так очевидно. Например, команда «Остановить» в описанной выше последовательности выступала еще и в качестве числа –1.
Компьютерное программирование иногда называют написанием кода, или кодированием. От программиста вы можете услышать фразы типа: «Я потратил свои каникулы на кодирование», «Я писал код до семи утра». Иногда компьютерных программистов называют кодерами, хотя кому-то этот термин может показаться уничижительным. Такие программисты, возможно, предпочтут, чтобы их называли программными инженерами.
Коды команд, на которые реагирует процессор (например, 10h и 11h, соответствующие командам «Загрузить» и «Сохранить»), называются машинными кодами, или машинным языком. В данном случае термин «язык» используется потому, что он напоминает устный или письменный человеческий язык в том смысле, что машина его «понимает» и реагирует на него.
Для обозначения команд, выполняемых нашей машиной, я использовал довольно длинные фразы вроде «Сложить с переносом». Как правило, команды — это короткие мнемонические коды, написанные заглавными буквами. Мнемокоды могут состоять всего из двух или трех букв. Далее перечислены возможные мнемокоды для команд, распознаваемых нашим компьютером.
Операция
Код
Мнемокод
Загрузить
10h
LOD
Сохранить
11h
STO
Сложить
20h
ADD
Вычесть
21h
SUB
Сложить с переносом
22h
ADC
Вычесть с заимствованием
23h
SBB
Перейти
30h
JMP
Перейти, если 0
31h
JZ
Перейти, если перенос
32h
JC
Перейти, если не 0
33h
JNZ
Перейти, если не перенос
34h
JNC
Остановить
FFh
HLT
Эти мнемокоды особенно полезны, когда используются в сочетании с другими сокращенными обозначениями. Например, вместо длинной команды «Загрузить байт из ячейки 1003h в аккумулятор» можем написать следующее.
LOD A,[1003h]
Обозначения A и [1003h] справа от мнемокода называются аргументами, которые определяют, что конкретно происходит при выполнении команды «Загрузить». При записи аргументов место назначения указывается слева (А — аккумулятор), а источник — справа. Квадратные скобки означают, что в аккумулятор нужно загрузить не число 1003h, а значение, хранящееся в ячейке памяти по адресу 1003h.
Аналогично команду «Сложить байт из ячейки 001Eh со значением в аккумуляторе» можно сократить до такого выражения.
ADD A, [001Eh]
А команду «Сохранить содержимое аккумулятора по адресу 1003h» — до выражения следующего вида.
STO [1003h], A
Обратите внимание: место назначения (ячейка памяти для команды «Сохранить») по-прежнему указывается слева, а источник — справа. Содержимое аккумулятора нужно сохранить в ячейке 1003h. Длинную команду «Перейти к ячейке 0000h, если флаг нуля не равен 1» можно записать кратко.
JNZ 0000h
В этой команде квадратные скобки не используются, поскольку она предполагает переход к ячейке 0000h, а не к значению, которое может в ней храниться.
Такая сокращенная запись удобна, поскольку позволяет перечислить команды в столбик и сделать их легко читаемыми, не прибегая к рисованию ячеек памяти. Для указания ячейки, в которой хранится определенная команда, можете использовать шестнадцатеричный адрес с двоеточием.
0000h: LOD A, [1005h]
А вот так можно указать на данные, хранящиеся по определенному адресу.
1000h: 00h, A7h
1002h: 00h, 1Ch
1004h: 00h, 00h
Два байта, разделенные запятой, указывают на то, что первый хранится в ячейке по адресу слева, а второй — в ячейке, следующей за ней. Эти три строки эквивалентны следующей строке.
1000h: 00h, A7h, 00h, 1Ch, 00h, 00h
Таким образом, программа для умножения двух чисел может быть записана в виде следующей серии команд.
0000h: LOD A, [1005h]
ADD A, [1001h]
STO [1005h], A
LOD A, [1004h]
ADC A, [1000h]
STO [1004h], A
LOD A, [1003h]
ADD A, [001Eh]
STO [1003h], A
JNZ 0000h
001Eh: HLT
1000h: 00h, A7h
1002h: 00h, 1Ch
1004h: 00h, 00h
Пустые строки и другие пробелы применяются для упрощения восприятия. При написании кода лучше не использовать фактические адреса, поскольку они могут измениться. Например, если вы решили сохранить числа в ячейках с 2000h до 20005h, то придется переписывать множество выражений. Лучше использовать метки для обозначения ячеек памяти. Эти метки — просто слова или то, что их напоминает.
BEGIN: LOD A,[RESULT + 1]
ADD A,[NUM1 + 1]
STO [RESULT + 1], A
LOD A,[RESULT]
ADC A,[NUM1]
STO [RESULT], A
LOD A,[NUM2 + 1]
ADD A,[NEG1]
STO [NUM2 + 1], A
JNZ BEGIN
NEG1: HLT
NUM1: 00h, A7h
NUM2: 00h, 1Ch
RESULT: 00h, 00h
Важно: метки NUM1, NUM2 и RESULT ссылаются на ячейки памяти, где хранятся два байта. В приведенных выражениях метки NUM1 + 1, NUM2 + 1 и RESULT + 1 ссылаются на второй байт соответствующей метки. Обратите внимание на метку NEG1 (negative one, то есть «минус один») у команды HLT.