Программирование на Ассемблере для начинающих с примерами программ
Многие считают, что Assembler – уже устаревший и нигде не используемый язык, однако в основном это молодые люди, которые не занимаются профессионально системным программированием. Разработка ПО, конечно, хорошо, но в отличие от высокоуровневых языков программирования, Ассемблер научит глубоко понимать работу компьютера, оптимизировать работку с аппаратными ресурсами, а также программировать любую технику, тем самым развиваясь в направлении машинного обучения. Для понимания этого древнего ЯП, для начала стоит попрактиковаться с простыми программами, которые лучше всего объясняют функционал Ассемблера.
IDE для Assembler
Первый вопрос: в какой среде разработки программировать на Ассемблере? Ответ однозначный – MASM32. Это стандартная программа, которую используют для данного ЯП. Скачать её можно на официальном сайте masm32.com в виде архива, который нужно будет распаковать и после запустить инсталлятор install.
Перед работой главное не забыть дописать в системную переменную PATH строчку:
С:\masm32\bin
Программа «Hello world» на ассемблере
Считается, что это базовая программа в программировании, которую начинающие при знакомстве с языком пишут в первую очередь. Возможно, такой подход не совсем верен, но так или иначе позволяет сразу же увидеть наглядный результат:
.386 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib .data msg_title db "Title", 0 msg_message db "Hello world", 0 .code start: invoke MessageBox, 0, addr msg_message, addr msg_title, MB_OK invoke ExitProcess, 0 end start
Для начала запускаем редактор qeditor.
exe в папке с установленной MASM32, и в нём пишем код программы. После сохраняем его в виде файла с расширением «.asm», и билдим программу с помощью пункта меню «Project» → «Build all». Если в коде нет ошибок, программа успешно скомпилируется, и на выходе мы получим готовый exe-файл, который покажет окно Windows с надписью «Hello world».Сложение двух чисел на assembler
В этом случае мы смотрим, равна ли сумма чисел нулю, или же нет. Если да, то на экране появляется соответствующее сообщение об этом, и, если же нет – появляется иное уведомление.
.486 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data .code start: mov eax, 123 mov ebx, -90 add eax, ebx test eax, eax jz zero invoke MessageBox, 0, chr$("В eax не 0!"), chr$("Info"), 0 jmp lexit zero: invoke MessageBox, 0, chr$("В eax 0!"), chr$("Info"), 0 lexit: invoke ExitProcess, 0 end start
Здесь мы используем так называемые метки и специальные команды с их использованием (jz, jmp, test). Разберём подробнее:
- test – используется для логического сравнения переменных (операндов) в виде байтов, слов, или двойных слов. Для сравнения команда использует логическое умножение, и смотрит на биты: если они равны 1, то и бит результата будет равен 1, в противном случае – 0. Если мы получили 0, ставятся флаги совместно с ZF (zero flag), которые будут равны 1. Далее результаты анализируются на основе ZF.
- jnz – в случае, если флаг ZF нигде не был поставлен, производится переход по данной метке. Зачастую эта команда применяется, если в программе есть операции сравнения, которые как-либо влияют на результат ZF. К таким как раз и относятся test и cmp.
- jz – если флаг ZF всё же был установлен, выполняется переход по метке.
- jmp – независимо от того, есть ZF, или же нет, производится переход по метке.
Программа суммы чисел на ассемблере
Примитивная программа, которая показывает процесс суммирования двух переменных:
.486 . model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data msg_title db "Title", 0 A DB 1h B DB 2h buffer db 128 dup(?) format db "%d",0 .code start: MOV AL, A ADD AL, B invoke wsprintf, addr buffer, addr format, eax invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK invoke ExitProcess, 0 end start
В Ассемблере для того, чтобы вычислить сумму, потребуется провести немало действий, потому как язык программирования работает напрямую с системной памятью. Здесь мы по большей частью манипулируем ресурсами, и самостоятельно указываем, сколько выделить под переменную, в каком виде воспринимать числа, и куда их девать.
Получение значения из командной строки на ассемблере
Одно из важных основных действий в программировании – это получить данные из консоли для их дальнейшей обработки. В данном случае мы их получаем из командной строки и выводим в окне Windows:
.486 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data .code start: call GetCommandLine ; результат будет помещен в eax push 0 push chr$("Command Line") push eax ; текст для вывода берем из eax push 0 call MessageBox push 0 call ExitProcess end start
Также можно воспользоваться альтернативным методом:
.486 . model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data .code start: call GetCommandLine ; результат будет помещен в eax invoke GetCommandLine invoke MessageBox, 0, eax, chr$("Command Line"), 0 invoke ExitProcess, 0 push 0 call ExitProcess end start
Здесь используется invoke – специальный макрос, с помощью которого упрощается код программы. Во время компиляции макрос-команды преобразовываются в команды Ассемблера. Так или иначе, мы пользуемся стеком – примитивным способом хранения данных, но в тоже время очень удобным. По соглашению stdcall, во всех WinAPI-функциях переменные передаются через стек, только в обратном порядке, и помещаются в соответствующий регистр eax.
Циклы в ассемблере
Вариант использования:
.data msg_title db "Title", 0 A DB 1h buffer db 128 dup(?) format db "%d",0 .code start: mov AL, A .REPEAT inc AL .UNTIL AL==7 invoke wsprintf, addr buffer, addr format, AL invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK invoke ExitProcess, 0 end start
.data msg_title db "Title", 0 buffer db 128 dup(?) format db "%d",0 .code start: mov eax, 1 mov edx, 1 .WHILE edx==1 inc eax .IF eax==7 .BREAK .ENDIF .ENDW invoke wsprintf, addr buffer, addr format, eax invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK invoke ExitProcess, 0
Для создания цикла используется команда repeat. Далее с помощью inc увеличивается значение переменной на 1, независимо от того, находится она в оперативной памяти, или же в самом процессоре.
Сумма элементов массива на assembler
Здесь мы суммируем значения переменных в массиве, используя цикл «for»:
.486 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data msg_title db "Title", 0 A DB 1h x dd 0,1,2,3,4,5,6,7,8,9,10,11 n dd 12 buffer db 128 dup(?) format db "%d",0 .code start: mov eax, 0 mov ecx, n mov ebx, 0 L: add eax, x[ebx] add ebx, type x dec ecx cmp ecx, 0 jne L invoke wsprintf, addr buffer, addr format, eax invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK invoke ExitProcess, 0 end start
Команда dec, как и inc, меняет значение операнда на единицу, только в противоположную сторону, на -1. А вот cmp сравнивает переменные методом вычитания: отнимает одно значение из второго, и, в зависимости от результата ставит соответствующие флаги.
С помощью команды jne выполняется переход по метке, основываясь на результате сравнения переменных. Если он отрицательный – происходит переход, а если операнды не равняются друг другу, переход не осуществляется.
Ассемблер интересен своим представлением переменных, что позволяет делать с ними что угодно. Специалист, который разобрался во всех тонкостях данного языка программирования, владеет действительно ценными знаниями, которые имеют множество путей использования. Одна задачка может решаться самыми разными способами, поэтому путь будет тернист, но не менее увлекательным.
Post Views: 38 869
Программирование на Ассемблере для начинающих с примерами программ
Многие считают, что Assembler – уже устаревший и нигде не используемый язык, однако в основном это молодые люди, которые не занимаются профессионально системным программированием. Разработка ПО, конечно, хорошо, но в отличие от высокоуровневых языков программирования, Ассемблер научит глубоко понимать работу компьютера, оптимизировать работку с аппаратными ресурсами, а также программировать любую технику, тем самым развиваясь в направлении машинного обучения. Для понимания этого древнего ЯП, для начала стоит попрактиковаться с простыми программами, которые лучше всего объясняют функционал Ассемблера.
IDE для Assembler
Первый вопрос: в какой среде разработки программировать на Ассемблере? Ответ однозначный – MASM32. Это стандартная программа, которую используют для данного ЯП. Скачать её можно на официальном сайте masm32.com в виде архива, который нужно будет распаковать и после запустить инсталлятор install.exe. Как альтернативу можно использовать FASM, однако для него код будет значительно отличаться.
Перед работой главное не забыть дописать в системную переменную PATH строчку:
С:\masm32\bin
Программа «Hello world» на ассемблере
Считается, что это базовая программа в программировании, которую начинающие при знакомстве с языком пишут в первую очередь. Возможно, такой подход не совсем верен, но так или иначе позволяет сразу же увидеть наглядный результат:
.386 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib .data msg_title db "Title", 0 msg_message db "Hello world", 0 .code start: invoke MessageBox, 0, addr msg_message, addr msg_title, MB_OK invoke ExitProcess, 0 end start
Для начала запускаем редактор qeditor.exe в папке с установленной MASM32, и в нём пишем код программы. После сохраняем его в виде файла с расширением «.asm», и билдим программу с помощью пункта меню «Project» → «Build all». Если в коде нет ошибок, программа успешно скомпилируется, и на выходе мы получим готовый exe-файл, который покажет окно Windows с надписью «Hello world».
Сложение двух чисел на assembler
В этом случае мы смотрим, равна ли сумма чисел нулю, или же нет. Если да, то на экране появляется соответствующее сообщение об этом, и, если же нет – появляется иное уведомление.
.486 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data .code start: mov eax, 123 mov ebx, -90 add eax, ebx test eax, eax jz zero invoke MessageBox, 0, chr$("В eax не 0!"), chr$("Info"), 0 jmp lexit zero: invoke MessageBox, 0, chr$("В eax 0!"), chr$("Info"), 0 lexit: invoke ExitProcess, 0 end start
Здесь мы используем так называемые метки и специальные команды с их использованием (jz, jmp, test). Разберём подробнее:
- test – используется для логического сравнения переменных (операндов) в виде байтов, слов, или двойных слов. Для сравнения команда использует логическое умножение, и смотрит на биты: если они равны 1, то и бит результата будет равен 1, в противном случае – 0. Если мы получили 0, ставятся флаги совместно с ZF (zero flag), которые будут равны 1. Далее результаты анализируются на основе ZF.
- jnz – в случае, если флаг ZF нигде не был поставлен, производится переход по данной метке. Зачастую эта команда применяется, если в программе есть операции сравнения, которые как-либо влияют на результат ZF. К таким как раз и относятся test и cmp.
- jz – если флаг ZF всё же был установлен, выполняется переход по метке.
- jmp – независимо от того, есть ZF, или же нет, производится переход по метке.
Программа суммы чисел на ассемблере
Примитивная программа, которая показывает процесс суммирования двух переменных:
.486 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32. inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data msg_title db "Title", 0 A DB 1h B DB 2h buffer db 128 dup(?) format db "%d",0 .code start: MOV AL, A ADD AL, B invoke wsprintf, addr buffer, addr format, eax invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK invoke ExitProcess, 0 end start
В Ассемблере для того, чтобы вычислить сумму, потребуется провести немало действий, потому как язык программирования работает напрямую с системной памятью. Здесь мы по большей частью манипулируем ресурсами, и самостоятельно указываем, сколько выделить под переменную, в каком виде воспринимать числа, и куда их девать.
Получение значения из командной строки на ассемблере
Одно из важных основных действий в программировании – это получить данные из консоли для их дальнейшей обработки. В данном случае мы их получаем из командной строки и выводим в окне Windows:
.486 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data .code start: call GetCommandLine ; результат будет помещен в eax push 0 push chr$("Command Line") push eax ; текст для вывода берем из eax push 0 call MessageBox push 0 call ExitProcess end start
Также можно воспользоваться альтернативным методом:
.486 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32. lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data .code start: call GetCommandLine ; результат будет помещен в eax invoke GetCommandLine invoke MessageBox, 0, eax, chr$("Command Line"), 0 invoke ExitProcess, 0 push 0 call ExitProcess end start
Здесь используется invoke – специальный макрос, с помощью которого упрощается код программы. Во время компиляции макрос-команды преобразовываются в команды Ассемблера. Так или иначе, мы пользуемся стеком – примитивным способом хранения данных, но в тоже время очень удобным. По соглашению stdcall, во всех WinAPI-функциях переменные передаются через стек, только в обратном порядке, и помещаются в соответствующий регистр eax.
Циклы в ассемблере
Вариант использования:
.data msg_title db "Title", 0 A DB 1h buffer db 128 dup(?) format db "%d",0 . code start: mov AL, A .REPEAT inc AL .UNTIL AL==7 invoke wsprintf, addr buffer, addr format, AL invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK invoke ExitProcess, 0 end start
.data msg_title db "Title", 0 buffer db 128 dup(?) format db "%d",0 .code start: mov eax, 1 mov edx, 1 .WHILE edx==1 inc eax .IF eax==7 .BREAK .ENDIF .ENDW invoke wsprintf, addr buffer, addr format, eax invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK invoke ExitProcess, 0
Для создания цикла используется команда repeat. Далее с помощью inc увеличивается значение переменной на 1, независимо от того, находится она в оперативной памяти, или же в самом процессоре. Для того, чтобы прервать работу цикла, используется директива «.BREAK». Она может как останавливать цикл, так и продолжать его действие после «паузы». Также можно прервать выполнение кода программы и проверить условие repeat и while с помощью директивы «.CONTINUE».
Сумма элементов массива на assembler
Здесь мы суммируем значения переменных в массиве, используя цикл «for»:
.486 .model flat, stdcall option casemap: none include /masm32/include/windows.inc include /masm32/include/user32.inc include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib includelib /masm32/lib/kernel32.lib include /masm32/macros/macros.asm uselib masm32, comctl32, ws2_32 .data msg_title db "Title", 0 A DB 1h x dd 0,1,2,3,4,5,6,7,8,9,10,11 n dd 12 buffer db 128 dup(?) format db "%d",0 .code start: mov eax, 0 mov ecx, n mov ebx, 0 L: add eax, x[ebx] add ebx, type x dec ecx cmp ecx, 0 jne L invoke wsprintf, addr buffer, addr format, eax invoke MessageBox, 0, addr buffer, addr msg_title, MB_OK invoke ExitProcess, 0 end start
Команда dec, как и inc, меняет значение операнда на единицу, только в противоположную сторону, на -1. А вот cmp сравнивает переменные методом вычитания: отнимает одно значение из второго, и, в зависимости от результата ставит соответствующие флаги.
С помощью команды jne выполняется переход по метке, основываясь на результате сравнения переменных. Если он отрицательный – происходит переход, а если операнды не равняются друг другу, переход не осуществляется.
Ассемблер интересен своим представлением переменных, что позволяет делать с ними что угодно. Специалист, который разобрался во всех тонкостях данного языка программирования, владеет действительно ценными знаниями, которые имеют множество путей использования. Одна задачка может решаться самыми разными способами, поэтому путь будет тернист, но не менее увлекательным.
Post Views: 38 870
Примеры на Ассемблере
Как выучить английский
В наше время любой человек должен знать английский язык. А тем более программист. Потому что довольно большая часть документации существует только на английском. А профессионал не может ждать, пока кто-то переведёт ему документацию. Он должен уметь быстро получать нужную инфорамцию и использовать её, независимо от того, на каком она языке — на английском или на русском… Ссылки на курсы по английскому… |
Примеры на Ассемблере позволяют, во-первых, потренироваться в программировании на этом языке, а во-вторых, более глубоко вникнуть в ассемблер и более полно в нём разобраться.
Поэтому я решил наконец создать раздел, где буду приводить примеры относительно простых программ. Я буду стараться, чтобы это были не просто исходники на ассемблере, где рассматривается использование какой-либо команды (как это я делаю в рассказах об инструкциях процессора Интел), а чтобы это были какие-то более-менее законченные программы, которые полностью или частично можно было бы применить где-то ещё — в своих разработках, в курсовых/контрольных и т. п.
То есть в этом разделе будут исходные коды несложных программ на Ассемблере. И это, надеюсь, поможет вам в изучении Ассемблера, а также позволит какие-то части этих программ использовать в своих разработках.
Подразумевается, что у вас есть начальные знания в этой области. Иначе, хотя все примеры будут с подробными комментариями, понять в полной мере всё это будет сложно.
Для создания программ я буду использовать разные средства разработки. Обычно это будет текстовый редактор и какой-либо ассемблер.
Самые простые программы я буду создавать в Emu8086. Программы посложнее буду писать в текстовом редакторе PSPad, а компилировать либо с помощью TASM, либо с помощью MASM. Сам процесс компиляции (ассемблирования) я описывать не буду. Надеюсь, вы знаете, как это делается. Если нет, то см. по ссылкам выше.
ВАЖНО!
Не все программы будут работать в Windows NT или других операционных системах. Надеюсь, это тоже понятно.
Некоторые примеры будут на языках высокого уровня, а код на ассемблере будет только в виде небольшой вставки. Это будет в тех случаях, когда надо показать простой пример на ассемблере, а загромождать исходный текст большими кусками кода не самых важных функций ввода-вывода не хочется.
Итак, вот что доступно на сегодняшний день:
Структура программы на ассемблере
Программирование на уровне машинных команд — это тот минимальный уровень, на котором возможно составление программ. Система машинных команд должна быть достаточной для того, чтобы реализовать требуемые действия, выдавая указания аппаратуре вычислительной машины.
Каждая машинная команда состоит из двух частей:
- операционной — определяющей, «что делать»;
- операндной — определяющей объекты обработки, «с чем делать».
Машинная команда микропроцессора, записанная на языке ассемблера, представляет собой одну строку, имеющую следующий синтаксический вид:
метка команда/директива операнд(ы) ;комментарии
При этом обязательным полем в строке является команда или директива.
Метка, команда/директива и операнды (если имеются) разделяются по крайней мере одним символом пробела или табуляции.
Если команду или директиву необходимо продолжить на следующей строке, то используется символ обратный слеш: \.
По умолчанию язык ассемблера не различает заглавные и строчные буквы в написании команд или директив.
Примеры строк кода:
Count db 1 ;Имя, директива, один операнд
mov eax,0 ;Команда, два операнда
cbw ; Команда
Метки
Метка в языке ассемблера может содержать следующие символы:
- все буквы латинского алфавита;
- цифры от 0 до 9;
- спецсимволы: _, @, $, ?.
В качестве первого символа метки может использоваться точка, но некоторые компиляторы не рекомендуют применять этот знак. В качестве меток нельзя использовать зарезервированные имена Ассемблера (директивы, операторы, имена команд).
Первым символом в метке должна быть буква или спецсимвол (но не цифра). Максимальная длина метки – 31 символ. Все метки, которые записываются в строке, не содержащей директиву ассемблера, должны заканчиваться двоеточием : .
Команды
Команда указывает транслятору, какое действие должен выполнить микропроцессор. В сегменте данных команда (или директива) определяет поле, рабочую область или константу. В сегменте кода команда определяет действие, например, пересылка (mov) или сложение (add).
Директивы
Ассемблер имеет ряд операторов, которые позволяют управлять процессом ассемблирования и формирования листинга. Эти операторы называются директивами. Они действуют только в процессе ассемблирования программы и, в отличие от команд, не генерируют машинных кодов.
Операнды
Операнд– объект, над которым выполняется машинная команда или оператор языка программирования.
Команда может иметь один или два операнда, или вообще не иметь операндов. Число операндов неявно задается кодом команды.
Примеры:
- Нет операндов ret ;Вернуться
- Один операнд inc ecx ;Увеличить ecx
- Два операнда add eax,12 ;Прибавить 12 к eax
Метка, команда (директива) и операнд не обязательно должны начинаться с какой-либо определенной позиции в строке. Однако рекомендуется записывать их в колонку для большего удобства чтения программы.
В качестве операндов могут выступать
- идентификаторы;
- цепочки символов, заключенных в одинарные или двойные кавычки;
- целые числа в двоичной, восьмеричной, десятичной или шестнадцатеричной системе счисления.
Идентификаторы
Идентификаторы – последовательности допустимых символов, использующиеся для обозначения таких объектов программы, как коды операций, имена переменных и названия меток.
Правила записи идентификаторов.
- Идентификатор может состоять из одного или нескольких символов.
- В качестве символов можно использовать буквы латинского алфавита, цифры и некоторые специальные знаки: _, ?, $, @.
- Идентификатор не может начинаться символом цифры.
- Длина идентификатора может быть до 255 символов.
- Транслятор воспринимает первые 32 символа идентификатора, а остальные игнорирует.
Комментарии
Комментарии отделяются от исполняемой строки символом ; . При этом все, что записано после символа точка с запятой и до конца строки, является комментарием. Использование комментариев в программе улучшает ее ясность, особенно там, где назначение набора команд непонятно. Комментарий может содержать любые печатные символы, включая пробел. Комментарий может занимать всю строку или следовать за командой на той же строке.
Структура программы на ассемблере
Программа, написанная на языке ассемблера, может состоять из нескольких частей, называемых модулями. В каждом модуле могут быть определены один или несколько сегментов данных, стека и кода. Любая законченная программа на ассемблере должна включать один главный, или основной, модуль, с которого начинается ее выполнение. Модуль может содержать сегменты кода, сегменты данных и стека, объявленные при помощи соответствующих директив. Перед объявлением сегментов нужно указать модель памяти при помощи директивы .MODEL.
Пример «ничего не делающей» программы на языке ассемблера:
.686P
.MODEL FLAT, STDCALL
.DATA
.CODE
START:
RET
END START
В данной программе представлена всего одна команда микропроцессора. Эта команда RET. Она обеспечивает правильное окончание работы программы. В общем случае эта команда используется для выхода из процедуры.
Остальная часть программы относится к работе транслятора.
.686P — разрешены команды защищенного режима Pentium 6 (Pentium II). Данная директива выбирает поддерживаемый набор команд ассемблера, указывая модель процессора. Буква P, указанная в конце директивы, сообщает транслятору о работе процессора в защищенном режиме.
.MODEL FLAT, stdcall — плоская модель памяти. Эта модель памяти используется в операционной системе Windows. stdcall — используемое соглашение о вызовах процедур.
.DATA — сегмент программы, содержащий данные.
.CODE — блок программы, содержащей код.
START — метка. В ассемблере метки играют большую роль, что не скажешь о современных языках высокого уровня.
END START — конец программы и сообщение транслятору, что начинать выполнение программы надо с метки START.
Каждый модуль должен содержать директиву END, отмечающую конец исходного кода программы. Все строки, которые следуют за директивой END, игнорируются. Если опустить директиву END, то генерируется ошибка.
Метка, указанная после директивы END, сообщает транслятору имя главного модуля, с которого начинается выполнение программы. Если программа содержит один модуль, метку после директивы END можно не указывать.
Назад
Назад: Язык ассемблера
7.4. Пример полной программы на Ассемблере
Прежде, чем написать нашу первую полную программу на Ассемблере, нам необходимо научиться выполнять операции ввода/вывода, без которых ни одна сколько-нибудь серьёзная программа обойтись не может. В самом языке машины, в отличие от языка нашей учебной машины УМ-3, нет команда ввода/вывода,1чтобы, например, ввести целое число, необходима достаточно большаяпрограммана машинном языке.
Для организации ввода/вывода мы в наших примерах будем использовать макрокоманды из учебника [5]. Вместо каждой макрокоманды Ассемблер будет подставлять соответствующий этой макрокоманде набор команд и констант (этот набор, как мы узнаем позже, называется макрорасширениемдля макрокоманды).
Нам понадобятся следующие макрокоманды ввода/вывода.
outch op1
где операнд op1может быть в форматеi8,r8илиm8. Значение операнда трактуется как код символа, этот символ выводится в текущую позицию экрана. Для задания кода символа удобно использовать символьную константу языка Ассемблер, например,′A′. Такая константа преобразуется программой Ассемблера именно в код этого символа. Например, outch ′*′выведет символ звёздочки на место курсора.
inch op1
где операнд op1может быть в форматеr8илиm8. Код введённого символа записывается в место памяти, определяемое операндом.
outint op1[,op2]
outword op1[,op2]
Здесь, как всегда, квадратные скобки говорят о том, что второй операнд может быть опущен. В качестве первого операнда op1можно использоватьi16,r16илиm16, а второго –i8,r8илиm8. Действие макрокоманды outint op1,op2полностью эквивалентно процедуре вывода языка Паскальwrite(op1:op2), а действие макрокоманды с именемoutwordотличается только тем, что первый операндтрактуетсякак беззнаковое (неотрицательное) число.
inint op1
где операнд op1может иметь форматr16илиm16, производит ввод с клавиатуры на место первого операнда целого значения из диапазона–215..+216. Особо отметим, что операнды форматовr8иm8недопустимы.
newline
предназначена для перехода курсора к началу следующей строки экрана и эквивалентна вызову процедуры без параметров writelnязыка Паскаль. Этого же эффекта можно достичь, если вывести на экран служебные символы с кодами 10 и 13, т.е. выполнить, например, макрокоманды
outch 10
outch 13
flush
предназначена для очистки буфера ввода и эквивалентна вызову процедуры без параметров readlnязыка Паскаль.
outstr
Эта макрокоманда выводит на экран строку текста из того сегмента, на который указывает сегментный регистр DS, причём адрес начала этой строки в сегменте должен находится в регистреDX. Таким образом, физический адрес начала выводимого текста определяется по формуле
Афиз = (DS*16 + DX)mod 220
Заданный таким образом адрес принято записывать в виде так называемой адресной пары<DS,DX>. В качестве признака конца выводимой строки символов должен быть задан символ$(он рассматривается как служебный признак конца и сам не выводится). Например, если в сегменте данных есть текст
Data segment
. . .
T db ′Текст для вывода на экран$’
. . .
data ends
то для вывода этого текста на экран можно выполнить следующий фрагмент программы
. . .
mov DX,offset T; DX:=адрес T
outstr
. . .
Рассмотрим теперь пример простой полнойпрограммы на Ассемблере. Эта программа должна вводить значение целой переменнойA и реализовывать оператор присваивания (в смысле языка Паскаль)
X := (2*A — 241 div (A+B)2) mod 7
где B–параметр, т. е. значение, которое не вводится, а задаваётся в самой программе. ПустьA,BиС–знаковыецелые величины, описанные в сегменте данных так:
A dw ?
B db –8; это параметр, заданный программистом
X dw ?
Вообще говоря, результат, заносимый в переменную Xкороткий(это остаток от деления на 7), однако мы выбрали дляXформат слова, т.к. его надо выдавать в качестве результата, а макрокомандаoutintможет выводить толькодлинныецелые числа.
Наша программа будет содержать три сегмента с именами data,codeиstackи выглядеть следующим образом:
include io.asm
; вставить в программу файл с макроопределениями
; для макрокоманд ввода-вывода
data segment
A dw ?
B db -8
X dw ?
Data ends
stack segment stack
db 128 dup (?)
stack ends
code segment
assume cs:code, ds:data, ss:stack
start:mov ax,data; это команда формата r16,i16
mov ds,ax ; загрузка сегментного регистра DS
inint A ; макрокоманда ввода целого числа
mov bx,A ; bx := A
mov al,B ; al := B
cbw ; ax := длинное B
add ax,bx ; ax := B+A=A+B
add bx,bx ; bx := 2*A
imul ax ; (dx,ax) := (A+B)2
mov cx,ax ; cx := младшая часть(A+B)2
mov ax,241
cwd ; <dx,ax> := сверхдлинное 241
idiv cx ; ax := 241 div (A+B)2 , dx := 241 mod (A+B)2
sub bx,ax ; bx := 2*A — 241 div (A+B)2
mov ax,bx
cwd
mov bx,7
idiv bx ; dx := (2*A — 241 div (A+B)2) mod 7
mov X,dx
outint X
finish
code ends
end start
Прокомментируем текст нашей программы. Во-первых, заметим, что сегмент стека мы нигде явно не используем, однако он необходим в любойпрограмме. Как мы узнаем далее из нашего курса, во время выполнения любой программы возможно автоматическое (без нашего ведома) переключение на выполнение некоторой другой программы, при этом используется сегмент стека. Подробно этот вопрос мы рассмотрим при изучениипрерываний.
В начале сегмента кода расположена директива assume, она говорит программе Ассемблера, на какие сегменты будут указывать соответствующие сегментные регистры при выполнении команд,обращающихсяк этим сегментам. Сама эта директива не меняет значения ни одного сегментного регистра, подробно про неё необходимо прочитать в учебнике [5].
Заметим, что сегментные регистры SSиCSдолжны быть загруженыперед выполнениемсамой первойкоманды нашей программы. Ясно, что сама наша программа этого сделать не в состоянии, так как для этого необходимо выполнить хотя бы одну команду, что требует доступа к сегменту кода, и, в свою очередь, уже установленного на этот сегмент регистраCS. Получается замкнутый круг, и единственным решением будет попросить какую-тодругуюпрограмму загрузить значения этих регистров,передвызовомнашей программы. Как мы потом увидим, эту операцию будет делать служебная программа, которая называетсязагрузчиком.
Первые две команды нашей программы загружают значение сегментного регистра DS, в младшей модели для этого необходимы именнодвекоманды, так как одна команда имела бы несуществующий формат:
mov ds,data; формат SR,i16 такого формата нет!
Пусть, например, при счёте нашей программы сегмент данных будет располагаться, начиная с адреса 10000010оперативной памяти. Тогда команда
mov ax,data
будет во время счёта иметь вид
mov ax,6250 ; 100000 div 16 = 6250
Макрокоманда
inint A; макрокоманда ввода целого числа
вводит значение целого числа в переменную A.
Далее начнём непосредственное вычисление правой части оператора присваивания. Задача усложняется тем, что величины A и Bимеют разную длину и непосредственно складывать их нельзя. Приходится командами
mov al,B ; al := B
cbw ; ax := длинное B
преобразовать короткое целое B, которое сейчас находится на регистреal, в длинное целое на регистреax. Далее вычисляется значение выражения(A+B)2и можно приступать к выполнению деления. Так как делитель является длинным целым числом (мы поместили его на регистрcx), то необходимо применить операциюдлинногоделения, для чего делимое (число241 на регистреax) командой
cwd
преобразуем в сверхдлинное целое и помещаем на два регистра (dx,ax). Вот теперь всё готово для команды целочисленного деления
idiv cx; ax:= 241 div (A+B)2 , dx:= 241 mod (A+B)2
Далее мы присваиваем остаток от деления (он в регистре dx) переменнойXи выводим значение этой переменной по макрокоманде
outint X
которая эквивалентна процедуре WriteLn(X)языка Паскаль. Последним предложением в сегменте кода является макрокоманда
finish
Эта макрокоманда заканчивает выполнение нашей программы, она эквивалентна выходу программы на Паскале на конечный end.
И, наконец, директива
end start
заканчивает описание всего модуля на Ассемблере. Обратите внимание на параметр этой директивы – метку start. Она указываетвходную точкупрограммы, т.е. её первую выполняемую команду программы.
Сделаем теперь важные замечания к нашей программе. Во-первых, мы не проверяли, что команды сложения и вычитания дают правильный результат (для этого, как мы знаем, после выполнения этих команд нам было бы необходимо проверить флаг переполнения OF, т.к. наши числа мы считаем знаковыми). Во-вторых, команда длинного умножения располагает свой результат в двух регистрах (dx,ax), а в нашей программе мы брали результат произведения только из регистра ax, предполагая, что на регистре dx находятся только незначащие цифры произведения. По-хорошему надо было бы проверить, что в dx содержаться только нулевые биты, если ax 0, и только двоичные “1”, если
ax < 0. Другими словами, знак числа в регистре dx должен совпадать со знаком числа в регистре ax, для знаковых чисел это и есть признак того, что в регистре dx содержится незначащая часть произведения. И, наконец, мы не проверили, что не производим деления на ноль (в нашем случае что A<>8). В наших учебных программах мы иногда не будем делать таких проверок, но в “настоящих” программах, которые Вы будете создавать на компьютерах и предъявлять преподавателям, эти проверки являются обязательными.
Продолжая знакомство с языком Ассемблера, решим следующую задачу. Напишем фрагмент программы, в котором увеличивается на единицу целое число, расположенное в 23456710 байте оперативной памяти. Мы уже знаем, что запись в любой байт памяти возможна только тогда, когда этот байт расположен в одном из четырёх текущих сегментах. Сделаем, например, так, чтобы наш байт располагался в сегменте данных. Главное здесь – не путать сегменты данных, которые мы описываем в программе на Ассемблере, с активными сегментами, на начала которых установлены сегментные регистры. Описываемые в программе сегменты обычно размещаются загрузчиком на свободных участках оперативной памяти, и, как правило, при написании текста программы неизвестно их будущего месторасположение.1 Однако ничто не мешает нам любой участок оперативной памяти сделать сегментом, установив на него какой-либо сегментный регистр. Так мы и сделаем для решения нашей задачи, установив сегментный регистр DS на начало ближайшего сегмента, в котором будет находиться наш байт с адресом 23456710. Так как в сегментный регистр загружается адрес начала сегмента, делённый на 16, то нужное нам значение сегментного регистра можно вычислить по формуле: DS := 234567 div 16 = 14660. При этом адрес A нашего байта в сегменте (его смещение от начала сегмента) вычисляется по формуле: A := 234567 mod 16 = 7. Таким образом, для решения нашей задачи можно предложить следующий фрагмент программы:
mov ax,14660
mov ds,ax; Начало сегмента
mov bx,7; Смещение
inc byte ptr [bx]
Теперь, после изучения арифметических операций, перейдём к рассмотрению команд переходов, которые понадобятся нам для программирования условных операторов и циклов. После изучения нашего курса мы должны уметь отображать на Ассемблер любые конструкции языка Паскаль.
Статья 1. Простейшая программа на языке ассемблера
Статья 1. Простейшая программа на языке ассемблераНачнем изучение языка ассемблера с рассмотрения простой, возможно, даже наипростейшей программы (пример 1.1), которая выводит на экран терминала строку с текстом. Вопросы ввода в компьютер текста программы, ее трансляции и компоновки мы рассмотрим в следующей статье, а пока сосредоточимся на структуре программы.
Пример 1.1. Простейшая программа
text segment 'code' ; (1) Начало сегмента команд assume CS:text, DS:text ; (2) Сегментные регистры CS и DS ; будут указывать на сегмент команд begin: mov AX,text ; (3) Адрес сегмента команд загрузим mov DS,AX ; (4) сначала в AX, затем в DS mov AH,09h ; (5) Функция DOS 09h вывода на экран mov DX,offset message ; (6) Адрес выводимого сообщения int 21h ; (7) Вызов DOS mov AH,4Ch ; (8) Функция 4Ch завершения программы mov AL,00h ; (9) Код 0 успешного завершения int 21h ; (10) Вызов DOS message db 'Наука умеет много гитик$' ; (11) Выводимый текст text ends ; (12) Конец сегмента команд end begin ; (13) Конец текста с точкой входа
Следует заметить, что при вводе исходного текста программы с клавиатуры можно использовать как прописные, так и строчные буквы: транслятор воспринимает, например, строки text segment и TEXT SEGMENT одинаково. Однако, с помощью ключа /ML можно заставить транслятор различать прописные и строчные буквы в именах. Тогда строки text segment и TEXT segment уже не будут эквивалентны. фактически они будут описывать два разных сегмента. Неэквивалентность прописных и строчных букв касается только имен; строки
mov ds,ax MOV DS,AX mov DS,AX
во всех случаях воспринимаются одинаково.
В настоящей книге в программах и их описаниях мы используются преимущественно строчные буквы. прописными буквами выделены обозначения регистров и, иногда, имена программных и иных файлов.
Наша программа содержит 13 строк — предложений языка ассемблера. Первое предложение с помощью оператора segment открывает сегмент команд программы. Сегменту дается произвольное имя text. Описатель ‘code’ (так называемый класс сегмента) говорит о том, что это сегмент команд (слово code в переводе может означать и коды, и команды программы). В конце предложения после точки с запятой располагается комментарий. Таким образом, предложение языка ассемблера может состоять из четырех полей: имени, оператора, операндов и комментария, располагаемых в перечисленном порядке.
Любая программа должна обязательно состоять из сегментов — без сегментов программ не бывает. Обычно в программе задаются три сегмента: команд, данных и стека, но мы в нашей простой программе пока ограничились одним сегментом команд.
В предложении 2 мы с помощью оператора assume сообщаем ассемблеру (программе-транслятору), что сегментные регистры CS и DS будут указывать на один и тот же сегмент text. Сегментные регистры (а всего их в процессоре четыре) играют очень важную роль. Когда программа загружается в память и становится известно, по каким адресам памяти она располагается, в сегментные регистры заносятся начальные адреса закрепленных за ними сегментов. В дальнейшем любые обращения к ячейкам программы осуществляются путем указания сегмента, в котором находится интересующая нас ячейка, а также номера того байта внутри сегмента, к которому мы хотим обратиться. Этот номер носит название относительного адреса, или смещения. Поскольку в единственном сегменте нашей программы будут размещаться и команды, и данные, мы указываем ассемблеру оператором assume (assume — предположим), что и сегментный регистр команд CS, и сегментный регистр данных DS будут указывать на сегмент text. При этом в регистр CS адрес начала сегмента будет загружен автоматически, а регистр DS нам придется инициализировать вручную.
Строго говоря, в приведенной программе, где нет прямых обращений к ячейкам сегмента данных, не было необходимости сопоставлять в операторе assume сегмент text с сегментным регистром DS (сопоставление сегмента команд с сегментным регистром команд CS обязательно во всех случаях). Учитывая, однако, что практически в любой разумной программе обращения к полям данных имеются, мы с самого начала написали оператор assume в том виде, в каком он используется в реальных программах.
Первые два предложения программы служат для передачи служебной информации программе ассемблера. Ассемблер воспринимает и запоминает эту информацию и пользуется ею в своей дальнейшей работе, однако в состав выполнимой программы, состоящей из машинных кодов, эти строки не попадут, так как процессору, выполняющему программу, они не нужны. Другими словами, операторы segment и assume не транслируются в машинные коды, а используются лишь самим ассемблером на этапе трансляции программы. Такие нетранслируемые операторы иногда называют псевдооператорами, или директивами ассемблера в отличие от истиных операторов — команд языка.
Предложение 3, начинающееся с метки begin, является первой выполнимой строкой программы. Для того, чтобы процессор знал, с какой строки начать выполнять программу после ее загрузки в память, начальная метка программы указывается в качестве операнда самого последнего оператора программы end (см. предложение 13). Можно подумать, что указание точки входа в программу излишне: ведь как будто и так ясно, что программу надо начать выполнять с начала, а закончить, дойдя до конца. Однако в действительности для программ, написанных на языке ассемблера, это совсем не так! Текст программы может начинаться с описания подпрограмм или полей данных. В этом случае предложение программы, с которого нужно начать ее выполнение, может располагаться где-то в середине текста программы. И завершается выполнение программы совсем не обязательно в ее последних строках, а там, где стоят предложения вызова специальной программы операционной системы, предназначенной именно для завершения текущей программы и передачи управления системе (см. предложения 8…10). Однако начиная от точки входа, программа выполняется строка за строкой точно в том порядке, в каком эти строки написаны программистом.
В предложениях 3 и 4 выполняется инициализация сегментного регистра DS. Сначала значение имени text (т.е. адрес сегмента text) загружается командой mov (от move, переместить) в регистр общего назначения процессора AX, а затем из регистра AX переносится в регистр DS. Такая двухступенчатая операция нужна потому, что процессор в силу некоторых особенностей своей архитектуры не может выполнить команду непосредственной загрузки адреса в сегментный регистр. Приходится пользоваться регистром AX в качестве «перевалочного пункта». Кстати, обратите внимание на то, что операнды в командах языка ассемблера записываются в несколько неестественном для европейца порядке — действие команды осуществляется справа налево.
Предложения 5, 6 и 7 реализуют существо программы — вывод на экран строки текста. Делается это не непосредственно, а путем обращения к служебным программам операционной системы MS-DOS, которую мы для краткости будем в дальнейшем называть просто DOS. Дело в том, что в составе команд процессора и, соответственно, операторов языка ассемблера нет команд вывода данных на экран (как и команд ввода с клавиатуры, записи в файл на диске и т.д.). Вывод даже одного символа на экран в действительности представляет собой довольно сложную операцию, для выполнения которой требуется длинная последовательность команд процессора. Конечно, эту последовательность команд можно было бы включить в нашу программу, однако гораздо проще обратиться за помощью к операционной системе. В состав DOS входит большое количество программ, осуществляющих стандартные и часто требуемые функции — вывод на экран и ввод с клавиатуры, запись в файл и чтение из файла, чтение или установка текущего времени, выделение или освобождение памяти и многие другие.
Для того, чтобы обратиться к DOS, надо загрузить в регистр общего назначения AH номер требуемой функции, в другие регистры — исходные данные для выполнения этой функции, после чего выполнить команду int 21h (int — от interrupt, прерывание), которая передаст управление DOS. Вывод на экран строки текста можно осуществить функцией 09h, которая требует, чтобы в регистре DX содержался адрес выводимой строки. В предложении 6 адрес строки message загружается в регистр DX, а в предложении 7 осуществляется вызов DOS.
После того, как DOS выполнит затребованные действия, в данном случае выведет на экран текст «Наука умеет много гитик» (помните одноименный карточный фокус?), выполнение программы продолжится. Вообще-то нам вроде ничего больше делать не нужно. Однако на самом деле это не так. После окончания работы программы DOS должна выполнить некоторые служебные действия. Надо освободить занимаемую нашей программой память, чтобы туда можно было загрузить следующую программу. Надо вызвать системную программу, которая выведет на экран запрос DOS и будет ждать следующей команды оператора. Все эти действия выполняет функция DOS с номером 4Ch. Эта функция предполагает, что в регистре AL находится код завершения нашей программы, который она передаст DOS. При желании код завершения только что закончившейся программы можно «выловить» в DOS и проанализировать, но сейчас мы этим заниматься не будем. Если программа завершилась успешно, код завершения должен быть равен 0, поэтому в предложении 9 мы загружаем 0 в регистр AL и вызываем DOS уже знакомой нам командой int 21h.
После последнего выполнимого предложения программы можно описывать используемые в ней данные. У нас в качестве данных выступает строка текста. Текстовые строки вводятся в программу с помощью директивы ассемблера db (от define byte, определить байт), и заключаются в апострофы. Для того, чтобы в программе можно было обращаться к данным, поля данных, как правило, предваряются именами. В нашем случае таким именем является вполне произвольное обозначение message, с которого начинается предложение 11.
Выше, в предложении 6, мы через регистр DX передали DOS адрес начала выводимой на экран строки текста. Но как DOS определит, где эта строка закончилась? Хотя нам конец строки в программе отчетливо виден, однако в машинных кодах, из которых состоит выполнимая программа, он никак не отмечен, и DOS, выведя на экран слово «гитик», продолжит вывод байтов памяти, расположенных за нашей фразой. Поэтому DOS следует передать информацию о том, где кончается строка текста. Некоторые функции DOS требуют указания в одном из регистров длины выводимой строки, однако функция 09h работает иначе. Она выводит текст до символа $, которым мы и завершили нашу фразу.
Директива ends (end segment, конец сегмента) в предложении 12 указывает ассемблеру, что сегмент text закончился.
Последняя строка программы содержит директиву end, которая говорит программе ассемблера, что закончился вообще весь текст программы, и больше ничего транслировать не нужно. В качестве операнда этой директивы, как уже отмечалось, обычно указывается точка входа в программу, т.е. адрес первой выполнимой программной строки. В нашем случае это метка begin.
Сайт управляется системой uCoz
Avr studio примеры программ на ассемблере. Практическое программирование микроконтроллеров Atmel AVR на языке ассемблера
ВВЕДЕНИЕ. Микроконтроллеры, их возникновение и применение
Предыстория микроконтроллеров
Электроника в греческом стиле
Почему AVR?
Что дальше?
ЧАСТЬ I. ОБЩИЕ ПРИНЦИПЫ УСТРОЙСТВА И ФУНКЦИОНИРОВАНИЯ ATMEL AVR
Глава 1. Обзор микроконтроллеров Atmel AVR
Семейства AVRОсобенности практического использования МК AVR
Глава 2. Общее устройство, организация памяти, тактирование, сброс
Память программПамять данных (ОЗУ, SRAM)
Энергонезависимая память данных (EEPROM)
Способы тактирования
Сброс
Особенности подключения дополнительной внешней памяти данных
Глава 3. Знакомство с периферийными устройствами
Порты ввода-выводаТаймеры-счетчики
Аналого-цифровой преобразователь
Последовательные порты
U ART
Интерфейс SPI
Интерфейс TWI (12С)
Универсальный последовательный интерфейс USI
Глава 4. Прерывания и режимы энергосбережения
ПрерыванияРазновидности прерываний
Режимы энергосбережения
Потребление МК AVR
Потребление МК AYR и режимы энергосбережения
ЧАСТЬ II. ПРОГРАММИРОВАНИЕ МИКРОКОНТРОЛЛЕРОВ ATMEL AVR
Глава 5. Общие принципы программирования МК семейства AVR
Ассемблер или С?Способы и средства программирования AVR
Редактор кода
Об AVR Studio
Обустройство ассемблера
Программаторы
О hex-файлах
Команды, инструкции и нотация AVR-ассемблера
Числа и выражения
Директивы и функции
Общая структура AVR-программы
Обработка прерываний
RESET
Простейшая программа
Задержка
Программа счетчика
Использование прерываний
Задержка по таймеру
Программа счетчика с использованием прерываний
О конфигурационных битах
Глава 6. Система команд AVR
Команды передачи управления и регистр SREGКоманды проверки-пропуска
Команды логических операций
Команды сдвига и операции с битами
Команды арифметических операций
Команды пересылки данных
Команды управления системой
Выполнение типовых процедур на ассемблере
О стеке, локальных и глобальных переменных
Глава 7. Арифметические операции
Стандартные арифметические операцииУмножение многоразрядных чисел
Деление многоразрядных чисел
Операции с дробными числами
Генератор случайных чисел
Операции с числами в формате BCD
Отрицательные числа в МК
Глава 8. Программирование таймеров
8- и 16-разрядные таймерыФормирование заданного значения частоты
Отсчет времени
Точная коррекция времени
Частотомер и периодомер
Частотомер
Периодомер
Управление динамической индикацией
LED-индикаторы и их подключение
Программирование динамической индикации
Таймеры в режиме PWM
Глава 9. Использование EEPROM
Еще раз о сохранности данных в EEPROMЗапись и чтение EEPROM
Хранение констант в EEPROM
Глава 10. Аналоговый компаратор и АЦП
Аналого-цифровые операции и их погрешностиРабота с аналоговым компаратором
Интегрирующий АЦП на компараторе
Принцип работы и расчетные формулы
Программа интегрирующего АЦП
Встроенный АЦП
Пример использования АЦП
Программа
Глава 11. Программирование SPI
Основные операции через SPIАппаратный вариант
Программный вариант
О разновидностях энергонезависимой памяти
Запись и чтение flash-памяти через SPI
Программа обмена с памятью 45DB011В по SPI
Запись и чтение flash-карт
Подключение карт ММС
Подача команд и инициализация ММС
Запись и чтение ММС
Глава 12. Интерфейс TWI (12С) и его практическое использование
Базовый протокол 12СПрограммная эмуляция протокола 12С
Запись данных во внешнюю энергонезависимую память
Режимы обмена с памятью АТ24
Программа
Часы с интерфейсом 12С
Запись данных
Чтение данных
Глава 13. Программирование UART/USART
Инициализация UARTПередача и прием данных
Пример установки часов DS1307 с помощью UART
Приемы защиты от сбоев при коммуникации
Проверка на четность
Как организовать корректный обмен
Дополнительные возможности USART
Реализация интерфейсов RS-232 и RS-485
Преобразователи уровня для RS-232
RS-485
Глава 14. Режимы энергосбережения и сторожевой таймер
Программирование режима энергосбереженияПример прибора с батарейным питанием
Доработка программы
Использование сторожевого таймера
ПРИЛОЖЕНИЯ
Приложение 1. Основные параметры микроконтроллеров Atmel AVR
Приложение 2. Команды Atmel AVR
Арифметические и логические команды
Команды операций с битами
Команды сравнения
Команды передачи управления
Команды безусловного перехода и вызова подпрограмм
Команды проверки-пропуска и команды условного перехода
Команды переноса данных
Команды управления системой
Приложение 3. Тексты программ
Демонстрационная программа обмена данными с flash-памятью 45DB011В по интерфейсу SPI
Процедуры обмена по интерфейсу 12С
Приложение 4. Обмен данными с персональным компьютером и отладка программ через UART
Работа с COM-портом в Delphi
COM-порт и Windows API
Работа с СОМ через готовые компоненты
Установка линии RTS в DOS и Windows
Программа СОМ2000
Отладка программ с помощью терминальной программы
Приложение 5. Словарь часто встречающихся аббревиатур и терминов
Соответствие терминов на русском их переводу на английский
Соответствие терминов на английском их переводу на русский
Литература
Предметный указатель
Итак, надеюсь добросовестный читатель уже собрал программатор, экспериментальную плату, а также установил и настроил требуемое программное обеспечение.
Сейчас, написав первую статью из цикла, я понимаю, что несколько погорячился и сделал ту же ошибку, что и мои предшественники, поставив словосочетание «для начинающих». Вернее было бы сформулировать тему «Для начинающих программировать на ассемблере», то есть я предполагаю, что читатель уже имеет хотя бы поверхностное представление о том, что такое микроконтроллер, иначе только на знакомство с этой темой у нас уйдет уйма времени. Для тех же, кто совсем не знаком с ними, могу порекомендовать совершенно замечательный на мой взгляд цикл статей С. Рюмика «Микроконтроллеры AVR», опубликованный в журнале Радиоаматор (№№ 1-11 за 2005 год). В этом цикле в качестве базового контроллера выбран ATmega8, однако общие функциональные узлы у вышеназванного контроллера и ATtiny13 практически не отличаются.
Для знакомства же непосредственно с микроконтроллером ATtiny13 я рекомендую книгу А.В. Евстифеева «Микроконтроллеры AVR семейства tiny. Руководство пользователя» (М.: Издательский дом «Додэка-XXI», 2007. — 432 с.). Она содержит переведенные и систематизированные даташиты на весь номенклатурный ряд контроллеров семейства tiny, и, на мой взгляд, должна являться настольной для тех, кто занимается программированием микроконтроллеров.
Впрочем, я по мере повествования буду давать кое-какие сведения относительно тех узлов и модулей контроллера, которые будут применяться в написанных программах.
Но все это лирическое отступление. Вернемся непосредственно к повествованию.
Контроллер ATtiny13 несмотря на свой малый размер, имеет весьма неплохие функциональные характеристики. А небольшое количество выводов с лихвой компенсируется количеством функций, которые каждый из них выполняет. Цоколевка и описание выводов представлено ниже:
Таблица взята из вышеназванной книги А.В. Евстифеева.
Как можно видеть, каждый вывод может выполнять не менее трех функций, а то и намного больше. Поначалу мы не будем рассматривать альтернативные функции, а лишь базовую — цифровой вход/выход.
Как видно из рисунка и таблицы, все выводы, за исключением выводов питания, имеет название РВ с последующим порядковым номером. Что же это означает? Все выводы контроллера объединены по 8 штук для удобства работы с ними, а на каждую группу из 8 выводов выделено по три специальных регистра ввода-вывода. Вообще понятие регистров является ключевым при работе в контроллерами, особенно на ассемблере. Рассмотрим более подробно каждый из трех вышеупомянутых регистров. Все они являются однобайтовыми ячейкам в памяти контроллера. Каждый бит их отвечает один из выводов контроллера, причем номер бита в регистре совпадает с номером вывода (например, 0-й бит отвечает за вывод РВ0, 1-й — за РВ1 и т.д.). Все регистры имеют свое имя, по которому к ним обращаются при написании программ. Что же это за имена?
1. Регистр DDRB отвечает за направление передачи информации каждого вывода контроллера. Если какой-либо бит этого регистра равен «0», то соответствующий ему вывод будет входом, а если «1» — то выходом. Причем каждый вывод конфигурируется индивидуально и в любом месте программы. Это значит, что при разных условиях или в разное время один и тот же вывод может быть сконфигурирован как вход либо как выход, причем независимо от остальных выводов.
2. Регистр PINB содержит в себе текущее состояние всех выводов: если на вывод подано напряжение, то в соответствующий бит записывается логическая «1», если напряжение отсутствует — логический «0». В основном этот регистр используется для считывания состояния вывода, находящегося в режиме входа.
3. Регистр PORTB выполняет двоякую функцию в зависимости направления передачи информации. Если вывод работает как цифровой выход, то запись «1» в какой-либо бит регистра PORTB приводит к появлению напряжения на соответствующем выводе, а запись «0» — к исчезновению напряжения. Таким образом, в режиме выхода именно этот регистр определяет состояние каждого вывода. В режиме цифрового входа запись логической «1» в какой-либо бит приводит к подключению встроенного подтягивающего резистора на соответствующем выводе, а запись «0» — к его отключению. Что же это за такая штука — «подтягивающий резистор», и для чего она предназначена? Если вывод работает как цифровой вход, то сопротивление входного буфера достаточно велико, а входной ток — весьма мал. Поэтому любые электрические наводки могут привести к самопроизвольному переключению вывода в произвольное состояние. Чтобы этого не происходило, между входом и источником питания включается резистор сопротивлением несколько десятков килоом, «подтягивающий» потенциал входа к напряжению питания (отсюда и название). Ток, протекающий через этот резистор достаточно мал, чтобы не мешать работе остальной схемы, но достаточно велик, чтобы воспрепятствовать случайным переключениям вывода. Мы часто будем использовать подтягивающие резисторы при работе с кнопками, поскольку когда они не нажаты, выводы, к которым они подключены, фактически «висят» в воздухе и подвержены наводкам.
Следует упомянуть, что при включении питания все регистры сброшены в 0, и каждый вывод выполняет функцию цифрового входа без подтягивающего резистора.
Теперь, когда мы имеем хоть какое-то представление, ЧТО нужно для работы с вводами контроллера, пришла пора узнать, КАК с ними работать.
Напишем нашу первую рабочую программу на ассемблере. Вначале я дам полный алгоритм создания нового проекта, в дальнейшем же буду его опускать, останавливаясь только на самом тексте программы.
1. Заходим в папку asm, создаем в ней новую папку. Переименовываем в удобное для нас имя. Для определенности я буду называть их по номеру нашего шага. В данном случае «step2».
2. Правой кнопкой щелкаем на файле build.bat и изменяем путь к исходному файлу, указывая вновь созданную папку (step2). У меня после этого содержимое выглядит так:
«F:\Prog\AVR\asm\avrasm32 -fI %F:\Prog\AVR\asm\step2\main.asm
pause»
У вас оно может отличаться в зависимости от того, куда вы распаковали архив.
3. Заходим в папку Asmedit и запускаем программу ASM_Ed.exe
4. В открывшемся окне пишем текст программы. На этом пункте остановлюсь более подробно, поскольку он является основным в нашем сегодняшнем занятии, равно как и в последующих.
Что же собой представляет текст ассемблерной программы? Он может включать в себя несколько элементов, записываемых по определенным правилам:
Команды ассемблера с операндами или без них в зависимости от синтаксиса команды. Между именем команды и первым операндом должен быть либо пробел, либо знак табуляции, либо и то и другое в любом количестве. Операнды разделяются между собой запятой, до и после которой может стоять также произвольное количество пробелов либо знаков табуляции;
Директивы, каждая из которых начинается с символа «.»;
Метки, представляющие собой произвольно названные пользователем места программы, к которым может потребоваться переход. Каждая метка оканчивается символом «:»;
Комментарии, начинающиеся с символа «;». Весь текст от начала комментария до конца строки игнорируется при создании hex-файла и может быть совершенно произвольным;
Пустые строки для лучшей структурированности и читабельности программы.
В каждой строке может быть не более одной команды. Однако одновременное присутствие в строке метки с последующей командой и комментарием допускается.
Используя эти правила, напишем программу, которая будет включать светодиод LED2, пока удерживается нажатой кнопка SB1, и выключать его, если кнопка отпущена. Текст программы представлен ниже:
.include «F:\Prog\AVR\asm\Appnotes\tn13def.inc»
sbi DDRB, 4 ;РВ4 — выход (светодиод LED2)
sbi PORTB, 2 ;Включение подтягивающего резистора на РВ2 (кнопка SB1)
sbic PINB, 2 ;Если РВ2=0 (кнопка нажата), пропустить след. строку
sbi PORTB, 4 ;Установка РВ4 в 1 (выключение светодиода)
sbis PINB, 2 ;Если РВ2=1 (кнопка отпущена), пропустить след. строку
cbi PORTB, 4 ;Установка РВ4 в 0 (включение светодиода)
Разберем его поподробнее. Первая строка содержит директиву «include», написанную по указанным выше правилам с точкой в начале. Назначение ее — включать в текст программы указанный за ней файл. Как я говорил еще в первом шаге, нам потребуется файл «tn13def.inc». В этой строке вам необходимо будет изменить путь, указав расположение папки Appnotes в своем компьютере. Зачем же нам нужно подключать этот файл? Любопытный читатель может заглянуть в него и почитать его содержимое, но, скорее всего, поначалу он мало что поймет там. Пока же скажу, что в нем содержится соответствие имен регистров, которые по умолчанию ассемблер не знает, с их физическими адресами в контроллере.
Следующие строки представляют собой команды ассемблера. Внимательный читатель заметит, что всего используется четыре различные команды. рассмотрим назначение каждой.
Команда sbi имеет два операнда: первый — имя регистра, второй — номер бита. В результате ее выполнения указанный бит в указанном регистре устанавливается в «1».
Команда cbi по синтаксису аналогична вышеприведенной и выполняет прямо противоположную функцию — сбрасывает указанный бит в указанном регистре в «0».
Команда sbis также аналогична по синтаксису вышеприведенным. Однако в отличие от них она не выполняет никаких операций с регистрами, а лишь проверяет состояние указанного бита в указанном регистре, и если тот равен «1», пропускает следующую за командой строку. В противном же случае следующая за ней строка выполняется, равно как и все остальные за ней.
Команда sbiс является противоположностью команды sbis. Она пропускает следующую строку, если указанный бит регистра равен «0».
Теперь, суммируя все вышеизложенное, попробуем разобраться в алгоритме работы программы. Для начала я сделаю это буквально построчно.
1 строка. Директивой include подключается файл tn13def.inc, содержащий определения регистров.
2 строка. Командой sbi устанавливается «1» в бит 4 регистра DDRB, тем самым вывод РВ4 переключается на выход. Если посмотреть схему платы (рис. 1 предыдущего шага), можно видеть, что к этому выводу подключен светодиод LED2. После команды и знака «;» написан комментарий, кратко поясняющий смысл выполняемых в строке действий.
3 строка. Той же командой sbi устанавливается «1» в бит 2 регистра PORTB, подключая внутренний подтягивающий резистор к выводу РВ2, к которому подключена кнопка SB1. Поскольку мы не изменяли состояние бита 2 регистра DDRB, этот вывод так и останется входом, что нам, собственно, и нужно.
4 строка. Командой sbic проверяется наличие логического «0» на входе PB2, используя регистр PINB. Если внимательно посмотреть на схему, можно увидеть, что кнопки при нажатии, замыкают соответствующий вывод с общим проводом. Это стандартный прием, поскольку при отпущенной кнопке на выводе присутствует логическая «1» за счет подтягивающего резистора, а при нажатой появляется логический «0» благодаря подключению вывода к общему проводу. Итак, если на выводе РВ2 присутствует логический «0», то есть кнопка нажата, мы пропускаем следующую строку, а если кнопка отпущена, то выполняем ее.
5 строка. В ней командой sbi устанавливается логическая «1» в бит 4 регистра PORTB, тем самым выключая светодиод LED2. Въедливый читатель может поинтересоваться, почему же светодиод выключается, если мы подаем напряжение на выход. Ответ кроется в схеме. Светодиод анодом подключен к проводу питания, а катодом к выводу контроллера. Поэтому если подать на вывод напряжение, то потенциалы анода и катода сравняются, и светодиод погаснет. Если же на вывод выдать логический «0», то к светодиоду будет приложено напряжение, и он зажжется. Таким образом пара строк 4 и 5 выключает светодиод LED2 при отпущенной кнопке.
6 строка. Противоположна по смыслу 4-й. Командой sbis проверяется наличие логической «1» на входе РВ2, то есть проверяется, отпущена ли кнопка. Если кнопка отпущена, то следующая строка пропускается, и происходит переход к следующей за ней. Но поскольку 7-я строка последняя, то происходит переход ко 2-й строке. Если же кнопка нажата, то выполняется строка 7.
7 строка. Противоположна 5-й. Командой cbi бит 4 регистра PORTB сбрасывается в «0», тем самым включая светодиод LED2. Таким образом, пара строк 6 и 7 включает светодиод LED2 при нажатой кнопке SB1.
Как видите, ничего особо сложного мы не совершили. Используя знание всего 3-х регистров и 4-х команд, мы написали нашу первую программу. Что же делать с ней дальше. Если вы еще не забыли, мы продолжаем писать алгоритм создания программы.
5. Написав текст программы в окне редактора, выбираем пункт меню «File», и в открывшемся списке нажимаем «Save As…». В окне сохранения файла выбираем созданную нами папку step2 и указываем имя файла «main», поскольку именно это имя было задано нами в файле «build.bat»
После сохранения окно программы должно иметь следующий вид:
6. Создаем hex-файл. Для этого нажимаем кнопку «II» на панели инструментов. Должно появится окно следующего вида:
Оно извещает нас о том, что ассемблирование прошло без ошибок и создан файл прошивки «main.hex» объемом 6 слов, то есть 12 байт. Замечу, что аналогичная программа на языке Си имела бы как минимум в 5 раз больший объем.
7. Зайдя в папку step2, обнаруживаем в ней пополнение в виде вновь созданного файла main.hex, который теперь может быть зашит в контроллер любым программатором, что и необходимо выполнить, дабы увидеть результаты работы написанной нами программы. После прошивки контроллера, если схема собрана правильно, все должно работать по разработанному нами алгоритму: при отпущенных кнопках светодиод LED2 должен быть погашен, а во время удержания нажатой кнопки SB1 — зажжен.
До следующего шага предлагаю сделать такие задания:
1. Добавить к программе обработку нажатия кнопки SB2 с противоположным алгоритмом: при отпущенной кнопке SB2 светодиод LED1 должен быть зажжен, а при нажатой — погашен.
2. Написать программу управления светодиодом LED2 при помощи обеих кнопок. При нажатии на кнопку SB1 светодиод должен зажигаться и оставаться включенным до тех пор, пока не будет нажата кнопка SB2, которая выключает его до следующего нажатия SB1.
Всем добрый вечер! Веду свою трансляцию из уютного мира, который называется «ассемблер». Сразу поясню что тема касается микроконтроллеров AVR — и я пока ещё не знаю, пригодится ли этот пост тем, кто хочет использовать ассемблер для любой другой задачи. Дело в том, что я буквально несколько дней назад начал учить ассемблер с нуля — нужно сделать одно устройство — и я решил сделать в нём всё самостоятельно. Так вот — в один прекрасный день понял, что учить ассемблер абсолютно бесполезно! Ассемблер можно только понять! То есть всем тем, кто хочет программировать на ассемблере я настоятельно рекомендую детально вникнуть в то, каким образом ФИЗИЧЕСКИ работает микроконтроллер, а затем уже изучать тонкости команд.
Так вот, я пожалуй начну небольшой цикл статей, в которых буду с самого начала рассказывать как именно я понял те или иные вещи в программировании на ассемблере — думаю для тех, кто вообще не понимает что такое асм я буду как раз таким «переводчиком» с языка тех, кто в этом деле очень хорошо шарит.
Сразу скажу, что я более-менее вкурил эту тему с подачи DIHALT — поэтому эти статейки будут являться неким переводом с супер-пупер-ассемблерно-микроконтроллерного языка на язык понятный большинству людей. Ну а гуру надеюсь будут меня поправлять по ходу пьесы и если вдруг я что то объясню неправильно — то они поправят меня.
Итак первые выводы об ассемблере, которые я сделал пару дней назад, меня потрясли до глубины души — и я просидел за статьями DI HALT»а с 11 вечера до 5 утра — после чего лёг спать довольным и счастливым. Я понял суть программирования на ассемблере для микроконтроллеров.
Как же это объяснить ещё проще? Думаю нужно начать с самой сути.
***
Изначально не будем вдаваться в технические подробности (о них мы поговорим в следующей статье) — просто представьте, что есть 3 персонажа :
1. Микроконтроллер — это англичанин Стив, который приехал к русскому. Он идеально знает английский язык, но по-русски он вообще не понимает — ни единого слова. Только английский. Он проиграл в споре и обязался делать бесприкословно всё то, о чём его попросит русский.
2. Ассемблер — это переводчик Вася у которого мама англичанка а папа русский. Он знает идеально и английский и русский язык.
3.Мы — это русский, к которому приехал англичанин. Ну то есть мы это мы=) При этом мы идеально знаем русский язык и (!!!) чуть-чуть английский — самую малость, со словариком.
***
Представьте такую ситуацию — англичанин сидит у Вас в комнате на стуле. А Вы сидите себе за компом и читаете этот пост, как вдруг у Вас внезапно открылась форточка! Вот ведь незадача! Ветер дует, занавеска превратилась в парус… Было бы неплохо закрыть! Но вот ведь как лень вставать со стула, снимать ноги с системника, запихивать их в тапочки, отставлять кружку с кофе(пивом) и идти бороться со стихией. И тут Вы внезапно осознаёте, что у нас то в комнате есть проспоривший англичанин, которого самое время погонять! И вы ему так мило говорите «Дружище! Закрой форточку пожалуйста, а потом можешь опять присесть на стул!» а он сидит, смотрит на вас с недоумением и ничего не делает! Можно конечно по щам надавать — но он же тогда всё равно вас не поймёт! Тогда Вы звоните своему другу-переводчику Василию — он приходит, и садится рядом с англичанином на стул. И вы говорите — Переведи: «Стив, пойди и закрой форточку, а потом обратно сядь на стул!» Переводчик переводит на английский — англичанин понимает и идёт закрывает форточку, а затем приходит и садится на стул.
В этом моменте нужно просто понять роль ассемблера в этой цепочке «Мы-Ассемблер-Контроллер»
То есть как бы что такое ассемблер все поняли? Тогда читаем дальше.
***
Так вот, представляем такую ситуацию. Васе говоришь — «Слушай, ну короче такое дело — я калькулятор дома забыл, раздели 56983 на 2 и скажи Стиву, чтобы он столько раз отжался на кулаках» и Вася на калькуляторе считает и говорит Стиву по-английски » Отожмись на кулаках 28491 раз» Это называется «ДИРЕКТИВА» — другими словами директива это задание для Васи, результат выполнения которой это действие Стива.
Есть другая ситуация — Вы говорите Васе «Скажи Стиву, чтобы он отжался 28491 раз» и Вася просто переводит Ваши слова на английский. Это называется ОПЕРАТОР
Всё просто — есть директива и есть оператор. Оператор — это Ваше прямое указание что делать Стиву — Вася тут только переводит Ваше требование на инглиш. А Директива — это задание для самого Васи — и Вася сначала делает то, что Вы ему сказали, а потом уже в зависимости от результата говорит Стиву что-либо.
Теперь мы будем мучать англичанина регулярно! Но предварительно нужно получше познакомиться с нашим переводчиком Васей. Нужно знать следующее — Вася всегда Вас слушается беспрекословно — что ему сказали, то он и делает. Васин калькулятор не имеет десятичных знаков — если вы глянете пример с отжиманиями то 56983 \ 2 = 28491.5 — но у Васи всё после запятой обрубается — и он видит только целое число — причём неважно там будет 28491.000001 или там будет 28491.9999999 — для Васи это один фиг будет 28491 в обоих случаях. Ничего не округляется. Ещё важная информация про Васю. Вася жесток — ему пофиг на то, что Стив затрахается отжиматься двадцать восемь тысяч раз. Ему сказали — Вася перевёл. Причём не только перевёл — но и заставил сделать то, что Вы попросили. Так что если Стив помрёт на двадцать три тысячи пятьсот тринадцатом отжимании — то это будет исключительно Ваша вина.
Собственно это пока что всё. В следующем посте будем копать глубже — пока же просто достаточно понять это. Просто представить эту ситуацию и понять что к чему, кто исполняет какую роль и чем директива отличается от оператора.
А дальше мы постараемся называть всё своими именами и примерно прикинуть как же ассемблер работает с микроконтроллером по взрослому.
Клон знаменитого Tetris, написанный на ассемблере. Он целиком вмещается в 512 байт загрузочного сектора (ему требуется всего 446 байт места, это как раз максимальный размер загрузчика в MBR).
MBR — раздел, содержащий код и данные, необходимые для последующей загрузки операционной системы и расположенные в первых физических секторах. Самые первые 446 байт диска отдаются под код загрузчика. Именно в это место и записывается TetrOS.
Естественно, из-за таких свойств он загружается перед любой операционной системой — никакой ОС ему не требуется, он работает сам. Да-да, вы не ослышались, TetrOS — сам себе загрузчик.
Вот так это выглядит на экране:
А исходник на загрузочном секторе выглядит так:
И да, это весь исходник. Вы же помните, что он весит всего 446 байт?
Можно запустить эту «чудо-операционную систему» под qemu или даже по-настоящему установить на загрузочный раздел диска или флешки.
Запуск
Просто установите qemu:
sudo apt-get install qemu
и запустите:
Загрузка на флешку
Скопируйте образ на флешку. Допустим, если флешка подмонтирована как /dev/sde , вам понадобится выполнить следующую команду, чтобы записать на ее загрузочный сектор TetrOS:
sudo dd if=tetros.img of=/dev/sde
Описание игры
Разработчик сумел всего в 512 байт памяти впихнуть не самый скучный дизайн. У каждого кирпичика в игре есть свой цвет, управление производится кнопками, в случае поражения игра завершается, кирпичики генерируются случайным образом… BolgenOS и рядом не стояла!
К несчастью, из-за размера от некоторых фич пришлось отказаться. В игре нет подсчета очков, рестарта игры без перезагрузки и отображения того, каким будет следующий кирпичик.
Название: Практическое программирование микроконтроллеров Atmel AVR на языке ассемблера 2 издание
Издательство: «БХВ-Петербург»
Год издания: 2011
Страниц: 354
Язык: Русский
Формат: DjVu
Размер: 12,2 Мб
Наложены принципы функционирования, особенности архитектуры и приемы программирования микроконтроллеров Atmel AVR.
Приведены готовые рецепты для программирования основных функций современной микроэлектронной аппаратуры: от реакции на нажатие кнопки или построения динамической индикации до сложных протоколов записи данных во внешнюю память или особенностей подключения часов реального времени. Особое внимание уделяется обмену данными микроэлектронных устройств с персональным компьютером, приводятся примеры программ. В книге учтены особенности современных моделей AVR и сопутствующих микросхем последних лет выпуска.
Приложение содержит основные параметры микроконтроллеров AVR, перечень команд и тексты Приложения содержат основные параметры микроконтроллеров AVR, перечень команд и тексты программ для них, а также список используемых терминов и аббревиатур.
Для учащихся, инженерно-технических работников и радиолюбителей
7. Микроконтроллеры, их возникновение и применение
8. Предыстория микроконтроллеров
10. Электроника в греческом стиле
12. Почему AVR?
14. Что дальше?
17.ЧАСТЬ L ОБЩИЕ ПРИНЦИПЫ УСТРОЙСТВА И ФУНКЦИОНИРОВАНИЯ ATMEL AVR
19. Глава 1. Обзор микроконтроллеров Atmel AVR
21. Семейства AVR
23. Особенности практического использования МК AVR
23. О потреблении
25. Некоторые особенности применения AVR в схемах
27. Глава 2. Общее устройство, организация памяти, тактирование, сброс
27. Память программ
29. Память данных (ОЗУ, SRAM)
31. Энергонезависимая память данных (EEPROM)
32. Способы тактирования
34. Сброс
37. Глава 3. Знакомство с периферийными устройствами
38. Порты ввода-вывода
39. Таймеры-счетчики
41. Аналогово-цифровой преобразователь
42. Последовательные порты
43. UART
46. Интерфейс SPI
50. Интерфейс TWI (I2С)
50. Универсальный последовательный интерфейс USI
53. Глава 4. Прерывания и режимы энергосбережения
53. Прерывания
57. Разновидности прерываний
58. Режимы энергосбережения
61. ЧАСТЬ II. ПРОГРАММИРОВАНИЕ МИКРОКОНТРОЛЛЕРОВ ATMELAVR
63. Глава 5. Общие принципы программирования МК семейства AVR
63. Ассемблер или С?
67. Способы и средства программирования AVR
67. Редактор кода
68. Об AVR Studio
70. Обустройство ассемблера
71. Программаторы
75. О hex-файлах
78. Команды, инструкции и нотация AVR-ассемблера
79. Числа и выражения
80. Директивы и функции
84. Общая структура АVR-программы
85. Обработка прерываний
89. RESET
90. Простейшая программа
92. Задержка
94. Программа счетчика
96. Использование прерываний
97. Задержка по таймеру
98. Программа счетчика с использованием прерываний
101. О конфигурационных битах
105. Глава 6, Система команд AVR
105. Команды передачи управления и регистр SREG
111. Команды проверки-пропуска
113. Команды логических операций
114. Команды сдвига и операции с битами
116. Команды арифметических операций
118. Команды пересылки данных
122. Команды управления системой
123. Выполнение типовых процедур на ассемблере
125. О стеке, локальных и глобальных переменных
127. Глава 7. Арифметические операции
128. Стандартные арифметические операции
129. Умножение многоразрядных чисел
131. Деление многоразрядных чисел
134. Операции с дробными числами
136. Генератор случайных чисел
138. Операции с числами в формате BCD
143. Отрицательные числа в МК
147. Глава 8. Программирование таймеров
147. 8- и 16-разрядные таймеры
149. Формирование заданного значения частоты
153. Отсчет времени
158. Точная коррекция времени
160. Частотомер и периодомер
160. Частотомер
164. Периодомер
167. Управление динамической индикацией
168. LED-индикаторы и их подключение
171. Программирование динамической индикации
174. Таймеры в режиме PWM
179. Глава 9. Использование EEPROM
179. Еще раз о сохранности данных в EEPROM
181. Запись и чтение EEPROM
183. Хранение констант в EEPROM
187. Глава 10. Аналоговый компаратор и АЦП
187. Аналого-цифровые операции и их погрешности
190. Работа с аналоговым компаратором
193. Интегрирующий АЦП на компараторе
194. Принцип работы и расчетные формулы
198. Программа интегрирующего АЦП
201. Встроенный АЦП
204. Пример использования АЦП
206. Программа
215. Глава 11. Программирование SPI
215. Основные операции через SPI
216. Аппаратный вариант
218. Программный вариант
219. О разновидностях энергонезависимой памяти
221. Запись и чтение flash-памяти через SP!
224. Программа обмена с памятью 45DB011В по SPI
225. Запись и чтение flash-карт
225. Подключение карт ММС
228. Подача команд и инициализация ММС
232. Запись и чтение ММС
237. Глава 12. Интерфейс TW1 (I2С) и его практическое использование
237. Базовый протокол 1 2 С
240. Программная эмуляция протокола I 2 С
241. Запись данных во внешнюю энергонезависимую память
241. Режимы обмена с памятью АТ24
243. Программа
247. Часы с интерфейсом I 2 С
255. Запись данных
259. Чтение данных
261. Глава 13. Программирование UART/USART
262. Инициализация UART
263. Передача и прием данных
266. Пример установки часов DS1307 с помощью UART
271. Приемы защиты от сбоев при коммуникации
271. Проверка на четность
273. Как организовать корректный обмен
274. Дополнительные возможности USART
276. Реализация интерфейсов RS-232 и RS-485
280. Преобразователи уровня для RS-232
283. RS-485
285. Глава 14. Режимы энергосбережения и сторожевой таймер
286. Программирование режима энергосбережения
287. Пример прибора с батарейным питанием
289. Доработка программы
293. Использование сторожевого таймера
299. ПРИЛОЖЕНИЯ
301. Приложение 1. Основные параметры микроконтроллеров Atmel AVR
309. Приложение 2. Команды Atmel AVR
310. Арифметические и логические команды
311. Команды операций с битами
312. Команды сравнения
313. Команды передачи управления
313. Команды безусловного перехода и вызова подпрограмм
314. Команды проверки-пропуска и команды условного перехода
315. Команды переноса данных
316. Команды управления системой
317. Приложение 3. Тексты программ
317. Демонстрационная программа обмена данными с flash-памятью 45DB011В по интерфейсу SPI
321. Процедуры обмена по интерфейсу I2С
329. Приложение 4. Обмен данными с персональным компьютером и отладка программ через UART
329. Работа с СОМ-портом в Delphi
335. Установка линии RTS в DOS и Windows
337. Программа СОМ2000
339. Отладка программ с помощью эмулятора терминала
341. Приложение 5. Словарь часто встречающихся аббревиатур и терминов
347. Литература
349. Предметный указатель
для системы мэйнфрейма
Методы программирования или кодирования на ассемблере для системы мэйнфрейма Уловки программирования на ассемблере Примеры мэйнфреймов с комментариями |
|
Этот набор примеров программ написан на IBM Mainframe Assembler.Программы будут компилироваться с использованием Assembler / H или HLASM. Этот пакет предоставляет примеры некоторых методов кодирования, которые использовались программистами на ассемблере мэйнфреймов. Они будут запускаться как пакетные задания MVS на мэйнфрейме IBM или как проект с Micro Focus Mainframe Express (MFE), работающий на ПК с Windows (см. http://www.microfocus.com ).
Эта программа может служить учебным пособием для программистов, которые не знакомы с ассемблером 370, или справочником для опытных программистов.
Мы приложили значительные усилия, чтобы документы и программные технологии были правильными и точными. Мы оставляем за собой право вносить изменения без предварительного уведомления в любое время. Функция, предоставляемая в этой версии, основана на запросах на расширение от конкретной группы пользователей. Цель состоит в том, чтобы вносить изменения по мере необходимости и в сроки, которые зависят от наличия ресурсов.
Copyright © 1987-2021
SimoTime Technologies and Services
Все права защищены
В этом разделе представлены примеры конкретных методов кодирования.
IEFBR14, очень маленькая программа
На мэйнфрейме файлы могут быть размещены, созданы или удалены с помощью операторов DD в JCL (языке управления заданиями). Кроме того, JCL требует наличия операторов JOB и EXEC. Если бы программист просто хотел создать файл, используя член JCL с оператором JOB и оператором DD, это вызвало бы ошибку. Если программист добавил оператор EXEC, ключевое слово PGM требует имени программы, и эта программа будет выполняться.Следовательно, потребность в программе, которая просто возвращалась к вызывающей стороне, стала требованием. Первая версия этой программы была двухбайтовой (или x’07FE ‘) и называлась «самой маленькой программой в мире».
ЭТИКЕТКА ДАННЫХ ОПЕРАЦИИ КОММЕНТАРИИ IEFBR14 CSECT 07FE BR 14 Возврат к вызывающему через Reg-14 КОНЕЦ
В предыдущем примере код операции BR — это расширенная мнемоника для инструкции BCR (переход по регистру условий).Мнемоника BR генерирует команду BCR, которая устанавливает все биты маски в 1, и это вызывает безусловный переход к адресу, определенному в регистре 14.
Примечание: это стандартный протокол для вызывающей программы, обеспечивающий адрес возврата в регистре 14.
Если мы внимательно посмотрим на фактически сгенерированный, два байта кода (или x’07FE ‘), «07» — это код операции для инструкции BCR. «F» байта «FE» является маской для ветвления, и, поскольку все биты включены, он становится безусловным ветвлением.Буква «E» байта «FE» указывает регистр 14.
Незадолго до того, как было сообщено о первой «ошибке». «Код возврата» устанавливался на ненулевое значение, и последующие шаги задания, которые зависели от кода возврата, завершались ошибкой. В считанные минуты было внесено исправление, и размер программы удвоился до четырех байтов (или x’1BFF07FE ‘).
ЭТИКЕТКА ДАННЫХ ОПЕРАЦИИ КОММЕНТАРИИ IEFBR14 CSECT 1BFF SR 15,15 Вычтите Reg-15 из самого себя, получив ноль (код возврата) 07FE BR 14 Возврат к вызывающему через Reg-14 КОНЕЦ
В предыдущем примере код операции SR является мнемоникой для инструкции SR (вычитание регистра).Следовательно, вычитание содержимого регистра 15 из самого себя приводит к нулевому значению.
Примечание. Это стандартный протокол для регистра 15, который используется для хранения значения кода возврата.
Эта новая версия работает уже много лет без каких-либо ошибок. Это история о том, «почему и как» была создана программа, известная как IEFBR14.
Логика в первый раз
Иногда процедура ассемблера вызывается много раз и содержит сегменты кода, которые необходимо выполнить только при первом вызове процедуры.Ниже приводится пример техники кодирования, используемой для выполнения сегмента кода при первом вызове подпрограммы.
ЭТИКЕТКА ДАННЫХ ОПЕРАЦИИ КОММЕНТАРИИ 4700B00C NOBRANCH BC X'00 ', ONEJUMP В первый раз пройти нельзя 92F0B001 MVI NOBRANCH + 1, X'F0 'Перейти к безусловному переходу 47F0B000 B NOBRANCH Логика первого раза, выполнить один раз ONEJUMP EQU *
Это метод, который обычно используется для выполнения первоначальной или одноразовой логики.Инструкция ветвления кодируется с нулевой маской и никогда не будет ветвиться. Он провалится и выполнит следующую последовательную инструкцию. Первоначальная логика вставляется после ветви. Команда Move Immediate используется для преобразования инструкции Branch в безусловное ветвление. Код, следующий за ветвью, не будет выполняться снова, пока не будет загружена новая копия программы.
Примечание. Этот метод был приемлемой практикой много лет назад, потому что он был быстрым и требовал всего восьми байтов памяти.Однако в современном мире структурированного программирования использование динамического самомодифицирующегося кода больше не является общепринятой практикой.
См. Первый раз или разовая логика для более подробной информации. Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
Создать двоичную таблицу
Это довольно эзотерический метод кодирования для создания последовательной 256-байтовой таблицы набора символов с использованием одной инструкции.Этот метод использует функцию константы адресации (ADCON) ассемблера мэйнфрейма. Давайте посмотрим, как 256AL1 (* — TABLE) создает 256-байтовую таблицу EBCDIC. Во-первых, AL1 говорит создать однобайтовый ADCON. Значение 256 говорит о том, что процесс создания будет повторяться 256 раз. Теперь трюк, (* -TABLE) вычисляет значение каждого из 256 однобайтовых ADCON, беря значение текущего адреса (указанного *) и вычитая адрес TABLE. Например, предположим, что таблица будет расположена по адресу x’00010000 ‘.При первом создании ADCON адрес таблицы — x’00010000 ‘, текущий адрес — x’00010000’, а результирующий ADCON — x’00 ‘.
На второй итерации адрес таблицы по-прежнему x’00010000 ‘, но текущий адрес теперь x’00010001’, а результирующий ADCON равен x’01 ‘Этот процесс повторяется 256 раз.
ТАБЛИЦА DC 256AL1 (* - ТАБЛИЦА) * Создать 256-байтовую ТАБЛИЦУ
Предыдущий оператор сгенерирует следующее.
Адресные данные 00010000 000102030405060708090A0B0C0D0E0F 00010010 101112131415161718191A1B1C1D1E1F 00010020 202122232425262728292A2B2C2D2E2F 00010030 303132333435363738393A3B3C3D3E3F 00010040 404142434445464748494A4B4C4D4E4F 00010050 505152535455565758595A5B5C5DestiveF 00010060 606162636465666768696A6B6C6D6E6F 00010070 707172737475767778797A7B7C7D7E7F 00010080 858182838485868788898A8B8C8D8E8F 00010090
Примечание: предыдущая техника может считаться излишне умной.Для ясности, возможно, лучше будет кодировать следующим образом.
ТАБЛИЦА EQU * DC XL16'000102030405060708090A0B0C0D0E0F ' DC XL16'101112131415161718191A1B1C1D1E1F ' DC XL16'202122232425262728292A2B2C2D2E2F ' DC XL16'303132333435363738393A3B3C3D3E3F ' DC XL16'404142434445464748494A4B4C4D4E4F ' DC XL16'505152535455565758595A5B5C5DestiveF ' DC XL16'606162636465666768696A6B6C6D6E6F ' DC XL16'707172737475767778797A7B7C7D7E7F ' DC XL16'858182838485868788898A8B8C8D8E8F ' DC XL16'
См. Таблица в исходном коде для более подробной информации.Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
Увеличение содержимого регистра
Это общий метод кодирования, используемый для увеличения содержимого регистра. Есть много способов увеличить содержимое регистра, но этот метод использует одну инструкцию и не использует никаких элементов данных в памяти.
LA R3,1 (, R3) * Увеличить РЕГИСТР-3 на 1
Предыдущая инструкция загрузки адреса (LA) загрузит в R3 значение, содержащееся в R3, плюс значение смещения или 1.Поскольку величина для увеличения регистра содержится в 3-байтовом значении смещения инструкции LA, содержимое регистра может быть увеличено на значение от 1 до 4095 (то есть от x’001 ‘до x’FFF’.
См. Процедура увеличения регистра в исходном коде для более подробной информации. Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
Уменьшить содержимое регистра
Это общий метод кодирования, используемый для уменьшения содержимого регистра.Есть много способов уменьшить содержимое регистра, но этот метод использует одну инструкцию и не использует никаких элементов данных в памяти.
BCTR R3, R0 * Если OP-2 равен 0, тогда DECR OP-1, NO BRANCH
Предыдущий оператор использует уникальную характеристику инструкции Branch-on-Count-Register (BCTR). Обычно BCTR уменьшает значение в регистре, указанном в операнде-1, и когда содержимое регистра операнда-1 не равно нулю, выполняется переход к адресу, указанному в операнде 2.Есть одно исключение: если операнд-2 равен нулю, то ветвление никогда не выполняется. Следовательно, регистр операнда-1 уменьшается, и ветвление никогда не выполняется. В предыдущем операторе R3 будет уменьшен на единицу, и переход никогда не будет выполняться.
См. Процедура уменьшения регистра в исходном коде для более подробной информации. Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
Установите ON, старший бит регистра
Это обычный метод кодирования, используемый для приведения бита высокого порядка (самого левого) регистра в состояние ВКЛ.
O R3, = X'80000000 '* УСТАНОВИТЬ БИТ ВЫСОКОГО РАЗРЯДА НА X'80000000'
В этом методе используется инструкция OR (O), и в этом примере значение в памяти x’80000000 ‘объединяется с содержимым регистра-3, а результат помещается в регистр-3. Следовательно, если содержимое регистра-3 до выполнения инструкции содержит x’00000000 ‘, то после выполнения предыдущей инструкции OR содержимое регистра-3 будет равно x’80000000’.
Ассемблер мэйнфрейма может динамически создавать литералы.= X’80000000 ‘в предыдущем операторе заставит компилятор сгенерировать эквивалент следующей инструкции.
DC X'80000000 '
Пул литералов для динамически заданных литералов создается в конце CSECT, если не используется оператор LTORG. Когда используется оператор LTORG, будут сгенерированы литералы, созданные до момента выполнения оператора LTORG.
См. Установите бит высокого порядка в положение ON для более подробной информации.Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
Выключить, старший бит регистра
Это обычный метод кодирования, используемый для приведения старшего (крайнего левого) бита регистра в состояние ВЫКЛЮЧЕНО.
N R3, = X'7FFFFFFF '* ВЫКЛЮЧИТЬ БИТ ВЫСОКОГО РАЗРЯДА X'7F010203'
В этом методе используется инструкция AND (N), и в этом примере значение в памяти x’7FFFFFFF ‘соединяется с содержимым регистра-3, а результат помещается в регистр-3.Следовательно, если содержимое регистра-3 до выполнения инструкции содержит x’FF010203 ‘, то после выполнения предыдущей инструкции AND содержимое регистра-3 будет равно x’7F010203’.
Ассемблер мэйнфрейма может динамически создавать литералы. = X’7FFFFFFF ‘в предыдущем операторе заставит компилятор сгенерировать эквивалент следующей инструкции.
ДК X'7FFFFFFF '
Пул литералов для динамически заданных литералов создается в конце CSECT, если не используется оператор LTORG.Когда используется оператор LTORG, будут сгенерированы литералы, созданные до момента выполнения оператора LTORG.
См. Установите бит высокого порядка в положение ВЫКЛ. для более подробной информации. Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
Инициализировать поле пробелами
Это распространенный метод кодирования, используемый для инициализации поля пробелами.
MVI DATA80, X'40 '* Переместить пробел в 1-ю позицию MVC DATA80 + 1 (79), DATA80 * Распространение пространства через поле
Предыдущие два оператора используют то, как инструкция MOVE (MVC) выполняет функцию перемещения.Первый оператор использует инструкцию Move Immediate (MVI) для перемещения пробела в первый байт в 80-байтовом поле DATA80. Инструкция MVC выполняет побайтовое перемещение слева направо. Перемещая значение в ячейке памяти DATA80 в ячейку памяти DATA80 + 1, мы перемещаем пробел в следующую позицию в памяти. Поскольку длина MVC была определена как 79 байтов, этот процесс повторится, в результате все восемьдесят байтов DATA80 будут инициализированы пробелами.
См. Инициализация поля в пространствах для более подробной информации. Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
Поменять местами содержимое двух полей
Следующее использует результаты инструкции eXClusive-OR при многократном выполнении. Обратите внимание, что во втором eXClusive-OR поля поменяны местами.
XC WORKA16 (16), WORKZ16 * Следующие три исключающих ИЛИ XC WORKZ16 (16), инструкции WORKA16 меняют местами WORKA16 XC WORKA16 (16), содержимое WORKZ16 с содержимым WORKZ16
После выполнения трех предыдущих инструкций содержимое WORKA16 и WORKZ16 будет заменено местами.
См. Поменять местами поля для более подробной информации. Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
Установить / проверить код возврата на ноль
В этом разделе описывается, как установить или проверить значение кода возврата. Регистр 15 используется для передачи значения кода возврата между вызывающими программами. Поэтому, когда вы возвращаетесь к программе COBOL или заданию (JCL) и хотите, чтобы код возврата был равен нулю, вы должны поместить значение нуля (x’00000000 ‘) в регистр 15.
SR 15,15 * Установить КОД ВОЗВРАТА на НУЛЬ
или
LA 15,0 * Установить КОД ВОЗВРАТА на НУЛЬ
Есть несколько способов поместить значение в регистр 15. Предыдущие два оператора показывают, как установить регистр 15 в ноль. Первый метод быстрый и просто вычитает регистр 15 из самого себя.
Второй оператор также установит регистр 15 в ноль путем загрузки адреса, определенного в инструкции Load Address (LA), в регистр 15.В приведенном выше примере адрес (или значение) нуля будет загружен в регистр 15.
Следующие инструкции показывают, как проверить регистр 15 на нулевое или ненулевое значение.
LTR 15,15 * Загрузить R15 самим собой и протестировать контент BNZ ABENDRTN * Если R15 не ZERO, ответвите на ABENDRTN
Команда загрузки и тестирования регистра (LTR) загружает значение регистра в регистр и устанавливает код условия (не код возврата) в зависимости от того, равно ли значение целевого регистра нулю.В этом примере регистр 15 загружается своим содержимым и поэтому не изменяется. Однако код состояния устанавливается на основе содержимого регистра 15, являющегося нулевым или ненулевым значением.
Команда мнемонического перехода (BNZ) перейдет к подпрограмме аварийного завершения, если значение регистра 15 не равно нулю.
См. Установите код возврата на нулевую логику для более подробной информации. Чтобы вернуться к этому моменту, воспользуйтесь функцией браузера «назад».
LTORG
Ассемблер мэйнфрейма имеет возможность динамически создавать литералы при кодировании операторов ассемблера, используя определение литерала, которому предшествует знак равенства. Например, = X’C1C1C1C1 ‘или = C’AAAA’ вызовет выделение четырехбайтовой области памяти со значением «AAAA».
LTORG
Выше приведен пример оператора LTORG. Пул литералов для динамически заданных литералов создается в конце CSECT, если не используется оператор LTORG.Когда используется оператор LTORG, будут сгенерированы литералы, созданные до момента выполнения оператора LTORG.
Ниже приведен JCL мэйнфрейма (ASMTRXJ1.jcl), необходимый для запуска основной программы. Техника кодирования используется с ожиданием, что JCL будет использоваться как отдельная процедура. Это также будет работать на ПК с использованием Mainframe Express, предоставленного Micro Focus.
// ASMTRXJ1 JOB SIMOTIME, ACCOUNT, CLASS = 1, MSGCLASS = 0, NOTIFY = CSIP1 // * ********************************************** ******************** // * ASMTRXJ1.JCL - член JCL для пакетной обработки заданий * // * Этот член JCL предоставляется SimoTime Technologies * // * (C) Copyright 1987-2019 Все права защищены * // * URL веб-сайта: http://www.simotime.com * // * электронная почта: [email protected] * // * ********************************************** ******************** // * // * Текст - 370 Ассемблер, методы кодирования на ассемблере // * Автор - SimoTime Technologies // * Дата - 01 января 1997 г. // * // * Эта программа на ассемблере 370 покажет некоторые программные // * методы, используемые программистами на ассемблере.// * // * Этот набор программ будет работать на мэйнфрейме под MVS или на // * Персональный компьютер с Windows и Micro Focus Mainframe Express. // * // * Настоящее значение содержится в анимации этой программы. Ты можешь // * сразу видим результаты выполнения каждой инструкции. Этот // * - очень эффективный способ познакомиться с 370 //* набор инструкций. // * // * ********************************************** ******************** // * Шаг 1 из 1. Это одношаговое задание. // * // TRIXSTP1 EXEC PGM = ASMTRXA1 // СТЕПЛИБ DD DSN = SIMOTIME.DEMO.LOADLIB1, DISP = SHR // *
Эта программа (ASMTRXA1.mlc) не предоставляет много визуальной информации, когда она выполняется на мэйнфрейме. Настоящая ценность этой программы заключается в том, что она анимируется с использованием опции 370 Assembler в Mainframe Express, предоставляемой Micro Focus. Можно наблюдать за фактическим выполнением каждой отдельной инструкции и сразу видеть результаты.
ASMTRXA1 CSECT ************************************************* ********************* * ASMTRXA1.MLC - это программа HLASM * * Предоставлено SimoTime Technologies * * (C) Copyright 1987-2019 Все права защищены * * URL веб-сайта: http://www.simotime.com * * электронная почта: [email protected] * ************************************************* ********************* * Создано: 1993/06/01, Simmons * * Изменено: 1993/06/01, Simmons, на сегодняшний день изменений нет... * * * ************************************************* ********************* * * * Micro Focus Mainframe Express, версия 2.5 или новее с * * Требуется опция Ассемблера. Эта программа предоставляет образец * * некоторых методов кодирования, используемых программистами на ассемблере. * * Вы можете сразу увидеть результаты выполнения каждой инструкции.* * Это очень эффективный способ узнать, как эти * * техники работают. * * * * Примечание: комментарии к операторам EQU представляют собой ссылки HTML. * * * ************************************************* ********************* * BALR 11,0 Подготовить базовый регистр ИСПОЛЬЗОВАНИЕ *, 11 Установить регистр как базу * ************************************************* ********************* * ВТО для отображения информации об авторских правах * WTO '* ASMTRXA1 Примеры советов по кодированию на ассемблере v03.01.24- http://www.simotime.com ' LTR R15, R15 IS REG-15 = НУЛЬ ... BNZ ABEND4 ЕСЛИ НЕТ, ABEND ... * WTO '* ASMTRXA1 Авторские права 1987-2019 SimoTime Technologies- Все права защищены' LTR R15, R15 IS REG-15 = НУЛЬ ... BNZ ABEND4 ЕСЛИ НЕТ, ABEND ... * WTO '* ASMTRXA1 НАЧИНАЕТСЯ ...' * ONETIME EQU * ************************************************* ********************* * Это метод, который обычно используется при первом или * разовая логика.Инструкция ветвления кодируется с нулевой маской. * и никогда не разветвляется. Он провалится и выполнит следующий * последовательная инструкция. Первоначальная логика вставляется после * ветка. Инструкция Move Immediate используется для изменения Branch * инструкция быть безусловным переходом. Код, следующий за * ветка не будет выполняться, пока не будет загружена новая копия программы. ************************************************* ********************* NOBRANCH BC X'00 ', ONEJUMP В первый раз пройти нельзя MVI NOBRANCH + 1, X'F0 'Переход к безусловному переходу B NOBRANCH Логика первого раза, выполнить один раз ONEJUMP EQU * * ТАБЛЕРТН EQU * ************************************************* ********************* * Вот как вы создаете 256-байтовую таблицу набора символов EBCDIC * в одной инструкции.Это довольно эзотерический прием. * Также обратите внимание на технику, используемую для разветвления вокруг стола * без необходимости использовать этикетку. ************************************************* ********************* В * + 4 + 256 * ФИЛИАЛ вокруг СТОЛА ТАБЛИЦА DC 256AL1 (* - ТАБЛИЦА) * Создать 256-байтовую ТАБЛИЦУ * INCRREGS EQU * ************************************************* ********************* * Вот как вы увеличиваете содержимое регистра. * * Значение приращения может быть от 1 до 4095.* ************************************************* ********************* LA R3,0 * Установить R3 на НУЛЬ X'00000000 ' LA R3,1 (, R3) * Увеличить REG-3 на 1 X'00000001 ' LA R3,2 (, R3) * Увеличить REG-3 на 2 X'00000003 ' LA R3,3 (, R3) * Увеличить REG-3 на 3 X'00000006 ' * DECRREGS EQU * ************************************************* ********************* * Вот как вы уменьшаете содержимое регистра.* * Уменьшающее значение ограничено 1. * * Когда второй операнд указывает на регистр-0, ветвления нет. * ************************************************* ********************* LA R3,5 * УСТАНОВИТЬ R3 на ПЯТЬ X'00000005 ' BCTR R3, R0 * DECR OP-1, NO BRANCH X'00000004 ' BCTR R3, R0 * DECR OP-1, NO BRANCH X'00000003 ' BCTR R3, R0 * DECR OP-1, NO BRANCH X'00000002 ' * BITON EQU * ************************************************* ********************* * Установите старший бит регистра в состояние ВКЛ.* ************************************************* ********************* LA R3,0 * Установить R3 в ноль O R3, = X'80000000 '* УСТАНОВИТЬ БИТ ВЫСОКОГО РАЗРЯДА НА X'80000000' * BITOFF EQU * ************************************************* ********************* * Установите старший бит регистра в состояние ВЫКЛ. * ************************************************* ********************* L R3, = X'FF010203 '* Установите R3 в HEX FF010203 N R3, = X'7FFFFFFF '* ВЫКЛЮЧИТЬ БИТ ВЫСОКОГО РАЗРЯДА X'7F010203' * INIT80 EQU * ************************************************* ********************* * Инициализировать восьмидесятибайтовое поле пробелами.* ************************************************* ********************* MVI DATA80, X'40 '* Переместить пробел в 1-ю позицию MVC DATA80 + 1 (79), DATA80 * Распространение пространства через поле * SWAP16 EQU * ************************************************* ********************* * Один из уникальных результатов выполнения трех дополнительных инструкций ИЛИ * * - содержимое определенных элементов поменялось местами. * ************************************************* ********************* MVC WORKA16, A16 Переместите все A в WORKA16 MVC WORKZ16, Z16 Переместить все Z в WORKZ16 XC WORKA16 (16), WORKZ16 * Следующие три исключающих ИЛИ XC WORKZ16 (16), инструкции WORKA16 меняют местами WORKA16 XC WORKA16 (16), содержимое WORKZ16 с содержимым WORKZ16 * RCTOZERO EQU * ************************************************* ********************* * Проверить код возврата (Регистр-15) на нулевое значение * ************************************************* ********************* MVC WTODATA (8), = C'LTRICK ' LA R15,0 * Установить R15 на нулевое значение LTR R15, R15 * Загрузить R15 самим собой и протестировать контент BZ * + 8 * Если ноль, перейти к следующей инструкции B ABEND08 * Эта инструкция никогда не должна выполняться * ************************************************* ********************* * ОБЫЧНЫЙ КОНЕЦ РАБОТЫ * * ВОЗВРАТ В ПРОГРАММУ ВЫЗОВА ИЛИ ОПЕРАЦИОННУЮ СИСТЕМУ * ************************************************* ********************* WTO '* ASMTRXA1 ЗАВЕРШЕН... ' SR 15,15 * Установить КОД ВОЗВРАТА на НУЛЬ BR 14 * ВОЗВРАТ К АБОНЕНТУ * ABEND4 EQU * ************************************************* ********************* * ОТКАЗ ОТ КОДА ВОЗВРАТА 4 * * WTO '* ASMTRXA1 MLC, ОТКАЗЫВАЕТСЯ, RC = 4 ...' ВОЗВРАТ (14,12), RC = 4 * * ABEND08 EQU * * ABEND процедура ************************************************* ********************* * ВОЗВРАЩЕНИЕ С КОДОМ ВОЗВРАТА 8 * * ВОЗВРАТ В ПРОГРАММУ ВЫЗОВА ИЛИ ОПЕРАЦИОННУЮ СИСТЕМУ * ************************************************* ********************* WTO MF = (E, WTOBLOCK) LA R15,8 BR 14 WTOBLOCK DC H'84 ' DC XL2'0000 ' WTODATA DC CL80 '???????? ASMTRXA1 ОТКАЗЫВАЕТСЯ... ' ************************************************* ********************* * Определите константы и уравнения * ************************************************* ********************* DS 0F + силовое выравнивание ДАННЫЕ80 DC 80XL1'00 ' * LTORG * R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 * DS 0F + силовое выравнивание A16 постоянного тока 16CL1'A ' Z16 DC 16CL1'Z ' WORKA16 DC 16CL1'A ' WORKZ16 DC 16CL1'Z ' * КОНЕЦ
Этот документ может быть использован как руководство для начинающих программистов на ассемблере или как краткий справочник для опытных программистов.В примерах основное внимание уделяется методам кодирования отдельных инструкций. Как всегда, программист обязан тщательно протестировать все программы.
В мире программирования есть много способов решить проблему. Эта документация и программное обеспечение были разработаны и протестированы на системах, которые настроены для среды SIMOTIME на основе оборудования, операционных систем, требований пользователей и требований безопасности. Следовательно, могут потребоваться корректировки для выполнения заданий и программ при переносе в систему с другой архитектурой или конфигурацией.
SIMOTIME Services имеет опыт перемещения или совместного использования данных или обработки приложений в различных системах. Для получения дополнительной информации об услугах или технологиях SIMOTIME свяжитесь с нами, используя информацию в разделе комментариев или отзывов в этом документе.
Соглашение о программном обеспечении и отказ от ответственности
Разрешение на использование, копирование, изменение и распространение этого программного обеспечения, документации или учебных материалов для любых целей требует оплаты SimoTime Technologies.Как только плата будет получена SimoTime, будет доставлена последняя версия программного обеспечения, документация или учебные материалы, и будет предоставлена лицензия для использования на предприятии при условии, что уведомление об авторских правах SimoTime появится на всех копиях программного обеспечения. Имя или логотип SimoTime нельзя использовать в какой-либо рекламе или рекламе, относящейся к использованию программного обеспечения, без письменного разрешения SimoTime Technologies.
SimoTime Technologies не дает никаких гарантий и не делает заявлений относительно пригодности программного обеспечения, документации или учебных материалов для каких-либо целей.Он предоставляется «КАК ЕСТЬ» без каких-либо явных или подразумеваемых гарантий, включая подразумеваемые гарантии товарной пригодности, пригодности для определенной цели и ненарушения прав. SimoTime Technologies не несет ответственности за любые прямые, косвенные, особые или косвенные убытки, возникшие в результате потери возможности использования, данных или проектов, будь то в результате действия контракта или правонарушения, возникшего в результате или в связи с использованием или производительностью этого программного обеспечения. , документацию или учебные материалы.
Загрузки и ссылки
Примечание: Лицензия SimoTime требуется для того, чтобы элементы были доступны в локальной системе или на сервере.
В этот раздел включены ссылки на документы с дополнительной информацией, выходящие за рамки и цели этого документа. Первая группа документов может быть доступна из локальной системы или через подключение к Интернету, для второй группы документов потребуется подключение к Интернету.
Примечание: Лицензия SimoTime требуется для того, чтобы элементы были доступны в локальной системе или на сервере.
Текущий сервер или доступ в Интернет
Следующие ссылки могут указывать на текущий сервер или в Интернет.
Изучите Assembler Connection для получения дополнительных примеров методов программирования на ассемблере для мэйнфреймов и примеров кода.
Изучите соединение JCL для получения дополнительных примеров функциональности JCL с методами программирования и образцами кода.
Изучите расширенный список программных технологий, доступных для обзора и оценки. Программные технологии (или Z-Packs) предоставляют отдельные примеры программирования, документацию и файлы тестовых данных в одном пакете.Z-пакеты обычно имеют формат zip, чтобы сократить время загрузки.
Изучите таблицы перевода ASCII и EBCDIC. Эти таблицы предназначены для лиц, которым необходимо лучше понимать битовые структуры и различия форматов кодирования.
Изучите коды возврата состояния файла, чтобы интерпретировать результаты доступа к наборам данных VSAM и / или файлам QSAM.
Требуется доступ в Интернет
Для следующих ссылок потребуется подключение к Интернету.
Этот набор программ и документации можно загрузить для ознакомления и оценки. Для других целей потребуется лицензия на программное обеспечение SimoTime. Ссылка на оценочную опцию zPAK, которая включает участников программы, документацию и управляющие файлы.
Хорошее место для начала — Домашняя страница SimoTime для доступа к официальным документам, примерам программ и информации о продуктах. Эта ссылка требует подключения к Интернету
Узнать Веб-сайт Micro Focus для получения дополнительной информации о продуктах (включая Micro Focus COBOL) и услугах Micro Focus.Эта ссылка требует подключения к Интернету.
Словарь терминов
Изучите Глоссарий терминов, чтобы получить список терминов и определений, используемых в этом наборе документов и официальных документов.
Комментарии или обратная связь
Этот документ был создан и поддерживается SimoTime Technologies. Если у вас есть какие-либо вопросы, предложения, комментарии или отзывы, пожалуйста, используйте следующую контактную информацию.
1. | Отправьте электронное письмо в нашу службу поддержки. |
2. | Наши номера телефонов следующие. |
2.1. | 1415763-9430 офис-справочная |
2.2. | 1 415 827-7045 мобильный |
Мы ценим ваш отзыв.
Обзор компании
SimoTime Technologies была основана в 1987 году и является частной компанией.Мы специализируемся на создании и развертывании бизнес-приложений с использованием новых или существующих технологий и услуг. У нас есть команда людей, которые разбираются в широком спектре технологий, используемых в современных средах. Среди наших клиентов — малые предприятия, использующие Интернет-технологии, и корпорации, использующие очень большие системы мэйнфреймов.
Довольно часто, чтобы выйти на более крупные рынки или предоставить более высокий уровень обслуживания существующим клиентам, требуется, чтобы новые Интернет-технологии работали в дополнение к существующим корпоративным системам мэйнфреймов.Мы специализируемся на подготовке приложений и связанных данных, которые в настоящее время хранятся на одной платформе, для распределения по множеству платформ.
Подготовка прикладных программ потребует передачи исходных элементов, которые будут скомпилированы и развернуты на целевой платформе. Данные необходимо будет передавать между системами и, возможно, потребуется преобразовать и проверить на различных этапах процесса. SimoTime обладает технологиями, услугами и опытом, чтобы помочь в решении задач управления приложениями и данными, связанных с ведением бизнеса в мультисистемной среде.
Если вы хотите использовать Интернет для выхода на новые сегменты рынка или в качестве средства доставки существующих бизнес-функций, просто позвоните нам или посетите веб-сайт http://www.simotime.com
Вернуться к началу |
Программирование на ассемблере или методы кодирования для системы мэйнфрейма |
Авторские права © 1987-2021 SimoTime Technologies and Services Все права защищены |
Когда технологии дополняют бизнес |
http: // www.simotime.com |
Bixoft — Примеры программ на ассемблере
Bixoft — Примеры программ на ассемблереЭта страница содержит следующие фрагменты кода:
Мы хотели бы отметить, хотя это может быть излишним, что стандарт регистровые присвоения следующие:
Регистр | Функция |
---|---|
Регистр 0 | Рабочий регистр, в основном используется как параметр |
Регистр 1 | Рабочий регистр, обычно используется как указатель на список параметров или поле результата |
Регистры 2-11 | Может быть присвоено произвольно в каждой программе |
Регистр 12 | Базовый регистр для адресации в программе |
Регистр 13 | Указатель на бесплатную зону сохранения |
Регистр 14 | Рабочий регистр, обычно используется для обратных адресов |
Регистр 15 | Рабочий регистр, используемый для адреса подпрограммы или (при возврате) возвращаться- и коды причин |
Стандартный вызов подпрограммы.
Принудительно применяется даже самый распространенный способ вызова подпрограммы. Все же это посоветовал придерживаться давних практик. Это улучшает как читаемость и ремонтопригодность ваших программ. Обычное соглашение:
- При звонке:
- Регистр 0 содержит параметр (при необходимости)
- Регистр 1 содержит адрес списка параметров
- Регистр 13 содержит адрес области сохранения
- Регистр 14 содержит обратный адрес
- Регистр 15 содержит адрес точки входа вызываемого программа
- По возвращении:
- Регистр 0 мог быть изменен или не изменен
- Регистр 1 содержит адрес (если применимо) результатов
- Регистры со 2 по 14 без изменений
- Регистр 15 содержит возврат и (если применимо) код причины
Область сохранения состоит из 18 полных слов (по 4 байта) и придерживается к этим правил:
Расположение | Содержимое |
---|---|
X’00 ‘ | Зарезервировано для PL / I |
X’04 ‘ | Указатель на предыдущую область сохранения (т.е.е. регистр 13) |
X’08 ‘ | Указатель на следующую зону сохранения |
X’0C ‘ | Регистр 14 |
X’10 ‘ | Регистр 15 |
X’14 ‘ | Регистр 0 |
и т. Д. | до реестра 12 |
Далее следуют три фрагмента кода:
- Вызов подпрограммы.
- Вызываемая программа многократного использования.
Этот пример можно использовать только для многоразового и одноразового использования. программы, но не для программ с возможностью повторного входа или обновления. - Обновляемая программа с возможностью вызова.
Этот пример предназначен для повторных и обновляемых программ. Конечно его можно использовать как для многоразовых, так и для одноразовых программ.
* * Пример вызова подпрограммы. * * Мы предполагаем, что список параметров настроен LA R1, PLIST Reg.1 указывает на список параметров L R15, = V (ПОДПРОГРАММА) Адрес подпрограммы в рег.15 BALR R14, R15 Заполните регистр 14 и вызовите подпрограмму * Обработка результата LTR R0, R15 Сохранить и проверить код возврата BNZ ERROR Код возврата не равен нулю: обработка ошибок ХОРОШЕЕ ОБОРУДОВАНИЕ * *... Другой программный код ОШИБКА N R15, = X'00000FFF 'Удалить код причины L R15, ERRORS (R15) Получить адрес процедуры обработки ошибок из Таблица BR R15 И выполнить процедуру обработки ошибок. * * Подпрограммы ошибок для обработки неожиданных результатов от SUBPROG * При вводе reg.0 содержит коды возврата и причины. ОШИБКИ DC AL4 (ХОРОШО) Результат в порядке DC AL4 (RETCD4) Код возврата 4: предупреждение DC AL4 (RETCD8) Код возврата 8: проблема DC AL4 (RETCD12) Код возврата 12: undefined DC AL4 (RETCD16) Код возврата 16: фатальная ошибка
* * Образец вызываемой программы (одноразовый или многоразовый) * Этот образец нельзя использовать для повторно вводимых или обновляемых программ.* ПОДПРОГ CSECT ИСПОЛЬЗУЯ ПОДПРОГ, R15 Регистр 15 содержит адрес ПОДПРОГ B START Пропустить данные DC C'SUBPROG 'Имя программы DC C '& SYSDATE' Дата DC C '& SYSTIME' Время DC C'V1R2.05 'Номер версии DS 0H Повторное выравнивание на границе полуслова * START STM R14, R12,12 (R13) Сохранение регистров DROP R15 Больше не нужен как base-reg LR R12, R15 Заправка рег.12 с базовым адресом ИСПОЛЬЗОВАНИЕ ПОДПРОГА, R12 Теперь используйте регистр 12 в качестве базы. LA R14, SAVEAREA Адрес новой зоны сохранения ST R13,4 (R14) Укажите на предыдущую зону сохранения. ST R14,8 (R13) Укажите на следующую зону сохранения. LR R13, R14 R13 снова указывает на свободную зону сохранения. * ... Другой программный код EXIT L R13,4 (R13) Получить адрес предыдущей области сохранения LM R14, R12,12 (R13) Восстановить все регистры (кроме 13) LA R15 ,... Код возврата в рег.15 BR R14 Вернуться к вызывающему DROP R12 База больше не нужна * LTORG Все литералы SAVEAREA DS 18F Область сохранения
* * Образец вызываемой программы (обновляемой или повторно вводимой) * Этот образец можно использовать также для многоразовых и одноразовых программ. * ПОДПРОГ CSECT ИСПОЛЬЗУЯ ПОДПРОГ, R15 Регистр 15 содержит адрес ПОДПРОГ B START Пропустить данные DC C'SUBPROG 'Имя программы DC C '& SYSDATE' Дата DC C '& SYSTIME' Время DC C'V1R2.05 'Номер версии DC 0H Повторное выравнивание на границе полуслова * START STM R14, R12,12 (R13) Сохранить все регистры DROP R15 Больше не нужен в качестве базы LR R12, R15 Заполните регистр 12 базовым адресом ИСПОЛЬЗОВАНИЕ ПОДПРОГА, R12 Используйте регистр 12 в качестве базы LA R1, PRIVATE_LEN Требуемый объем хранилища GETMAIN RU, LV = (R1) Выделить хранилище для области сохранения и т. Д. * Адрес выделенной памяти теперь в регистре 1 ИСПОЛЬЗОВАНИЕ ЧАСТНОГО, R13 Сделайте хранилище адресуемым ST R13,4 (R1) Укажите на предыдущую область сохранения. ST R1,8 (R13) Укажите на следующую зону сохранения. LR R13, R1 R13 снова указывает на свободную зону сохранения *... Другой программный код EXIT LR R1, R13 Сохранить адрес нашей частной зоны L R13,4 (R13) Получить адрес предыдущей области сохранения LA R2, PRIVATE_LEN FREEMAIN A = (R1), LV = (R2) Свободное выделенное хранилище LM R14, R12,12 (R13) Восстановить все регистры (кроме 13) LA R15, ... Код возврата в рег.15 BR R14 Вернуться к вызывающему DROP R12 База больше не нужна * LTORG Все литералы * * Этот dsect описывает все переменные, приватные для каждого вызывающего абонента.ЧАСТНАЯ ИНФОРМАЦИЯ SAVEAREA DS 18F * ... Другие частные переменные PRIVATE_LEN EQU * -ЧАСТНЫЙ
Условная сборка.
В следующем примере показано применение условного
сборка. Первый
показан макрос, который проверяет содержимое JCL-переменной
СИСПАРМ.
Это означает оптимизацию создаваемой программы и
включение
запускается отладочный код.
Макрос устанавливает две переменные, которые можно тестировать в
программа
для генерации кода по желанию.Некоторые примеры такой логики приведены как
хорошо.
Ниже представлены следующие четыре фрагмента кода:
- Макрос, как описано выше.
- Вызов макроса.
Этот вызов назначает глобальным переменным & DBG и & OPT их намеревался значения. - Использование этих переменных для установки других
переменные.
Здесь мы демонстрируем, как переменную & DBG можно использовать для управления в вариант печати. - Направление генерации кода с использованием
переменные.
Здесь мы демонстрируем, как опция оптимизации может быть использована в открытом код.
МАКРОС CHECKPRM . * . * Программа на ассемблере (ASMA90) принимает в качестве JCL-параметра a . * спецификация переменной SYSPARM. Значение, введенное в . * JCL будет передан в глобальный символ набора с именем & SYSPARM. . * Значение, указанное в JCL, передается как одна строка. . * Параметры отделяются друг от друга запятой - без пробелов. . * Этот макрос разбивает строку на отдельные параметры.. * Затем параметры проверяются и обрабатываются. 4 разных ключевых слова .* разрешается: . * - DEBUG: создание кода отладки (процедура Snap и т. Д.) . * - NODEBUG: не генерировать отладочный код . * - OPT: создание оптимизированной программы. . * - NOOPT: создание полнофункциональной программы. . * * * Макрос CHECKPRM проверяет JCL-переменную SYSPARM и устанавливает два глобальных * переменные для отражения содержимого SYSPARM: * & DBG включен для включения кода отладки, выключен для исключения этого кода * & OPT включен для генерации оптимизированного кода, выключен для полной * функциональный код.* GBLB и DBG, и OPT & DBG SETB 0 По умолчанию: без кода отладки & OPT SETB 1 По умолчанию: полная оптимизация AIF ('. & SYSPARM' EQ '.'). ВЫХОД * * Сначала мы разбиваем строку SYSPARM на подстроки * LCLC & P (5) Массив, содержащий подстроки (параметры) LCLA & I, & N, & X & I SETA 0 Индекс символа для & SYSPARM & N SETA 1 Следующая позиция для извлечения & X SETA 1 Счетчик параметров (массив индексов & P) * .LOOP1 ANOP & I SETA & I + 1 Увеличение индекса символа AIF (& I GT K '& SYSPARM.LOOP1X Конец строки? AIF ('& SYSPARM' (& I, 1) NE ','). LOOP1 Конец подстроки? . * Поместите подстроку в массив & P & P (& X) SETC '& SYSPARM' (& N, & I- & N) Извлечь подстроку & N SETA & I + 1 Установить ptr на начало следующей подстроки & X SETA & X + 1 Увеличение счетчика подстроки ТОМУ НАЗАД .LOOP1 Пойдите, проверьте следующий символ . * .LOOP1X ANOP Точка выхода для цикла 1 & P (& X) SETC '& SYSPARM' (& N, & I- & N) Извлечь последнюю подстроку . * . * Проверить правильность ключевых слов (теперь в массиве & P) . * & I SETA 0 Индекс в массив & P .LOOP2 ANOP & I SETA & I + 1 Указатель параметра приращения AIF (& I GT & X) .LOOP2X Готово? (& X содержит количество параметров) AIF ('. & P (& I)' EQ '.') .LOOP2 Пропустить пустой параметр AIF ('. & P (& I)' EQ '.OPT'). OPT Включить оптимизацию AIF ('. & P (& I)' EQ '.NOOPT'). NOOPT Отключить оптимизацию AIF ('. & P (& I)' EQ '.DEBUG'). DEBUG Включить логику отладки AIF ('. & P (& I)' EQ '.NODEBUG'). NODEBUG Пропустить логику отладки . * Недопустимое значение: вывести предупреждение и продолжить MПРИМЕЧАНИЕ 4, 'Недействительный операнд SYSPARM: & P (& I)' AGO .LOOP2 Перейти проверить следующий параметр .* .OPT АНОП & OPT SETB 1 MПРИМЕЧАНИЕ 0, «Оптимизированное кодирование будет сгенерировано» AGO .LOOP2 . * .NOOPT ANOP & OPT SETB 0 M ПРИМЕЧАНИЕ 0, «Будет сгенерировано отказоустойчивое кодирование» AGO .LOOP2 . * .DEBUG ANOP & DBG SETB 1 MПРИМЕЧАНИЕ 0, "Отладочный код будет включен" AGO .LOOP2 . * .NODEBUG ANOP & DBG SETB 0 M ПРИМЕЧАНИЕ 0, «Код отладки будет исключен» AGO .LOOP2 . * .LOOP2X ANOP Точка выхода для loop2 .EXIT ANOP Точка выхода для пустого SYSPARM MEND
* * Глобальные и DBG контролируют параметры сборки отладки / узла. * - Когда & DBG = 1, отладка активна * Оптимизация глобального и OPT-контроля * - Когда & OPT = 1, то оптимизация происходит * - Когда & OPT = 0, тогда включается отказоустойчивость * GBLB и DBG, и OPT CHECKPRM Проверьте & SYSPARM для установки & DBG и & OPT * SOMEPROG CSECT SOMEPROG AMODE 31 SOMEPROG RMODE ANY * ... Вот кодировка.
* Теперь установите параметры печати Опция печати GBLC & PRT Controls & PRT SETC 'NOGEN' По умолчанию nogen AIF (NOT & DBG) .NOGEN Отладка активна? & PRT SETC 'GEN' Да: создать полный листинг .NOGEN ANOP ПЕЧАТЬ И ПЕЧАТЬ Активировать опцию печати *
* * Этот фрагмент кода перемещает данные, как указано в элементе управления перемещением. * Перемещаемые данные могут иметь длину до 32767 байт.* * R6 теперь указывает на элемент управления перемещением. * R8 будет использоваться как указатель источника, R9 содержит длину. * R10 будет использоваться как указатель назначения. * ИСПОЛЬЗОВАНИЕ MOVECTL, R6 Сделайте адресуемую зону управления перемещением L R8, MCRECPTR Точка на начало записи AH R8, MCRECOFS Добавить смещение к соответствующим данным LH R9, MCDATLEN Загрузить длину данных L R10, MCDEST Точка в зону назначения * * Теперь, чтобы переместить данные, мы обычно кодируем инструкцию MVCL, * поскольку MCDATLEN может указывать любой объем данных до 32767 байт.* Поскольку известно, что в настоящее время ни один элемент MOVECTL не указывает * длина более 256, мы можем оптимизировать код с помощью MVC * вместо MVCL. * AIF (& OPT) .OPTMOVE LR R11, R9 Целевая длина всегда экв. Источник-лен MVCL R10, R8 Перемещение данных НАЗАД .MOVEDONE . * .OPTMOVE ANOP BCTR R9, R0 Уменьшить длину на 1 для MVC EX R9, MOVEDATA Выполнить MVC-инструкцию B MOVEDONE MOVEDATA MVC 0 (0, R10), 0 (R8) Переместить данные MOVEDONE EQU * * .MOVEDONE ANOP DROP R6 MOVECTL больше не нужен
Самомодифицирующийся код.
Этот пример служит только для иллюстрации. Обычно мы бы очень
сильно
рекомендую никогда не реализовывать самомодифицирующийся код, потому что он отображает
ваш
программы не могут быть повторно доступны, и потому что это делает программы очень трудными для
читать
и поддерживать.
Далее следуют два фрагмента кода:
- Процедура инициализации.
Эта процедура выполняется только один раз при изменении условия ветвления. на начало распорядка. - Печать в две колонки.
В этом примере показано очень уродливое решение для печати в две колонки. проблема, который позволяет изменить код операции инструкции. Код операции измененный с SH на AH и наоборот, в результате чего указатель столбца переключается на и сюда.
Гораздо лучшим решением было бы выделить достаточно большой буфер к разместить все строки на странице. Тогда можно было бы заполнить все левый столбец — сверху вниз — до заполнения крайнего правого столбца. Большинство конечные пользователи предпочитают такая вертикально расположенная информация.
* ... Настроить адресность и т. Д. INIT BC X'00 ', INITDONE Эта ветка является веткой-никогда OI INIT + 1, X'F0 'Сделать предыдущую ветвь ветвью всегда * ... Код инициализации находится здесь INITDONE EQU * Конец процедуры инициализации
L R1, LINEPTR Получить последний использованный указатель в LINE SETPTR SH R1, = H'50 'Перейти к другому столбцу (по умолчанию: SH) XI SETPTR, X'01 'Измените AH на SH или наоборот ST R1, LINEPTR Сохранить обновленный указатель MVC 0 (40, R1), ДАННЫЕ Переместить данные в строку печати ... Другая кодировка для печати строки ЛИНИЯ DC CL133 '' DS 0F Повторное выравнивание по границе полного слова LINEPTR DC AL4 (LINE + 67) Чтобы начать печать данных в * левый столбец, делаем вид, что последний * перемещение было в правую колонку.
Обработка реентерабельного набора данных.
Для обработки набора данных VSAM необходимы как ACB, так и RPL. В приведенном ниже примере мы показываем, как создать ACB и RPL в повторно въезжающий программа.Вы можете предположить, что все названные места хранения были выделяются динамически, и к ним можно обращаться с помощью DSECT.
* SUBROUTN STM R14, R12,12 (R13) Сохранить все регистры LA R1, SAVEAREA Адрес новой зоны сохранения ST R13,4 (R1) Укажите на предыдущую область сохранения. ST R1,8 (R13) Укажите на следующую зону сохранения. LR R13, R1 Reg.13 указывает на бесплатную зону сохранения. очередной раз * * Сначала выделяем хранилище для ACB и RPL * GETMAIN RC, LV = IFGACBLV + IFGRPLLV Запросить хранилище для ACB + RPL LTR R15, R15 Getmain был в порядке? BNE ERROR16 Ошибка обрабатывается в другом месте ST R1, ACBPTR Сохранить указатель на ACB LA R1, IFGACBLV (R1) Укажите на RPL-часть области ST R1, RPLPTR Сохранить указатель на RPL * * Выделить хранилище для рабочей области * GETMAIN RC, LV = 4096, BNDRY = PAGE Запросить хранилище для рабочей области LTR R15, R15 Getmain был в порядке? BNE ERROR16 Ошибка обрабатывается в другом месте ST R1, WORKPTR Сохранить указатель на рабочую область * * Создайте PLIST для GENCB ACB в области получения.* Для этого GENCB код возврата не предусмотрен. * SR R6, R6 Регистр стирания 6 IC R6, SHRPOOL должен содержать номер shrpool L R7, WORKPTR Укажите рабочую область для создания PLIST ИСПОЛЬЗОВАНИЕ РАБОЧЕЙ ЗОНЫ R7 GENCB BLK = ACB, создать PLIST для GENCB ACB * AM = VSAM, метод доступа * WAREA = (R7), Местоположение для сгенерированного ACB * LENGTH = IFGACBLV, максимальная длина для сгенерированного ACB * DDNAME = (*, DDNAME), GENCB ACB должен скопировать DDNAME * SHRPOOL = (S, 0 (R6)), Shrpool-nr варьируется от 0 до 15 * MACRF = (KEY, DFR, SEQ, SKP, SIS, NSR), параметры для этого ACB * BUFND = 8, минимальное количество буферов данных * BUFNI = 1, минимальное количество индексных буферов * RMODE31 = ВСЕ, буферные и управляющие блоки более 16M * MF = (L, WORKAREA, GENACBLV) Создать PLIST в WORKAREA * * Теперь создайте ACB, используя PLIST в РАБОЧЕЙ ЗОНЕ. * GENCB BLK = ACB, MF = (E, (R7)) Сгенерировать ACB с помощью PLIST в РАБОЧЕЙ ЗОНЕ LTR R15, R15 ACB сгенерирован? BNZ ERROR17 Ошибка обрабатывается в другом месте DROP R7 WORKAREA больше не требуется * * Создайте PLIST для GENCB RPL в получаемой области.* Для этого GENCB код возврата не предусмотрен. * SR R6, R6 Очистить регистр IC R6, KEYLV для указания длины ключа L R7, ACBPTR Укажите на ACB LH R8, RECDLV Укажите длину записи L R9, RPLPTR И указать местоположение для генерируемой RPL L R10, WORKPTR Переадресация рабочей области ИСПОЛЬЗОВАНИЕ РАБОЧЕЙ ЗОНЫ R10 * GENCB BLK = RPL, создать PLIST для GENCB RPL * AM = VSAM, метод доступа * WAREA = (R9), Местоположение для сгенерированного RPL * LENGTH = IFGRPLLV, максимальная длина для сгенерированного RPL * ACB = (R7), указать ACB-адрес для RPL * AREA = (S, RECDPTR), Укажите область данных для записей * AREALEN = 4, длина области данных * ARG = (S, KEYPTR) Укажите расположение ключа * KEYLEN = (S, 0 (R6)), и длина ключа в байтах * ECB = (S, ECBPTR) Укажите ECB-адрес * RECLEN = (R8), и длина записи * OPTCD = (KEY, SEQ, ASY, NUP, KGE, GEN, LOC), параметры для RPL * MF = (G; РАБОЧАЯ ЗОНА; GENRPLLV) * * Теперь создайте RPL, используя PLIST в РАБОЧЕЙ ЗОНЕ. * GENCB BLK = RPL, MF = (E, (R10)) Создание RPL с помощью PLIST в WORKAREA LTR R15, R15 RPL сформированы? BNZ ERROR18 Ошибка обрабатывается в другом месте * * Теперь, когда мы создали и ACB, и RPL, мы можем открыть набор данных. * L R2, = AL4 (VSAMOPEN) Получить адрес открытой формы списка MVC WORKAREA (VSAMOPLV), 0 (R2) Копировать в рабочую область L R2, ACBPTR Перезагрузка указателя ACB OPEN ((R2)), MF = (E, (R10)) Открыть ACB с изменяемым PLIST LTR R15, R15 Набор данных успешно открыт? BNZ ERROR19 Ошибка обрабатывается в другом месте * * Возврат из подпрограммы * L R13,4 (R13) Получить адрес предыдущей области сохранения LM R14, R12,12 (R13) Восстановить все регистры (кроме 13) BR R14 Вернуться на главную * * Форма списка по умолчанию для открытого макроса * VSAMOPEN OPEN (0), ACB-адрес еще не известен * MODE = 31, разрешить 31-битную адресацию * MF = L Создать только PLIST
Замечания? Вопросов? Больше информации? Выберите тему вашего выбор или напишите нам с вашим вопросов.
Пример вызова стандартной подпрограммы.
Пример условной сборки.
Пример самомодифицирующегося кода.
Пример обработки повторно входимого набора данных.
Этот сайт является членом WebRing. Вам предлагается просмотреть список сайтов, любящих мэйнфреймы. | Динозавры не мертвы. Они живы-здоровы и живут в данных центры все вокруг тебя.Они говорят на языках и творят странную магию с компьютеры. Остерегайтесь динозавров! И на всякий случай ждёшь финала кончина эти динозавры: помните, что динозавры правили миром на протяжении 155 миллионов годы! | |
Динозавры и прочие анахронизмы [ Присоединяйся сейчас | Кольцо-концентратор | Случайный | << Назад | Следующий >> ] |
Код сборки
— обзор
Регистры ЦП
Теперь, когда мы создали наше уязвимое тестовое приложение; мы собираемся продолжить путь немного дальше, в область анализа сборки и декомпиляции.Для этого нам понадобится некоторый опыт работы с мнемоникой ассемблера и их взаимодействия с машинным кодом в скомпилированном приложении.
Сборка, в большинстве случаев, соответствует 1 к 1 инструкциям машинного кода. Под этим мы подразумеваем, что один блок машинного кода (10110) будет напрямую транслироваться в ассемблерный код (mov). Это позволяет нам использовать такую программу, как OllyDBG или IDA (Interactive Disassembler), для дальнейшего перевода этого кода сборки на язык программирования более высокого уровня, такой как C, C ++, Objective-C и т. Д.Мы не будем рассматривать IDA в этой книге из-за стоимости коммерческого приложения (у него есть демоверсия для ограниченной оценки и бесплатная версия для Windows, которая отстает от нескольких обновлений) для читателей, но если вы хотите В будущем вы неизбежно столкнетесь с IDA (http://www.hex-rays.com/products/ida/index.shtml) в своей будущей карьере в области инженерии обратного кода.
Несмотря на то, что мы не будем использовать IDA в наших примерах, мы решили, что мы должны хотя бы показать вам, как выглядит IDA, и дать краткое объяснение того, что происходит.На рис. 8.8 IDA загрузила notepad.exe и сопоставила все функции, импорт, экспорт и структуры блокнота в различных окнах, чтобы лучше помочь нам в анализе приложения. Мы не могли даже приступить к подробному описанию тонкостей IDA, имея такое ограниченное пространство, но, безусловно, стоит изучить, если он вас заинтересует. Мы рекомендуем прочитать книгу Криса Игла The IDA Pro Book: неофициальное руководство по самому популярному в мире дизассемблеру .
Рисунок 8.8. В настоящее время в IDA загружен блокнот.Exe
На рис. 8.9 мы можем видеть почти ту же информацию, что и в IDA на рис. 8.8, с основным отличием в представлении. OllyDbg представлен в четырех основных окнах (начиная с левого верхнего угла и двигаясь по часовой стрелке), окне ЦП (обрабатывает инструкции, которые в настоящее время обрабатываются), окне регистров (контролирует регистры), шестнадцатеричном дампе (переводы ASCII) и Окно Memory Stack (для всех ваших нужд push и pop). OllyDbg загрузит приложение, а затем остановится, ожидая, пока вы его пройдете.
Рисунок 8.9. OllyDbg загрузил Notepad.Exe для анализа
Оба приложения превосходны, и мы часто используем их для разных приложений. Если нам нужно быстро оценить небольшое приложение, мы обычно можем загрузить его в Ollydbg и быстро найти то, что мы ищем, в программе. Если мы анализируем большое приложение с множеством функций и вызовов, мы, как правило, предпочитаем IDA из-за ее множества различных утилит и режимов отображения. Если вы хотите попрактиковаться в использовании OllyDbg для исправления и реверс-инжиниринга, вы можете погуглить «OllyDbg Crackme», и у вас будет много часов видео на Youtube для просмотра и сайтов для чтения (будьте осторожны, кроличья нора глубокая).В целях демонстрации мы будем использовать собственные инструменты OS X, такие как Xcode, для анализа сборки.
Мы можем разбить ассемблерный код на набор команд управления, мнемоник и операндов. Операнды — это любая часть инструкции, которой управляет мнемоника. Регистры являются одним из таких операндов. Эти регистры ЦП составляют основу большинства взаимодействий с ЦП в ассемблерном коде, который мы будем использовать.
32-битные регистры общего назначения | |||||||
---|---|---|---|---|---|---|---|
EAX | EBX | ECX | EDX | ESI | EDI | ESP | 9006|
RAX | RBX | RCX | RDX | RSI | RDI | RSP | RBP |
EAX — для результатов используются данные накопителя.
EBX — Базовый регистр используется для хранения указателя на данные.
ECX —Счетный регистр используется в циклических и строковых операциях.
EDX —Регистр данных используется как регистр ввода / вывода данных.
ESI / EDI — индексные регистры источника и назначения используются для операций с памятью и строками.
ESP — Регистр указателя стека используется для указания на верхнюю часть стека (всегда).
EBP — Регистр указателя данных стека используется для ссылки на функции и переменные стека в текущем кадре стека. EBP также известен как «указатель кадра».
В 32-битной системе длина регистра, как вы уже догадались, составляет 32 бита. Многие домашние компьютеры по-прежнему работают на 32-битной основе, хотя большинство из них переходят на более новую, более быструю архитектуру, известную как x86-64. Когда была выпущена архитектура x86-64, разработчикам потребовалось расширить регистры ЦП за пределы исходной длины регистра до, как вы снова догадались, до 64 бит.Четыре общих регистра без указателя и индекса обычно затем разбиваются на четыре части в 64-битной системе. Подразделениями являются 64-, 32-, 16- и 8-разрядные регистры общего назначения, которые определяются (как и все языки ассемблера) их архитектурой ЦП (Intel).
Доступ к различным регистрам определяется режимом, в котором вы работаете. В 32- и 16-битном режиме у вас будет доступ к 32-битным и младшим регистрам (например, EAX, AX, AH, AL). Деление выглядит примерно как на рисунке 8.10 ниже; Опять же, это для справки, чтобы у вас было базовое представление о регистрах ЦП, прежде чем мы погрузимся в нутро ассемблерного кода.
Рисунок 8.10. Общие регистры, разбитые на 32, 16 и 8-битные регистры
8-битные регистры * H и * L называются * -High и * -Low и используются для ссылки на конкретный 8-битный раздел регистр. Регистры, такие как AL (A-Low), будут ссылаться на биты с 0 по 7, а AH (A-High) будут ссылаться на биты с 8 по 15. Чтобы вам было легче запомнить, есть 8 бит в байте, а Low и High Обозначение также называется младшим и старшим байтами регистра.Еще следует отметить, что регистр начинает отсчет с 0.
Примечание
До OS X 10.6 доступным по умолчанию (а иногда и единственным) ядром было 32-битное ядро. Чтобы узнать, какое ядро может работать на вашем Apple по умолчанию, вы можете обратиться к списку компьютеров Apple Mac, использующих 64-битное ядро (http://support.apple.com/kb/HT3770).
Самый простой способ узнать, смотрите ли вы на декомпилированный 64-битный код, — это если вы видите какую-либо ссылку на какой-либо из регистров R * X. 64-битные регистры представляют собой точно такие же буквенные комбинации, за исключением того, что буква «E» была заменена на «R.Это будет выглядеть примерно так, как показано на рисунке 8.11.
Рисунок 8.11. Пример 64-битной и 32-битной сборки
Мы расширим эти инструкции по сборке немного позже, когда мы продолжим рассмотрение этой главы. На данный момент основное объяснение того, что происходит в этих трех инструкциях, заключается в том, что первая инструкция говорит, что нужно поместить ebp в стек, вторая инструкция говорит, что значение esp должно быть перемещено в регистр ebp, третья инструкция говорит о результате ebp-8 будет добавлен в eax и сохранен.Все это примеры инструкций и не предназначены для какого-либо определенного порядка.
Регистры сегментов | |||||
---|---|---|---|---|---|
CS | DS | SS | ES | FS | GS |
CS — относится к текущему программному сегменту, в котором выполняется кодовый сегмент.
DS — относится к сегменту данных, к которому обращается текущая программа.
SS — относится к сегменту стека, который использует текущая программа.
ES, FS, GS —Дополнительные сегменты, используемые для адресации указателя.
Регистры управления | ||||
---|---|---|---|---|
CR0 | CR1 | CR2 | CR3 | CR4 |
CR0 — этот регистр управления содержит .
CR1 — Зарезервировано.
CR2 — В этом регистре управления хранится значение линейного адреса ошибки страницы (PFLA).Когда происходит сбой страницы, адрес памяти, к которому программа пыталась получить доступ, сохраняется в значении PFLA.
CR3 — Этот регистр управления используется для виртуальной адресации.
CR4 — Этот регистр управления содержит больше флагов, которые также изменяют поведение ЦП.
Регистры управления в системе x86 по умолчанию имеют длину 32 бита, при выполнении кода в длинном режиме регистры управления будут иметь длину 64 бита. Мы рассмотрим некоторые флаги в регистрах управления позже, но в целях демонстрации мы коснемся только поверхности.Если вы хотите глубже погрузиться в программирование на ассемблере, вам необходимо знать, как работать с регистрами управления, хорошей первой остановкой является руководство Intel для разработчиков архитектуры 64 и IA-32 (Intel, стр. 2–17).
Регистр указателя инструкции |
---|
EIP |
Указатель инструкции (EIP) является наиболее важным регистром при работе с обратным проектированием и разработкой эксплойтов. Когда мы начнем обсуждать программирование на ассемблере, вы лучше поймете, почему это так важно, но пока постарайтесь помнить, что управление указателем имеет решающее значение для большинства форм эксплуатации, поскольку EIP указывает на текущую выполняемую инструкцию и, следовательно, если мы можем контролировать его, мы можем направить его куда захотим.% ?.& 5`j5cvxm ~ E’gm > h @ (| ‘! Խ S / y, .a9l3C? B? `+ gǁN%
Bixoft — Примеры программ на ассемблере
Bixoft — Примеры программ на ассемблереЭта страница содержит следующие примеры программ:
- Традиционные программы на ассемблере:
- Ассемблерные программы, использующие расширенную сборку Bixoft макрос:
Модуль статического клея.
Для создания миниатюрного менеджера баз данных (СУБД) мы использовали в следующие помещения:
- Разделить логику на статический модуль с минимальной функциональностью и динамическая часть, которая будет влиять на перевод между логическими а также компоновка физических записей Для каждой компоновки логической записи динамическое модуль может поддерживать несколько версий.
- Используемая версия макета логической записи будет определенный по точке входа — в статике будет 1 точка входа модуль для расположение каждой логической записи (просмотр в терминологии SQL).
- Статическая часть будет связана с каждым вызывающим загрузочным модулем, и воля определить номер версии каждого макета логической записи. Таким образом, в любое время приложение должно начать использовать более новую версию логической записи макет, с ним должна быть связана более новая версия статического модуля.
- Инвертирование этой логики означает, что всякий раз, когда физическая структура принадлежащий база данных (базовые физические наборы данных) изменяется, Приложения вообще не нужно менять. Они могут продолжить свою работу с в существующая версия статического модуля, получающая от динамического модуль логические записи с соответствующим номером версии макета.
- Статический модуль будет вызываться с одним параметром. Этот
параметр
имеет следующую планировку:
- Код функции CL2
- CL1 код возврата
- Значение ключа CL15 для произвольного доступа
- CLnnn содержимое логической записи
- Статический модуль добавляет второй параметр.Этот параметр
содержит
следующие поля:
- AL4 указатель на рабочую память динамического модуля
- Номер версии CL2 схемы логической записи
- Селекторы логической записи CL8
- Для кода функции определены следующие коды
поле:
- RS — последовательное чтение
- RR — чтение в случайном порядке (по ключу)
- WS — последовательная перезапись
- WR — reWrite Random (по ключу)
- SK — переход к указанному ключу
- SN — перейти к указанному ключу, затем прочитать следующую запись
- IR — Вставить случайную (по ключу)
- DR — Удалить случайное (по ключу)
- SI — открыт для последовательного ввода
- RI — открыт для случайного ввода
- SU — открыт для последовательного обновления
- RU — открыт для случайного обновления
- WN — перезаписать текущую запись, затем прочитать следующую
- DN — Удалить текущую запись, затем прочитать следующую
- SD — создать Snap-Dump
- Для поля кода возврата определены следующие коды:
- 0 — все ок
- 1 — запись не найдена (случайная обработка) или конец файла (последовательный обработка)
- 2 — предупреждение, проблема решена, подробности см. В журнале заданий
- 3 — ошибка программирования в приложении, подробности см. В журнале заданий
- 4 — ошибка во время обработки, см. Журнал заданий, чтобы узнать об обнаруженной ошибке.
Обработка, вероятно, не может быть продолжена. - 5 — фатальная ошибка во время обработки, информацию об ошибке см. В журнале заданий
столкнулся.
Дальнейшая обработка невозможна.
Посмотреть исходный код программы BXAIO .
Модуль динамического ввода-вывода VSAM.
Краткое описание конструкции смотрите в теме выше: модуль статического клея.
Посмотреть исходный код программы BXAIO00.
Программа-пустышка в режиме 24.
Эта программа выдает сообщение, подтверждающее, что она была запущена правильно. Программа работает в режиме 24 и не имеет полезной функции. Этот программа был написан для тестирования макроса GLUE, и его можно использовать как образец или скелетная программа.
Посмотреть исходный код программы BXALOWPG.
Обзор блоков управления.
Эта программа не имеет функции времени выполнения. Он используется для генерации обзоры полей в блоках управления и проверить отсутствие конфликтов создан в именование полей.
Управляющие блоки, которые будут сгенерированы, могут быть выбраны путем изменения значение сборки-вариабеле & SELECT.
Посмотреть исходный код программы BXAMAPS.
Проверить значение переменной JCL.
Эта программа проверяет значение JCL-переменной.
Выполняемая проверка должна быть указана в поле PARM
EXEC-заявление.
Синтаксис следующий:
- операнд 1
- оператор (EQ или NE)
- операнд 2
Программа завершается с кодом возврата 0 (проверка оценивается как истина) или 4 (отметьте false).Другие шаги в задании могут быть выполнены или пропущены в зависимости от эти коды возврата.
В следующем примере показано, как программу BXATEST можно использовать в JCL proc:
// BXAASM PROC MEMB =, PROJ =, LVL = // * // ТЕСТ EXEC PGM = BXATEST, PARM = '& LVL EQ T' // PROD EXEC PGM = BXATEST, PARM = '& LVL EQ P' // * // * Вызвать ассемблер, используя параметры по умолчанию для TEST // * // ЕСЛИ (TEST.RC = 0) ТО // ASMT EXEC PGM = ASMA90, PARM = (OBJECT, NODECK, TERM, // 'SYSPARM (SRLIST, DBG, OPT)') // SYSLIB DD DSN = SYS1.MACLIB, DISP = SHR // DD DSN = SYS1.MODGEN, DISP = SHR // DD DSN = BIXOFT.ASMPLUS & LVL..MACLIB, DISP = SHR // DD DSN = BIXOFT.ASMPLUSP.MACLIB, DISP = SHR // DD DSN = BIXOFT. & PROJ. & LVL..MACLIB, DISP = SHR // DD DSN = BIXOFT. & PROJ.P.MACLIB, DISP = SHR // ... Прочие DD-операторы // ENDIF // * // * Вызвать ассемблер, используя параметры по умолчанию для PROD // * // ЕСЛИ (PROD.RC = 0) ТО // ASMP EXEC PGM = ASMA90, PARM = (OBJECT, NODECK, TERM, // 'SYSPARM (SRLIST, NODBG, OPT)') // SYSLIB DD DSN = SYS1.MACLIB, DISP = SHR // DD DSN = SYS1.MODGEN, DISP = SHR // DD DSN = BIXOFT.ASMPLUS & LVL..MACLIB, DISP = SHR // DD DSN = BIXOFT. & PROJ. & LVL..MACLIB, DISP = SHR // ... Прочие DD-операторы // ENDIF // * // PEND
Посмотреть исходный код программы BXATEST.
Скопируйте набор данных или элемент.
Эта программа копирует член из конкатенации PDS или физический последовательное объединение наборов данных.
- Ввод:
- JCL-parm с указанием «MEMBER = memname» или «DATSET = PS»
- INPUT dd-оператор, дающий входные наборы данных
- Выход:
- OUTPUT dd-оператор, определяющий набор данных, который должен быть создан
Для MEMBER = memname конкатенация INPUT PDS будет
искал
для указанного члена, который затем будет скопирован в OUTPUT.
Для DATSET = PS объединение INPUT последовательных физических файлов.
будут
скопировать в OUTPUT.
IEBCOPY делает больше, но для его ввода требуются управляющие карты, которые
не могу
быть замененным из переменных JCL.
IEHLIST также копирует наборы данных, но также перечисляет все записи,
заполнение катушки.
В следующем примере показано, как программу BXACOPY можно использовать в JCL proc:
// BXAASM PROC MEMB =, PROJ =, LVL = // * // * Копируем исходный член для использования // * // КОПИРОВАТЬ EXEC PGM = BXACOPY, PARM = 'MEMBER = & MEMB' // ВХОД DD DSN = BIXOFT.& PROJ. & LVL..ASM, DISP = SHR // DD DSN = BIXOFT. & PROJ.P.ASM, DISP = SHR // ВЫВОД DD ПРОБЕЛ = (TRK, (10,10,1), RLSE), DISP = (NEW, PASS, DELETE), // DCB = (RECFM = FB, LRECL = 80, BLKSIZE = 27920), // DSN = && ASM (& MEMB) // * // ... другие шаги // PEND
Посмотреть исходный код программы BXACOPY.
Выгрузить библиотеку.
Эта программа выгружает всех членов PDS в единую
IEBUPDTE-задание, которое можно использовать для перезагрузки библиотеки в другом месте.
Программа принимает параметр, определяющий имя шага для
в
IEBUPDTE-задание, которое будет сгенерировано.
Преимущество использования формата IEBUPDTE заключается в том, что исходный код может также можно просматривать или редактировать в DOS, Windows и Unix.
В приведенном ниже примере показано, как можно вызвать BXAUNLD.
// BXAUNLD EXEC PGM = BXAUNLD, PARM = 'GOODIES' // SYSUT1 DD DSN = BIXOFT.GOODIES.ASM, DISP = OLD // SYSUT2 DD DSN = BIXOFT.GOODIES.UNLOAD, DISP = (NEW, CATLG, CATLG), // ПРОБЕЛ = (TRK, (10,10), RLSE), UNIT = 3390, VOL = SER = TEMP00, // DCB = (LRECL = 80, BLKSIZE = 27920, RECFM = FB)
Посмотреть исходный код программы BXAUNLD.
Замечания? Вопросов? Больше информации? Выберите тему вашего выбор или напишите нам с вашим вопросов.
Примеры традиционного ассемблера:
Примеры расширенной сборки Bixoft:
Этот сайт является членом WebRing. Вам предлагается просмотреть список сайтов, любящих мэйнфреймы. | Динозавры не мертвы. Они живы-здоровы и живут в данных центры все вокруг тебя.Они говорят на языках и творят странную магию с компьютеры. Остерегайтесь динозавров! И на всякий случай ждёшь финала кончина эти динозавры: помните, что динозавры правили миром на протяжении 155 миллионов годы! | |
Динозавры и прочие анахронизмы [ Присоединяйся сейчас | Кольцо-концентратор | Случайный | << Назад | Следующий >> ] |
Синтаксис языка ассемблера
от Valvano
Синтаксис языка ассемблера от Valvano Разработка программного обеспечения на языке ассемблера
Синтаксис
Джонатан У.Valvano
В этой статье обсуждается программирование на языке ассемблера,
прилагается к книге Embedded Microcomputer Systems: Real Time Interfacing , опубликованной Brooks-Cole 1999. В этом документе всего четыре
части
Обзор
Синтаксис (поля, псевдооперации) (этот документ)
Локальные переменные
Примеры
Синтаксис языка ассемблера
Программы, написанные на языке ассемблера, состоят из последовательности
исходных заявлений.Каждый исходный оператор состоит из последовательности
символов ASCII, оканчивающихся символом возврата каретки. Каждое исходное заявление
может включать до четырех полей: метка, операция (инструкция
мнемоническая или ассемблерная директива), операнд и комментарий. В
ниже приведены примеры директивы сборки и обычного
машинная инструкция.
PORTAequ $ 0000; Постоянная времени сборки
ИнплдааПОРТА; Чтение данных из порта данных ввода / вывода с фиксированным адресом
Оператор на языке ассемблера содержит следующие поля.
Label Field может использоваться для определения символа.
Operation Field определяет код операции или псевдооперацию.
Operand Field определяет адрес или данные.
Поле комментариев позволяет программисту документировать программное обеспечение.
Иногда не все четыре поля присутствуют в ассемблере
утверждение. Строка может содержать просто комментарий. Первый токен
в этих строках должны начинаться со звездочки (*) или точки с запятой (;). Например,
; Эта строка является комментарием
* Это тоже комментарий
* Эта строка является комментарием
Команды с адресацией в собственном режиме не имеют операнда
поле.Например,
labelclracomment
decacomment
clicomment
incacomment
Рекомендация : Для небольших программ вы включаете автоматическую сборку цветов. В
После этого редактор раскрасит каждое поле в соответствии с его типом.
Рекомендация : Для больших программ отключите автоматическую сборку цветов, потому что система будет работать слишком медленно. Вместо этого используйте ассемблер для раскрашивания исходный код.
————————————————- ————————————-
Поле метки
Поле метки появляется как первое поле исходной выписки.
Поле метки может принимать одну из следующих трех форм:
A. Звездочка (*) или точка с запятой (;) в качестве первого символа в
поле метки указывает, что остальная часть исходной инструкции
это комментарий. Комментарии игнорируются Ассемблером и печатаются
в списке источников только для информации программиста.Примеры:
* Эта строка представляет собой комментарий
; Эта строка также является комментарием
B. Пробельный символ (пробел или табуляция) в качестве первого символа.
указывает, что поле метки пусто. У линии нет метки
и это не комментарий. На этих сборочных линиях нет этикеток:
ldaa0
rmb10
C. Символ символа в качестве первого символа указывает на то, что
строка имеет метку. Символы символов в верхнем или нижнем регистре.
буквы a-z, цифры 0-9 и специальные символы, точка (.),
знак доллара ($) и подчеркивание (_). Символы состоят от одного до
15 символов, первый из которых должен быть буквенным или специальным.
символы точка (.) или подчеркивание (_). Все персонажи значительны
буквы верхнего и нижнего регистра различны.
Символ может встречаться в поле метки только один раз. Если символ встречается более одного раза в поле метки, затем каждая ссылка на этот символ будет отмечен ошибкой. Исключение из этого Правило — это псевдооперация , которая позволяет вам определять и переопределять один и тот же символ.Обычно мы используем set для определения смещения стека для локальных переменные в подпрограмме. Для получения дополнительной информации см. Примеры локальных переменных . Set позволяет двум отдельным подпрограммам повторно использовать одно и то же имя для их локальных переменных.
За исключением директив equ = andset, метке присваивается значение программного счетчика.
первого байта собираемой инструкции или данных.
Значение, присвоенное метке, является абсолютным. Этикетки могут по желанию
заканчиваться двоеточием (:).Если используется двоеточие, оно не является частью
ярлыка, но просто действует, чтобы отделить ярлык от остальных
исходной строки. Таким образом, следующие фрагменты кода эквивалентны:
здесь: deca
bnehere
heredeca
bnehere
Метка может появляться в строке сама по себе. Ассемблер интерпретирует
это как установить значение метки, равное текущему значению
счетчика программ. Метка может находиться в строке с псевдооперацией.
Таблица символов вмещает не менее 2000 символов длиной 8 символов или меньше.Допускаются дополнительные символы до 15 за счет уменьшения максимально возможного количества символов в таблице.
————————————————- ————————————-
Поле операции
Поле операции находится после метки поле и должен
предшествовать хотя бы одному символу пробела. Операция
Поле должно содержать допустимую мнемонику кода операции или директиву ассемблера.
Символы верхнего регистра в этом поле преобразуются в нижний регистр.
перед проверкой как юридическая мнемоника.Таким образом, «nop», «NOP» и
«NoP» распознаются как один и тот же мнемоник. Записи в операции
поле может быть одного из двух типов:
Код операции . Они прямо соответствуют машинным инструкциям. Код операции включает в себя любое имя регистра, связанное с инструкцией. Эти имена регистров не должны отделяться от кода операции никакими символы пробела. Таким образом, clra означает очистить аккумулятор A, но ‘clr a’ означает очищенную ячейку памяти, обозначенную меткой ‘а’.Доступные инструкции зависят от микрокомпьютера, который вы используете. используют
Директива . Это специальные коды операций, известные Ассемблеру, которые контролировать процесс сборки, а не переводить в машинные инструкции. Коды псевдоопераций, поддерживаемые этим ассемблером являются
Группа A | Группа B | Группа C | означает |
орг | орг | .org | Определенный абсолютный адрес для последующего кодирования объекта |
= | экв | Определить постоянный символ | |
комплект | Определение или переопределение постоянного символа | ||
dc.b db | fcb | . Байта | Выделить байты памяти с инициализированными значениями |
fcc | Создать строку ASCII (без символа завершения) | ||
пост.ш dw | fdb | . Слово | Выделить слово (а) памяти с инициализированными значениями |
постоянного тока дл | . Длинный | Выделить 32-битное слово (слова) памяти с инициализированными значениями | |
DS DSB | юаней | .blkb | Выделить байты памяти без инициализации |
ds.w | .blkw | Выделить байты памяти без инициализации | |
дс.л | .blkl | Выделить 32-битные слова памяти без инициализации | |
конец | конец | . Конец | Обозначает конец исходного кода ( TExaS игнорирует их) |
————————————————- ————————————-
Поле операнда
Интерпретация поля операнда зависит от содержимое
поля операции.Поле операнда, если требуется, должно следовать
поле операции и должно предшествовать хотя бы одному пробелу
персонаж. Поле операнда может содержать символ, выражение,
или сочетание символов и выражений, разделенных запятыми.
В поле операнда не может быть пробелов. Например
следующие две строки создают идентичный объектный код, потому что
пробела между данными и + в первой строке:
ldaadata + 1
ldaadata
Поле операнда машинных команд используется для указания режим адресации инструкции, а также операнд Инструкция.В следующей таблице приведены поля операнда. форматы.
Операнд | Формат | 6811/6812 пример | ||
без операнда | аккумулятор и собственный | clra | ||
<выражение> | прямой, расширенный или относительный | ldaa 4 | ||
# <выражение> | немедленная | ldaa # 4 | ||
<выражение>, | рэндовиндексируется адресным регистром | ldaa 4, х | ||
| бит установлен или сброшен | bset 4, № $ 01 | ||
| бит тест и ветка | брсет 4, # 01 $, там | ||
<выражение>, R, <выражение>, <выражение> | бит тест и ветка | брсет 4, х, # 01 $, там |
Допустимый синтаксис поля операнда зависит от микрокомпьютера. |
Каждый символ связан с 16-битным целым значением, которое используется вместо символа во время вычисления выражения.Звездочка (*), используемая в выражении как символ, представляет текущее значение счетчика местоположения (первый байт многобайтовая инструкция)
Константы представляют количество данных, которые не изменяются в значение во время выполнения программы. Константы могут быть представлены ассемблеру в одном из четырех форматов: десятичном, шестнадцатеричном, двоичный код или ASCII . Программист указывает формат числа ассемблеру со следующими префиксами:
0xhexadecimal, синтаксис C
% двоичный
‘c’ ASCII код для одной буквы c
Константы без префикса интерпретируются как десятичные.Ассемблер преобразует все константы в двоичный машинный код и отображаются в листинге сборки в шестнадцатеричном формате.
Десятичная константа состоит из строки числовых цифр. В значение десятичной константы должно находиться в диапазоне 0–65535 включительно. В следующем примере показаны как допустимые, так и недопустимые десятичные константы:
ДЕЙСТВИТЕЛЬНО | НЕДЕЙСТВИТЕЛЬНО | НЕВЕРНАЯ ПРИЧИНА |
12 | 123456 | более 5 цифр |
12345 | 12.3 | недопустимый символ |
Шестнадцатеричная константа состоит максимум из четырех символов.
из набора цифр (0-9) и заглавных букв алфавита
(A-F), и перед ним стоит знак доллара ($). Шестнадцатеричные константы
должно быть в диапазоне от $ 0000 до $ FFFF. В следующем примере показано
как действительные, так и недопустимые шестнадцатеричные константы:
ДЕЙСТВИТЕЛЬНО | НЕДЕЙСТВИТЕЛЬНО | НЕВЕРНАЯ ПРИЧИНА |
$ 12 | ABCD | без предшествующих «$» |
$ ABCD | $ G2A | недопустимый символ |
$ 001F | $ 2F018 | слишком много цифр |
Двоичная константа состоит максимум из 16 единиц или нулей, которым предшествуют
знаком процента (%).В следующем примере показаны оба действительных
и недопустимые двоичные константы:
ДЕЙСТВИТЕЛЬНО | НЕДЕЙСТВИТЕЛЬНО | НЕВЕРНАЯ ПРИЧИНА |
% 00101 | 1010101 | пропавших без вести процентов |
% 1 | % 10011000101010111 | слишком много цифр |
% 10100 | % 210101 | неверная цифра |
Один символ ASCII может использоваться как константа в выражениях. ASCII Константы заключены в одинарные кавычки (‘). Любой персонаж,
кроме одинарной кавычки, может использоваться как символьная константа.
В следующем примере показаны допустимые и недопустимые символьные константы:
ДЕЙСТВИТЕЛЬНО | НЕДЕЙСТВИТЕЛЬНО | НЕВЕРНАЯ ПРИЧИНА |
‘*’ | ДЕЙСТВИТЕЛЬНЫЙ | слишком длинный |
Для неверного случая выше ассемблер не будет указывать
ошибка.Скорее он соберет первого персонажа и проигнорирует
остаток.
————————————————- ————————————-
Поле комментария
Последнее поле исходного кода Ассемблера заявление это комментарий
поле. Это поле не является обязательным и печатается только в источнике
листинг для документации. Поле комментария отделено
из поля операнда (или из поля операции, если операнд отсутствует
требуется) хотя бы одним символом пробела.Комментарий
Поле может содержать любые печатаемые символы ASCII.
Как разработчики программного обеспечения, наша цель — создать код, который
не только решает нашу текущую проблему, но может служить основой
наших будущих проблем. Чтобы повторно использовать программное обеспечение, мы должны оставить
наш код в таком состоянии, что будущий программист (в том числе
мы сами) можем легко понять его цель, ограничения и
выполнение. Документация — это не что-то прикрепленное к программному обеспечению
после того, как это сделано, а дисциплина, встроенная в него на каждом
стадия развития.Мы тщательно разрабатываем стиль программирования
предоставление соответствующих комментариев. Я чувствую комментарий, который говорит нам почему мы выполняем определенные функции информативнее комментариев
которые говорят нам, каковы функции. Примеры плохих комментариев
будет:
clrFlagFlag = 0
seiSet I = 1
ldaa $ 1003 Прочитать PortC
Это плохие комментарии, потому что они не содержат информации
помогите нам в будущем понять, что делает программа.
Пример хороших комментариев:
clrFlagSignify ключ не был набран
sei Следующий код не будет прерван
ldaa $ 1003Bit7 = 1, если переключатель нажат
Это хорошие комментарии, потому что они облегчают изменение
программа на будущее.
Самодокументирующийся код — это программа, написанная простым и очевидным
таким образом, что его цель и функция очевидны. К
напишите такой замечательный код, сначала мы должны сформулировать проблему
Организуя его в четко определенные подзадачи. Как мы ломаемся
сложная проблема на мелкие части проходит долгий путь, делая
программное обеспечение самодокументирования. Оба понятия абстракции (представленные
в последнем разделе) и модульный код (будет представлен в
следующий раздел) обращается к этому важному вопросу организации программного обеспечения.
Сопровождение ПО — это процесс исправления ошибок, добавления
новые функции, оптимизация по скорости или объему памяти, перенос на
новое компьютерное оборудование и настройку программного обеспечения для
новые ситуации. Это НАИБОЛЕЕ ВАЖНЫЙ этап разработки программного обеспечения.
Мое личное мнение таково, что блок-схемы или руководства по программному обеспечению
не являются хорошими механизмами для документирования программ, потому что это
трудно поддерживать эти типы документации в актуальном состоянии, когда
внесены изменения.
Мы должны использовать осторожные отступы и описательные имена для
переменные, функции, метки, порты ввода / вывода.Либеральное использование equ provide
объяснение функции программного обеспечения без затрат на скорость выполнения
или требования к памяти. Дисциплинированный подход к программированию
заключается в разработке шаблонов письма, которым вы постоянно следуете.
Разработчики программного обеспечения не похожи на писателей рассказов. Это нормально
используйте одну и ту же схему подпрограммы снова и снова. В следующей программе обратите внимание на следующее
вопросы стиля:
1) Начинается и заканчивается строкой из *
2) Указывает цель подпрограммы
3) Предоставляет параметры ввода / вывода, что они означают и
как они передаются
4) Различные фазы (подмодули) кода, обозначенные
строка
******************* Макс ***************************** **
* Цель: возвращает максимум два 16-битных числа
* Эта подпрограмма создает три 16-битных локальных переменных
* Входные данные: Num1 и Num2 — два 16-битных беззнаковых числа
*, переданных в стек
* Выход: RegX — это максимум X, Y
* Уничтожено: CCR
* Последовательность вызовов
* ldx # 100
* pshxNum1 помещается в стек
* ldx # 200
* pshx Num2 помещается в стек
* jsrMax
* pulyBalance стек
* pulyResult
Firstset0 Первая 16-битная локальная переменная
Secondset2 Вторая 16-битная локальная переменная
Resultset4 Максимум первой, второй
Num1set12 Входной параметр1
Num2set10 Входной параметр2
регистров MaxpshySave, которые будут изменены
* — — — — — — — — — — — — — — — — — — — — — — — — — — —
pshxAllocate Локальная переменная результата
pshxAllocate Вторая локальная переменная
pshxAllocate Первая локальная переменная
* — — — — — — — — — — — — — — — — — — — — — — — — — — —
tsxCreate указатель фрейма стека
ldyNum1, X
styFirst, XInitialize First = Num1
ldyNum2, X
stySecond, XInitialize Second = Num2
ldyFirst, X
styResult Result, X
styResult, что результат = Первый
cpySecond, X
bhsMaxOKSkip if First> = Second
ldySecond, XSince First
MaxOKldxResult, XReturn Result в RegX
* — — — — — — — — — — — — — — — — — — — — — — — — — — —
puly Разместите локальные переменные
puly
puly
* — — — — — — — — — — — — — — — — — — — — — — — — — — —
pulyRestore регистры
rts
****************** Конец макс. **************************** *
————————————————- ————————————-
Листинг ассемблера
Выходные данные ассемблера включают необязательный листинг принадлежащий
исходная программа и объектные файлы.Файл списка создается, когда открыт файл TheList.RTF .
Каждая строка списка содержит номер ссылочной строки,
адрес и байты собраны, и исходный исходный ввод
линия. Если строка ввода вызывает вывод более 8 байтов (например,
длинная директива FCC), дополнительные байты включены в
объектный код (файл S19 или загружен в память), но не показан в
листинг. Есть три варианта сборки, каждый из которых можно переключать.
включение / выключение с помощью команды Сборка-> Параметры.
(4) | циклов | показывает количество циклов для выполнения этой инструкции |
[100] | всего | дает общее количество рабочих циклов с момента последней псевдооперации организации |
{PPP} | тип | дает тип цикла |
Коды, используемые в типе цикла, различны для каждого микрокомпьютера.
Список сборки может дополнительно содержать таблицу символов.Таблица символов находится в конце списка сборок.
если включено. Таблица символов содержит название каждого символа,
вместе с его определенным значением. Поскольку установленный псевдооператор может использоваться
для переопределения символа значение в таблице символов является последним
определение.
————————————————- ————————————-
Ошибки сборки
Ошибки программирования делятся на две категории. Простой набор текста / синтаксис ошибка будет помечена ассемблером TExaS как ошибка , когда ассемблер пытается перевести исходный код в машину код.Ошибки программирования, которые сложнее найти и удалить это функциональные ошибки, которые могут быть обнаружены во время выполнения, когда программа не работает должным образом. Имеются в виду сообщения об ошибках чтобы быть понятным. Ассемблер имеет подробный режим (см. Команду Assembler-> Options), который предоставляет более подробную информацию. об ошибке и предлагает возможные решения.
Типы ошибок ассемблера
1) Неопределенный символ: Программа ссылается на метку, которая не существует
Как исправить: проверьте орфографию определения и доступа
2) Неопределенный код операции или псевдооперация
Как исправить: проверьте орфографию / наличие инструкции
3) Режим адресации недоступен
Как исправить: найдите режимы адресации, доступные для
инструкция
4) Ошибка выражения
Как исправить: проверьте скобки, начните с более простого выражения
5) Ошибка фазирования возникает, когда значение символа изменяется с pass1 на pass2
Как исправить: сначала удалите все неопределенные символы, затем удалите
пересылка ссылок
6) Ошибка адреса
Как исправить: используйте псевдооперации org для сопоставления доступной памяти.
Диагностические сообщения об ошибках помещаются в файл листинга просто
после строки, содержащей ошибку. Если файл TheList.RTF отсутствует, то ошибки сборки сообщаются в файле TheLog.RTF . Если файлов TheList.RTF или TheLog.RTF нет, то ошибки сборки не выводятся.
————————————————- ————————————-
Ошибки фазирования
Ошибка фазировки во время прохода 2 ассемблера, когда
адрес метки отличается от того, когда он был ранее
рассчитано.Цель первого этапа ассемблера — создать
таблица символов. Чтобы вычислить адрес каждой сборки
строки, ассемблер должен уметь определить точное число
байтов займет каждая строка. Для большинства инструкций номер
требуемого байта фиксировано и легко вычисляется, но для других
инструкции, количество байтов может варьироваться. Возникают ошибки фазирования
когда ассемблер вычисляет размер другой инструкции
в проходе 2, чем ранее рассчитывалось на проходе 2.Иногда фазировка
ошибка часто возникает в строке программы ниже, чем
где возникает ошибка. Ошибка фазирования обычно возникает из-за
использование прямых ссылок. В этом примере 6812 символ
«index» недоступен во время сборки ldaa index, x. Ассемблер неправильно выбирает 2-х байтовую адресацию IDX.
версия режима, а не правильный 3-байтовый режим IDX1.
ldaaindex, x
indexequ 100
; …
loopldaa # 0
В листинге показана ошибка фазирования
Copyright 1999-2000 Test EXecute And Simulate
$ 0000A6E064ldaaindex, x
$ 0064indexequ100
;…
$ 00038600loopldaa # 0
#####
Ошибка фазирования
Эта строка находилась по адресу $ 0002 на проходе 1, теперь на проходе 2 это
$ 0003
*************** Таблица символов ********************
индекс $ 0064
цикл $ 0002
##### Сборка не удалась, 1 ошибка!
Когда ассемблер переходит в цикл, значения Pass 1 и Pass 2 отключаются из-за ошибки фазирования в инструкции ldaa # 0 цикла. Решение здесь — сначала поставить индекс, равный 100.
————————————————- ————————————-
Ассемблер псевдооператора ‘ s
Псевдооперация — это специальные команды для ассемблера, которые интерпретируются в процессе сборки. Некоторые из них создают объектный код, но большинство этого не делают. Есть два распространенных формата псевдоопераций используется при разработке языка ассемблера Motorola. Ассемблер TExaS поддерживает обе категории. Если вы планируете экспортировать ПО разработано с помощью TExaS для другого приложения, тогда вам следует ограничить использование только psuedo-op совместим с этим приложением.
Group A поддерживается Motorola MCUez, HiWare и ImageCraft.
ICC11 и ICC12
Group B поддерживается Motorola DOS уровня AS05, AS08, AS11
и AS12
Group C — некоторые альтернативные определения
Группа A | Группа B | Группа C | означает |
орг | орг | .org | Определенный абсолютный адрес для последующего кодирования объекта |
= | экв | Определить постоянный символ | |
комплект | Определение или переопределение постоянного символа | ||
пост.б дб | fcb | . Байта | Выделить байты памяти с инициализированными значениями |
fcc | Создать строку ASCII (без символа завершения) | ||
dc.w dw | fdb | . Слово | Выделить слово (а) памяти с инициализированными значениями |
постоянного тока дл | . Длинный | Выделить 32-битное слово (слова) памяти с инициализированными значениями | |
дс дс.б | юаней | .blkb | Выделить байты памяти без инициализации |
ds.w | .blkw | Выделить байты памяти без инициализации | |
ds.l | .blkl | Выделить 32-битные слова памяти без инициализации | |
конец | конец | . Конец | Обозначает конец исходного кода ( TExaS игнорирует их) |
————————————————- ————————————-
приравнивает символ к значению
<метка> equ <выражение> (<комментарий>)
<метка> = <выражение> (<комментарий>)
Директива EQU (или =) присваивает значение выражения в
поле операнда к метке.Директива equ присваивает значение
кроме программного счетчика на этикетке. Этикетка не может
быть переопределенным где-нибудь еще в программе. Выражение не может
содержать любые прямые ссылки или неопределенные символы. Приравнивается к
прямые ссылки помечаются как Ошибки фазирования phasing_error.
В следующем примере имена локальных переменных не могут быть
повторно используется в другой подпрограмме:
; MC68HC812A4
; ***** фаза привязки ***************
Iequ-4
PTequ-3
Ansequ-1
; ******* Фаза распределения *********
functionpshxsave old Reg X
tsxcreate указатель кадра стека
leas-4, spallocate четыре байта для I, PT, Result
; ******** Фаза доступа ************
clrI, xClear I
ldyPT, xReg Y — это копия станции PT
, xstore в Ans
; ******** Фаза освобождения *****
txsdeallocation
pulxrestore old X
rts
В следующем примере псевдооперация equ используется для определения
порты ввода-вывода и для доступа к различным элементам связанных
состав.
* *********** Moore.RTF *********************
* Джонатан В. Вальвано 18.07.98 10: 54:28 PM
* Контроллер конечного автомата Мура
* PC1, PC0 — двоичные входы, PB1, PB0 — двоичные выходы
PORTBequ0x01
DDRBequ0x03
PORTCequ0x04
DDRCequ0x06
TCNTequ0x84; 16-битные тактовые импульсы без знака, увеличивающиеся каждый цикл
TSCRequ0x86; установите бит 7 = 1 для включения TCNT
* Контроллер конечного автомата
* C1, C0 — это входы B1, B0 — выходы
org $ 800 переменные идут в RAM
StatePtrmb2Pointer в текущее состояние
org $ F000 Поместить в EEPROM, чтобы его можно было изменить
Outequ0offset для выходного значения
* 2-битный шаблон, хранящийся в младшей части 8-битного байта
Waitequ1offset для времени ожидания
Nextequ2offset для 4 следующих состояний
* Четыре 16-битных абсолютных адреса без знака
InitStatefdbS1Initial state
S1fcbp% 01Outbput
fdbS2, S1, S2, S3
S2fcb% 10 Выход
fcb10 Время ожидания
fdbS3, S1, S2, S3
S3fcb% 11 Выход
fcb20 Время ожидания
$ fdbS1, S1, S2, Go в S1 9000 $ 9000 программ C00
movb # $ FF, TSCR enable TCNT
ldaa #% 11111111
staaDDRB B1, B0 — светодиодные выходы
ldaa #% 00000000
staaDDRC C1, C0 — входы переключателя
ldxInitState Указатель состояния
stxStatePt
stxStatePt
:
stxStatePt * 1.Выполнить вывод для текущего состояния
* 2. Подождать заданное время
* 3. Вход от переключателей
* 4. Перейти к следующему состоянию в зависимости от входа
* StatePt — указатель текущего состояния
FSMldxStatePt1. Вывести
ldabOut, xOutput значение для этого состояния в битах 1,0
stabPORTB
ldaaWait, x2. Ждать в этом состоянии
bsrWAIT
ldabPORTC3. Чтение ввода
andb # $ 03 просто интересует бит 1,0
lslb 2 байта на 16-битный адрес
abx добавить 0,2,4,6 в зависимости от ввода
ldxNext, x4.Следующее состояние в зависимости от входа
stxStatePt
braFSM
* Reg A — время ожидания (по 256 циклов)
WAITtfra, b
clraRegD = количество циклов ожидания
adddTCNTTCNT значение в конце задержки
WloopcpdTCNTEndT-TCNT когда EndT
rts
org $ FFFE
fdbMainreset vector
————————————————- ————————————-
установить символ приравнивания к значению
<метка> установить <выражение> (<комментарий>)
Директива SET присваивает значение выражения в операнде поле к метке.Директива set присваивает значение, отличное от счетчик программы на этикетке. В отличие от псевдооперации equ, метку можно переопределить где угодно в программе. Выражение не должен содержать прямых ссылок или неопределенных символов. Использование этой псевдооперации с прямыми ссылками не допускается. отмечен ошибками фазирования.
В следующем примере имена локальных переменных можно использовать повторно.
в другой подпрограмме:
; MC68HC812A4
; ***** фаза привязки ***************
Исеть-4
ПЦсет-3
Анссет-1
; ******* Фаза распределения *********
functionpshxsave old Reg X
tsxcreate указатель кадра стека
leas-4, spallocate четыре байта для I, PT, Result
; ******** Фаза доступа ************
clrI, xClear I
ldyPT, xReg Y — это копия станции PT
, xstore в Ans
; ******** Фаза освобождения *****
txsdeallocation
pulxrestore old X
rts
———————————————— —————————————
fcb Форма константного байта
(<метка>) fcb
(
Директива FCB может иметь один или несколько операндов, разделенных запятыми.
Значение каждого операнда усекается до восьми бит и сохраняется.
в одном байте объектной программы. Несколько операндов
хранятся в последовательных байтах.Операнд может быть числовой константой,
символьная константа, символ или выражение. Если несколько
присутствуют операнды, один или несколько из них могут быть нулевыми (два соседних
запятые), и в этом случае будет присвоен один нулевой байт
для этого операнда. Ошибка возникнет, если старшие восемь бит
из значений оцененных операндов не все единицы или все нули.
Может быть включена строка, которая хранится как последовательность
Символы ASCII. Разделители, поддерживаемые TExaS , — это «‘и \.Строка не заканчивается, поэтому программист
должен явно прекратить его. Например:
str1 fcb «Hello World», 0
В следующем конечном автомате определения fcb следующие:
используется для хранения выходных данных и времени ожидания.
Outequ0offset для выходного значения
* 2-битный шаблон, хранящийся в младшей части 8-битного байта
Waitequ1offset для времени ожидания
Nextequ2offset для 4 следующих состояний
* Четыре 16-битных абсолютных адреса без знака
InitStatefdbS1Initial state
S1fcbp% 01Outbput
fdbS2, S1, S2, S3
S2fcb% 10 Выход
fcb10 Время ожидания
fdbS3, S1, S2, S3
S3fcb% 11 Выход
fcb20 Время ожидания
fdbS1, S1, S2, S1
————————————————- ————————————-
fcc Форма Константа Символьная Строка
(<метка>) FCC <разделитель> <строка> <разделитель> (<комментарий>)
Директива FCC используется для хранения строк ASCII в последовательных байтах памяти.Начинается байтовое хранилище на текущем программном счетчике. Метка присваивается первому байт в строке. В строке может содержаться любой из печатаемых символов ASCII . Строка указана между двумя одинаковыми разделителями. Первый непустой символ после директивы FCC используется в качестве разделителя. Разделители Поддерживаются TExaS : «‘и \.
Примеры:
LABEL1FCC’ABC ‘
LABEL2fcc «Джон Вальвано»
LABEL4fcc / Добро пожаловать в FunCity! /
Первая строка создает символов ASCII ABC в ячейке LABEL1.Будьте осторожны и не размещайте код FCC в стороне от исполняемых инструкций. Сборщик произведет
объектный код, как и для обычных инструкций, одна строка в
время. Например, следующее приведет к сбою, потому что после выполнения
инструкции LDX, 6811 будет пытаться выполнить ASCII символов «Проблема» в качестве инструкций.
ldaa100
ldx # Strg
Strgfcc «Trouble»
Обычно мы собираем все fcc, fcb, fdb вместе и помещаем их в конец нашей программы, чтобы
микрокомпьютер не пытается выполнить постоянные данные.Например,
ldaaCon8
ldyCon16
ldx # Strg
braloop
* Поскольку петля бюстгальтера безусловна,
* 6811 не выйдет за эту точку.
Strgfcc «Нет проблем»
Con8fcb100
Con16fdb1000
———————————————— —————————————
fdb Form Double Byte
(<метка>) fdb
(
(
(
Директива FDB может иметь один или несколько операндов, разделенных запятыми. 16-битное значение, соответствующее каждому операнду, сохраняется в два последовательных байта объектной программы. Хранение начинается на текущем программном счетчике. Метка присваивается первому 16-битное значение.Несколько операндов хранятся в последовательных байтах. Операнд может быть числовой константой, символьной константой, символ или выражение. Если присутствует несколько операндов, один или несколько из них могут быть нулевыми (две соседние запятые), и в этом случае для этого операнда будут назначены два байта нулей.
В следующем конечном автомате определения fdb используются для определения указателей состояния. Например, InitState и четыре указателя Next.
Outequ0offset для выходного значения
* 2-битный шаблон, хранящийся в младшей части 8-битного байта
Waitequ1offset для времени ожидания
Nextequ2offset для 4 следующих состояний
* Четыре 16-битных абсолютных адреса без знака
InitStatefdbS1Initial state
S1fcbp% 01Outbput
fdbS2, S1, S2, S3
S2fcb% 10 Выход
fcb10 Время ожидания
fdbS3, S1, S2, S3
S3fcb% 11 Выход
fcb20 Время ожидания
fdbS1, S1, S2, S1
————————————————- ————————————-
пост.l Определить 32-битную константу
(<метка>) dc.l
(
(
Директива dl может иметь один или несколько операндов, разделенных запятыми. 32-битное значение, соответствующее каждому операнду, сохраняется в четыре последовательных байта объектной программы (с прямым порядком байтов).В сохранение начинается с текущего программного счетчика. Метка присвоена к первому 32-битному значению. Несколько операндов хранятся в последовательном байтов. Операнд может быть числовой константой, символьной константой, символ или выражение. Если присутствует несколько операндов, один или несколько из них могут быть нулевыми (две соседние запятые), в которых case четыре байта нулей будут присвоены этому операнду.
В следующем конечном автомате определения dl используются для определения 32-битных констант.
S1dl100000, $ 12345678
S2.long1,10,100,1000,10000,100000,1000000,10000000
S3dc.l-1,0,1
———————————————— —————————————
org Установить счетчик программы на исходную точку
org <выражение> (<комментарий>)
.org <выражение> (<комментарий>)
Директива ORG изменяет счетчик программы на указанное значение. выражением в поле операнда. Последующие заявления собираются в ячейки памяти, начиная с новой программы значение счетчика.Если в источнике не встречается директива ORG программы, счетчик программы обнуляется. Выражения не может содержать прямых ссылок или неопределенных символов.
Операторы org в следующем скелете помещают переменные в ОЗУ.
и программы в EEPROM MC68HC812A4
* ********** <<Имя>> ********************
org $ 800 переменные идут в ОЗУ
* << глобальные объекты, определенные с помощью rmb, идут сюда >>
org $ F000программы в EEPROM
Основное: lds # $ 0C00 инициализирует стек в ОЗУ
* << сюда идут однократные инициализации >>
цикл:
* << повторяющиеся операции перейдите сюда >>
braloop
* << подпрограммы перейдите сюда >>
org $ FFFE
fdbMainreset vector
————————————————- ————————————-
юаней Резервное несколько байтов
(<метка>) rmb <выражение> (<комментарий>)
(<метка>) ds <выражение> (<комментарий>)
(<метка>) ds.b <выражение> (<комментарий>)
(<метка>) .blkb <выражение> (<комментарий>)
Директива RMB приводит к увеличению счетчика местоположения на значение выражения в поле операнда. Эта директива резервирует блок памяти, длина которого в байтах равна к значению выражения. Зарезервированный блок памяти не инициализирован каким-либо заданным значением. Выражение не может содержать любые прямые ссылки или неопределенные символы. Эта директива обычно используется для резервирования блокнота или области стола на будущее использовать.
————————————————- ————————————-
ds.w Зарезервировать несколько слов
(<метка>) ds.w <выражение> (<комментарий>)
(<метка>) .blkw <выражение> (<комментарий>)
Директива ds.w приводит к увеличению счетчика местоположения. в 2 раза больше значения выражения в поле операнда. Этот директива резервирует блок памяти, длина которого в словах (16 бит) равно значению выражения.Блок зарезервированная память не инициализируется никаким заданным значением. Выражение не может содержать никаких прямых ссылок или неопределенных символов. Этот директива обычно используется для резервирования области блокнота или таблицы для дальнейшего использования.
————————————————- ————————————-
ds.l Зарезервировать несколько 32-битных слов
(<метка>) ds.l <выражение> (<комментарий>)
(<метка>) .blkl <выражение> (<комментарий>)
DS.Директива l заставляет счетчик местоположения быть продвинутым в 4 раза больше значения выражения в поле операнда. Этот директива резервирует блок памяти, длина которого в словах (32 бита) равно значению выражения. Блок зарезервированная память не инициализируется никаким заданным значением. Выражение не может содержать никаких прямых ссылок или неопределенных символов. Этот директива обычно используется для резервирования области блокнота или таблицы для дальнейшего использования.
———————————————— —————————————
конец Конец программы (необязательно)
конец (<комментарий>)
.конец (<комментарий>)
Директива END означает конец исходного кода. Ассемблер TExaS игнорирует эти коды псевдоопераций.
————————————————- ————————————-
Коды символов ASCII
БИТЫ от 4 до 6
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ||
0 | NUL | DLE | СП | 0 | @ | -п | ` | п. | |
Б | 1 | SOH | DC1 | : | 1 | А | Q | а | кв. |
я | 2 | STX | DC2 | ! | 2 | Б | R | б | р |
т | 3 | ETX | DC3 | # | 3 | С | S | с | с |
ю | 4 | EOT | DC4 | $ | 4 | D | т | д | т |
5 | ENQ | НАК | % | 5 | E | U | e | u | |
0 | 6 | ACK | SYN | и | 6 | Ф | В | ф | v |
7 | BEL | ETB | ‘ | 7 | G | Вт | г | Вт | |
т | 8 | BS | МОЖНО | ( | 8 | H | Х | ч | х |
O | 9 | HT | EM | ) | 9 | я | Я | и | л |
А | LF | ПОД | * | : | Дж | Z | j | z | |
3 | Б | VT | ESC | + | ; | К | [ | к | { |
С | FF | ФС | , | < | л | \ | л | ; | |
D | CR | GS | – | = | М | ] | м | } | |
E | SO | RS | . | п | ~ | ||||
Ф | S1 | США | / | ? | O | _ | или | DEL |
————————————————- ————————————-
S-19 Код объекта
S-запись выходной формат кодирует программу и объект данных
модули в формат для печати (ASCII).Это позволяет просматривать объектный файл со стандартным
инструменты и позволяет отображать модуль при переходе из
от одного компьютера к другому или во время нагрузок между хостом и целью.
Формат S-записи также включает информацию для использования в случае ошибки.
проверка для обеспечения целостности передачи данных.
S-записи — это символьные строки, состоящие из нескольких полей, которые
определить тип записи, длину записи, адрес памяти, код / данные,
и контрольная сумма. Каждый байт двоичных данных кодируется как 2-символьный
шестнадцатеричное число: первый символ, представляющий старший
4 бита, а второй — 4 младших бита байта.
5 полей, которые составляют S-запись:
1) Тип S0, S1 или S9
2) Длина записи
3) Адрес
4) Код / данные
5) Контрольная сумма
Было определено восемь типов S-записей для различных требуется кодирование, транспортировка и декодирование, но в большинстве микроконтроллеров Motorola используются только три типа . Запись S0 — это запись заголовка, содержащая имя файла в формате ASCII в поле «Код / данные». Адресное поле этот тип обычно 0000.Запись S1 — это запись данных, содержащая информацию, которая должна быть загружена последовательно. начиная с указанного адреса. Запись S9 является маркером конца файла и иногда содержит начальную адрес для начала исполнения. Во встроенной микрокомпьютерной среде, начальный адрес должен быть запрограммирован в соответствующем месте. Для большинства микроконтроллеров Motorola вектор сброса является последним. два байта ПЗУ или EEPROM.
Длина записи содержит количество пар символов в записи длины, без учета типа и длины записи.
Для типов записей S0, S1, S9 поле адреса представляет собой 4-байтовое значение. Для типа записи S1 адрес указывает где поле данных должно быть загружено в память.
В поле Code / Data содержится от 0 до n байтов. Эта информация содержит исполняемый код, загружаемую память данные или описательная информация.
Поле контрольной суммы состоит из 2 символов ASCII, используемых для проверки ошибок. В мере
значащий байт дополнения суммы значений до единицы
представлен парами символов, составляющими длину записи,
адрес и поля кода / данных.При генерации контрольной суммы
один добавляет (назовите результат сумму ) длину записи, адрес и поле кода / данных, используя 8-битный модуль
арифметика (без учета переполнений). Контрольная сумма вычисляется
контрольная сумма = $ FF — сумма
При проверке контрольной суммы добавляется (назовем результат сумма ) длина записи, адресный код / поле данных и контрольная сумма, используя
8-битная арифметика по модулю (без учета переполнения). Сумма должна быть $ FF.
Каждая запись может заканчиваться CR / LF / NULL.
Ниже приведен типичный модуль S-записи:
S1130000285F245F2212226A0004242237C2A
S1130010000200080008262
S113002041E4E42234300182342000824A952
S107003000144ED
0
FC
Модуль состоит из четырех записей кода / данных и завершения S9. записывать.
Первый код / запись данных S1 объясняется следующим образом:
S1S-запись типа S1, указывающая, что код / запись данных должна быть загружен / проверен по 2-байтовому адресу.
13 Hex 13 (19 в десятичной системе), обозначающее 19 пар символов, представляющих Далее следуют 19 байт двоичных данных.
00 Четырехсимвольное 2-байтовое поле адреса: шестнадцатеричный адрес 0000, указывает место, куда должны быть загружены следующие данные.
Следующие 16 пар символов представляют собой байты ASCII фактического программный код / данные
2A Контрольная сумма первой записи S1.
Вторая и третья записи кода / данных S1 также содержат 13 долларов США. пары символов и заканчиваются контрольными суммами.Четвертый код / данные S1 запись содержит 7 пар символов.
Запись о завершении S9 объясняется следующим образом:
S9S-запись типа S9, указывающая на завершение записи.
03Hex 03, указывающий на три пары символов (3 байта) для следить.
00 Четырехсимвольное 2-байтовое поле адреса, нули 00
FCC Контрольная сумма записи S9.
Этот документ состоит из четырех общих частей
Обзор
Синтаксис (поля, псевдооперации) (этот документ)
Локальные переменные
Примеры
IBM Assembler — Учебное пособие, ссылки, примеры, руководства -IBM Mainframes
Я видел много запросов на «IBM Assembler — Учебное пособие, справочные материалы, примеры, руководства, эмуляторы, утилиты, книги, часто задаваемые вопросы» и т. Д.Ниже я собрал некоторую относящуюся к делу информацию. Не стесняйтесь добавлять полезные URL-адреса / информацию. в пользу нашей базы знаний форумов ASSEMBLER. Некоторые из этих ссылок содержат отличные примеры. Если вы серьезно подумываете об обучении на примерах, просмотрите файлы ленты CBT и извлеките уроки из работы других — зачем изобретать велосипед. Также см. Другие ссылки, такие как SimoTime. Пожалуйста, не торопитесь и терпеливо просматривайте эти URL / ссылки. Изучение ассемблера — чаще всего — разочаровывающее и пугающее занятие для новичков.Кривая обучения не похожа на другие языки программирования.Ссылки в Интернете:
Наши местные ссылки:
Раздел загрузок — Эмуляторы, Симуляторы
— ibmmainframes.com/downloads.php
‘Пожалуйста, примите во внимание … это срочно … Мистер Макмиллан и мистер Сом’
— ibmmainframes.com/viewtopic.php?t=2190
Компакт-диски Mainframe — прочная платформа
— www.mainframesindia.com
Воспользуйтесь функцией ПОИСКА на этом форуме по определенному ключевому слову.
— ibmmainframes.com / search.php
Другие ссылки:
Кодирование на ассемблере
— подсказки, подсказки, руководства, FAQ и т. Д.
— Используйте BBCode [URL] для внешних ссылок
SimoTime: Assembler Connection, COBOL Connection, VSAM … Этот сайт содержит обзор инструкций с советами, методами и задокументированными примерами программирования.
— Подключение ассемблера (нажмите, чтобы узнать больше на отображаемых страницах)
—— Используйте BBCode [URL] для внешних ссылок
— 370 примеров набора команд от SimoTime Enterprises
—— Используйте BBCode [URL] для внешних ссылок
— Разделительные инструкции — Расширенные мнемонические коды операций
—— Используйте BBCode [URL] для внешних ссылок
— 370 Обзор инструкций от SimoTime Enterprises
—— Используйте BBCode [URL] для внешних ссылок
— Таблица перевода ASCII или EBCDIC от SimoTime Enterprises
—— h Использовать BBCode [URL] для внешних ссылок
Дон Хиггинс — Гуру эмуляторов — разработчик Micro Focus и т. Д.
— Временная шкала событий эмуляции ассемблера мэйнфрейма IBM PC-370
——
Неофициальная веб-страница Дейва по HLASM
— Используйте BBCode [URL] для внешних ссылок
Используйте [URL] BBCode для внешних ссылок — отличный ресурс для системного программиста / разработчика для IBM Software & Utilities (общественное достояние)
Загрузите каталог File001, чтобы увидеть список файлов на бесплатной ленте CBT (или компакт-диске)
— Использовать BBCode [URL] для внешних ссылок
— Использовать BBCode [URL] для внешних ссылок (переполнение ленты)
— Файл № 069 Примеры кодирования из книги ASM Кармина Каннателло
—— Используйте BBCode [URL] для внешних ссылок
— Файл № 505 Ассемблер ASSIST — перемещен в CBT Overflow — Файл 085
— Файл # 085 ASSIST Assembler — используется для обучения BAL Assembler (переполнение ленты)
—— Используйте BBCode [URL] для внешних ссылок
— Зеркало ленты CBT для XmitManager (для просмотра CBT.XMI файлы)
—— Используйте BBCode [URL] для внешних ссылок
Книги:
«Программирование на языке ассемблера для IBM 370: Assist Edition»
(серия Бенджамина / Каммингса по структурному программированию)
от Фрэнка М. Каррано
«Язык ассемблера IBM 370 с вспомогательными, структурированными концепциями и расширенными темами»
(использует эмулятор DOS PC-370)
Чарльз Дж. Качмар
‘Ассемблерный язык с ПОМОЩЬЮ’
, Росс Овербек
«Расширенный язык ассемблера и интерфейсы MVS»
(для IBM Systems и прикладных программистов)
Кармине А.Cannatello
«Программирование на языке ассемблера для компьютеров, совместимых с IBM и IBM»
(ранее 370/360, программирование на языке ассемблера)
Нэнси Стерн, Олден Сагер, Роберт А. Стерн
‘Язык ассемблера MVS’
Кевин Маккуиллен, Энн Принс
«Программирование на языке ассемблера: семейство IBM System / 370»
от Джорджа Страбла
============================================
-Пелад
Главное не переставать расспрашивать — Альберт Эйнштейн
.