Assembler
- Повлиял на:
- Принятые расширения файлов:
- .asm
- Реализации и версии (свернуть все | развернуть все):
Assembler — язык программирования низкого уровня, представляющий собой формат записи машинных команд, удобный для восприятия человеком.
Команды языка ассемблера один в один соответствуют командам процессора и, фактически, представляют собой удобную символьную форму записи (мнемокод) команд и их аргументов. Также язык ассемблера обеспечивает базовые программные абстракции: связывание частей программы и данных через метки с символьными именами и директивы.
Директивы ассемблера позволяют включать в программу блоки данных (описанные явно или считанные из файла); повторить определённый фрагмент указанное число раз; компилировать фрагмент по условию; задавать адрес исполнения фрагмента, менять значения меток в процессе компиляции; использовать макроопределения с параметрами и др.
Каждая модель процессора, в принципе, имеет свой набор команд и соответствующий ему язык (или диалект) ассемблера.
Достоинства и недостатки
- минимальное количество избыточного кода (использование меньшего количества команд и обращений в память). Как следствие — большая скорость и меньший размер программы
- большие объемы кода, большое число дополнительных мелких задач
- плохая читабельность кода, трудность поддержки (отладка, добавление возможностей)
- трудность реализации парадигм программирования и любых других сколько-нибудь сложных конвенций, сложность совместной разработки
- меньшее количество доступных библиотек, их малая совместимость
- непосредственный доступ к аппаратуре: портам ввода-вывода, особым регистрам процессора
- возможность написания самомодифицирующегося кода (т.е. метапрограммирования, причем без необходимости программного интерпретатора)
- максимальная «подгонка» для нужной платформы (использование специальных инструкций, технических особенностей «железа»)
- непереносимость на другие платформы (кроме двоично совместимых).
Синтаксис
Общепринятого стандарта для синтаксиса языков ассемблера не существует. Однако, существуют стандарты де-факто — традиционные подходы, которых придерживаются большинство разработчиков языков ассемблера. Основными такими стандартами являются Intel-синтаксис и AT&T-синтаксис.
Общий формат записи инструкций одинаков для обоих стандартов:
`[метка:] опкод [операнды] [;комментарий]`
Опкод — непосредственно мнемоника инструкции процессору. К ней могут быть добавлены префиксы (повторения, изменения типа адресации и пр.). В качестве операндов могут выступать константы, названия регистров, адреса в оперативной памяти и пр.. Различия между стандартами Intel и AT&T касаются, в основном, порядка перечисления операндов и их синтаксиса при различных методах адресации.
Используемые мнемоники обычно одинаковы для всех процессоров одной архитектуры или семейства архитектур (среди широко известных — мнемоники процессоров и контроллеров Motorola, ARM, x86). Они описываются в спецификации процессоров.
Например, процессор Zilog Z80 наследовал систему команд Intel i8080, расширил ее и поменял мнемоники (и обозначения регистров) на свой лад. Например, сменил интеловские mov
на ld
. Процессоры Motorola Fireball наследовали систему команд Z80, несколько её урезав. Вместе с тем, Motorola официально вернулась к мнемоникам Intel. и в данный момент половина ассемблеров для Fireball работает с интеловскими мнемониками, а половина с мнемониками Zilog.
Директивы
Кроме инструкций, программа может содержать директивы: команды, не переводящиеся непосредственно в машинные инструкции, а управляющие работой компилятора. Набор и синтаксис их значительно разнятся и зависят не от аппаратной платформы, а от используемого компилятора (порождая диалекты языков в пределах одного семейства архитектур). В качестве набора директив можно выделить:
- определение данных (констант и переменных)
- управление организацией программы в памяти и параметрами выходного файла
- задание режима работы компилятора
- всевозможные абстракции (т.е. элементы языков высокого уровня) — от оформления процедур и функций (для упрощения реализации парадигмы процедурного программирования) до условных конструкций и циклов (для парадигмы структурного программирования)
- макросы
Происхождение и критика термина «язык ассемблера»
Данный тип языков получил свое название от названия транслятора (компилятора) с этих языков — ассемблера (англ. assembler — сборщик). Название последнего обусловлено тем, что на первых компьютерах не существовало языков более высокого уровня, и единственной альтернативой созданию программ с помощью ассемблера было программирование непосредственно в кодах.
Язык ассемблера в русском языке часто называют «ассемблером» (а что-то связанное с ним — «ассемблерный»), что, согласно английскому переводу слова, неправильно, но вписывается в правила русского языка. Однако, сам ассемблер (программу) тоже называют просто «ассемблером», а не «компилятором языка ассемблера» и т. п.
Использование термина «язык ассемблера» также может вызвать ошибочное мнение о существовании единого языка низкого уровня, или хотя бы стандарта на такие языки. При именовании языка, на котором написана конкретная программа, желательно уточнять, для какой архитектуры она предназначена и на каком диалекте языка написана.
Элементы синтаксиса:
Комментарий до конца строки | ; ! / # |
---|---|
Регистрозависимость | нет |
Последовательность | конец строки |
Ссылки:
IDE/Редакторы:
Примеры:
Hello, World!:
Пример для версий Intel x86 (IA32)MSDOS
mov ax,cs
mov ds,ax
mov ah,9
mov dx, offset Hello
int 21h
xor ax,ax
int 21h
Hello:
db "Hello World!",13,10,"$"
Hello, World!:
Пример для версий Amiga move.l #DOS
move.l 4.w,a6
jsr -$0198(a6) ;OldOpenLibrary
move.l d0,a6
beq.s .Out
move.l #HelloWorld,d1
A) moveq #13,d2
jsr -$03AE(a6) ;WriteChars
B) jsr -$03B4 ;PutStr
move.l a6,a1
move.l 4.w,a6
jsr -$019E(a6) ;CloseLibrary
.Out rts
DOS dc.b 'dos.library',0
HelloWorld dc.b 'Hello World!',$A,0
Hello, World!:
Пример для версий AtariST move.l #helloworld,-(A7)
move #9,-(A7)
trap #1
addq.l #6,A7
move #0,-(A7)
trap #1
helloworld:
dc.b "Hello World!",$0d,$0a,0
Hello, World!:
Пример для версий Intel x86 (IA32)NASM Linux , используется Intel синтаксис. Компиляция и линковка:
- nasm –f elf –o hello.o hello.asm
- ld -o hello hello.o
SECTION .data
msg db "Hello, world!",0xa
len equ $ - msg
SECTION .text
global _start
_start: ; Точка входа в программу
mov eax, 4 ; 'write' системный вызов
mov ebx, 1
mov ecx, msg ; Указатель на данные
mov edx, len ; Количество данных
int 0x80 ;Вызов ядра
mov eax, 1 ; '_exit' системный вызов
mov ebx, 0 ; Возвращаем 0 (все хорошо)
int 0x80 ; Вызов ядра
Hello, World!:
Пример для версий PDP-8/ — комментарии.
/ Hello World на ассемблере для DEC PDP-8
*200
hello, cla cll
tls / tls устанавливает флаг печати.
tad charac / создает индексный регистр
dca ir1 / для получения символов
tad m6 / настроить счетчик для
dca count / ввода символов.
next, tad i ir1 / получить символ.
jms type / его тип.
isz count / сделать что нибудь еще?
jmp next / нет, ввести другой символ
hlt
type, 0 / подпрограмма type
tsf
jmp .-1
tls
cla
jmp i type
charac, . / используется в качестве начального значения ir1.
310 / H
305 / E
314 / L
314 / L
317 / O
254 / ,
240 /
327 / W
317 / O
322 / R
314 / L
304 / D
241 / !
m6, -15
count, 0
ir1 = 10
$
Hello, World!:
Пример для версий PDP-11Программа написана на макроассемблере MACRO-11 Для компиляции и запуска этой программы в ОС RT-11 командуем:
. MACRO HELLO
ERRORS DETECTED: 0
. LINK HELLO -- Линкуем
. RUN HELLO -- Запускаем
Hello, world!
.TITLE HELLO WORLD ; Название
.MCALL .TTYOUT,.EXIT
HELLO:: MOV #MSG,R1 ; Начальный адрес строки
1$: MOVB (R1)+,R0 ; Получаем следующий символ
BEQ DONE ; Если ноль, выходим из цикла
.TTYOUT ; Иначе печатаем символ
BR 1$ ; Повтор цикла
DONE: .EXIT
MSG: .ASCIZ /Hello, world!/ ; Строка Hello, world!
.END HELLO ; Конец программы HELLO
Hello, World!:
Пример для версий System/360, System/370IBM System/360/370/390 Basic Assembler Language .
// EXEC ASSEMBLY
START
MAIN BALR 2,0
USING *,2
OPEN PRINT
MVC BUF,HW
PUT PRINT
CLOSE PRINT
EOJ
HW DC CL132'HELLO WORLD'
BUF DS CL132
PRINT DTFPR IOAREA1=BUF,DEVADDR=SYSLST,BLKSIZE=132, *
DEVICE=3203,CONTROL=YES,PRINTOV=YES
END MAIN
/*
// EXEC LNKEDT
// EXEC
/*
/&
Hello, World!:
Пример для версий Apple II********************************
* HELLO WORLD FOR 6502 APPLE ][ *
********************************
STROUT EQU $DB3A
LDY #>HELLO
LDA #<HELLO
JMP STROUT
HELLO ASC "HELLO WORLD!",00
Hello, World!:
Пример для версий PDP-10CHTTYO — весь ввод/вывод осуществляется с помощью каналов ввода/вывода. Лучше всего сделать символические имена для тех каналов, которые вы используете, и начинать их с CH. Определите эти имена с помощью MIDAS оператора == .
.CALL — это символическое обозначение для вызова системного вызова. Его формат: .CALL [SETZ ? SIXBIT/callname/ ? arguments ((SETZ))] .
OPEN открывает канал ввода/вывода для использования. Требует два параметра — номер канала и имя устройства в SIXBIT.
.LOSE %LSFIL — системный вызов, который печатает сообщение об ошибке ввода/вывода, если вдруг она произошла.
.IOT — системный вызов, который фактически занимается вводом/выводом. В качестве параметра нужно указать канал и адрес, содержащий код символа для вывода. Например, “H представляет H .
TITLE PRINTHELLO
A=1
CHTTYO==1 ;Канал для вывода.
START: ;Открытие TTY канала.
.CALL [SETZ ? SIXBIT/OPEN/
[.UAO,,CHTTYO] ? [SIXBIT/TTY/] ((SETZ))]
.LOSE %LSFIL
.IOT CHTTYO,["H] ;Печать HELLO WORLD посимвольно.
.IOT CHTTYO,["E]
.IOT CHTTYO,["L]
.IOT CHTTYO,["L]
.IOT CHTTYO,["O]
.IOT CHTTYO,[^M] ;Символ новой строки
.IOT CHTTYO,["W]
.IOT CHTTYO,["O]
.IOT CHTTYO,["R]
.IOT CHTTYO,["L]
.IOT CHTTYO,["D]
.VALUE ;Программка, остановись :)
END START
Числа Фибоначчи:
Пример для версий MIPS32Эмулятор MARS. Вывод консоли MARS:
The Fibonacci numbers are:
1 1 2 3 5 8 13 21 34 55 89 144
-- program is finished running --
Программа выводит 15 чисел Фибоначчи. Количество чисел можно изменить в секции .data.
.data
space:.asciiz " "
head: .asciiz "The Fibonacci numbers are:\n"
fib: .word 0 : 15
size: .word 15
.text
main:
la $t0, fib
la $t5, size
lw $t5, 0($t5)
li $t2, 1
add.d $f0, $f2, $f4
sw $t2, 0($t0)
sw $t2, 4($t0)
addi $t1, $t5, -2
loop:
lw $t3, 0($t0)
lw $t4, 4($t0)
add $t2, $t3, $t4
sw $t2, 8($t0)
addi $t0, $t0, 4
addi $t1, $t1, -1
bgtz $t1, loop
la $a0, fib
move $a1, $t5
jal print
li $v0, 10
syscall
print:
add $t0, $zero, $a0
add $t1, $zero, $a1
la $a0, head
li $v0, 4
syscall
out:
lw $a0, 0($t0)
li $v0, 1
syscall
la $a0, space
li $v0, 4
syscall
addi $t0, $t0, 4
addi $t1, $t1, -1
bgtz $t1, out
jr $ra
Факториал:
Пример для версий MIPS3213! и дальше вызывают переполнение, поэтому вывод такой:
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 1932053504
14! = 1278945280
15! = 2004310016
.data
string1: .asciiz "! = "
string2: .asciiz "\n"
.text
main:
li $t1, 1
li $t2, 1
j loop
loop:
li $v0, 1
la $a0, ($t2)
syscall
la $a0, string1
li $v0, 4
syscall
mult $t1,$t2
mflo $t1
li $v0, 1
la $a0, ($t1)
syscall
la $a0, string2
li $v0, 4
syscall
addiu $t2,$t2,1
beq $t2, 16, endloop
j loop
endloop:
li $v0, 10
syscall
Комментарии
]]>blog comments powered by Disqus
]]>