]]> ]]>
Править | Обсудить | История

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/370

IBM 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-10

CHTTYO — весь ввод/вывод осуществляется с помощью каналов ввода/вывода. Лучше всего сделать символические имена для тех каналов, которые вы используете, и начинать их с 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     

Факториал:

Пример для версий MIPS32

13! и дальше вызывают переполнение, поэтому вывод такой:

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

]]>

Работа программистам