Особенности программирования на языке Assembler
В нашу жизнь уже давно вошли процессоры с 64-х разрядной архитектурой. Не смотря на то, что все еще активно используются 32-х разрядные процессоры, и что программ для них в разы больше, новая архитектура приобретает все больше поклонников. 64-х разрядные процессоры позволяют использовать больше ресурсов, чем 32-х разрядные, позволяют оперировать с большим количеством данных за единицу времени… Читать ещё >
Особенности программирования на языке Assembler (реферат, курсовая, диплом, контрольная)
Оглавление Введение
1. Основные отличия архитектур i686 и amd64
2. Общие принципы программирования на языке Assembler для платформ i686 и amd64
Регистры Принцип передачи параметров в функции Работа со стеком Адресация
3. Листинг программы для сравнения архитектур i686 и amd64
4. Пример работы программы
5. Сравнение программ Вывод Список литературы
В нашу жизнь уже давно вошли процессоры с 64-х разрядной архитектурой. Не смотря на то, что все еще активно используются 32-х разрядные процессоры, и что программ для них в разы больше, новая архитектура приобретает все больше поклонников. 64-х разрядные процессоры позволяют использовать больше ресурсов, чем 32-х разрядные, позволяют оперировать с большим количеством данных за единицу времени, что в свою очередь повышает скорость и точность вычислений. В тоже время использование 64-х разрядной архитектуры влечет за собой повышенное потребление оперативной памяти и некоторые проблемы с совместимостью программ, написанных, для 32-х разрядной архитектуры.
Можно предположить, что новая архитектура будет требовать других способов программирования, и это окажется правдой. Например, были изменены регистры, стек, правила передачи аргументов в функции и другое.
В данной работе будет приведено сравнение особенностей программирования для 32-х разрядных и 64-разрядных процессоров на языке ассемблера. В качестве ОС будет применяться операционная система Ubuntu 12.10 LTS, компилятор gcc. Также мы будем придерживаться AT&T нотации языка программирования Assembler.
1. Основные отличия архитектур i686 и amd64
Нововведения в архитектуре 64-х разрядных процессоров позволили значительно увеличить объем используемой памяти для одного ядра процессора .
Таблица 1. Общие ограничения на память
Характеристика | 32-разрядные модели | 64-х разрядные модели | |
Виртуальное адресное пространство (один роцесс) | 4 ГБ | 16 ТБ | |
Виртуальное адресное пространство (32-х разрядный процесс) | 2 ГБ (3 ГБ, при запуске системы с ключом /3GB) | 4 ГБ | |
Виртуальное адресное пространство (64-х разрядный процесс) | ; | 8 ТБ | |
Пул подкачиваемой памяти (режим ядра) | 470 МБ | 128 ГБ | |
Пул неподкачиваемой памяти (режим ядра) | 156 МБ | 128 ГБ | |
Элемент системной таблицы страниц | 660−900 МБ | 128 ГБ | |
Также использование 64-х разрядной архитектуры позволяет обращаться к большему количеству регистров большего объема во время работы программы. Если при использовании 32-х разрядного режима мы могли обращаться к восьми 32-х разрядным регистрам общего назначения: EAX, EBX, ECX, EDX, EBP, ESI, EDI, ESP, к восьми 64-х разрядным регистрам для работы медиа данными и с числами с плавающей точкой: MMX0/FPR0, MMX1/FPR1, MMX2/FPR2, MMX3/FPR3, MMX4/FPR4, MMX5/FPR5, MMX6/FPR6, MMX7/FPR7, к флаговому 32-х разрядному регистру EFLAGS и к 32-х разрядному регистру-указателю на следующую инструкцию EIP, то в 64-х разрядном режиме у нас гораздо больше возможностей:
* Регистры общего назначения были расширены до 64-х разрядов с сохранением старой структуры и получили названия RAX, RBX, RCX, 3RDX, RBP, RSI, RDI и RSP;
* Были введены новые 64-х разрядные регистры в количестве восьми штук: R8, R9, R10, R11, R12, R13, R14, R15;
* Флаговый регистр и регистр-указатель на следующую инструкцию процессора были расширены до 64-х разрядов и получили названия RFLAGS и RIP соответственно;
* Было добавлено 16 128-разрядных медиа-регистров под названиями XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15.
Из вышесказанного можно сделать вывод о том, что использование 64-х разрядной архитектуры позволит более быстро, качественно и удобно решать поставленные как научные, так и общие задачи.
Стоит заметить, что результаты тестирования программ на различных платформах показывают, что в большинстве случаев использование 64-х разрядной архитектуры дает прирост производительности, по сравнению с 32-х разрядной архитектурой.
2. Общие принципы программирования на языке Assembler для платформ i686 и amd64
В данном разделе мы рассмотрим четыре основных вопроса, которые должны быть решены в первую очередь программистом на языке Assembler при переходе на новую аппаратную платформу: регистры, стек, передача параметров в функции и адресация.
Регистры
Использование 64-х разрядных регистров позволяет на единицу времени передавать гораздо больше информации. Если, в случае 32-х разрядной архитектуры, мы можем передать 32 бита информации за раз (максимальное число 4 294 967 296), то в случае 64-х разрядной архитектуры мы можем передать максимальное значение, равное 18 446 744 073 709 551 616.
Листинг 1. Передача данных в 64-х разрядной системе.
// Передача в регистр одного числа
movq %rbx, %rax
Листинг 2. Передача данных в 32-х разрядной системе.
// Передача в регистр одного числа
movl %ebx, %eax
Если число такого объема передавать не требуется, то мы можем в одном регистре передать несколько меньших чисел. Такой ход можно сделать на обеих архитектурах, но в случае 64-х разрядной архитектуры, объем данных, передаваемых за один такт, будет все равно больше, чем на 32-х разрядной архитектуре.
Листинг 3. Передача нескольких данных в одном регистре (64-х разрядная система).
// Передача в регистр трех чисел
movl %ecx, %eax
shlq $ 32, %rax
movw %dx %ax
shll $ 16, %eax
movw %bx, %ax
Листинг 4. Передача нескольких данных в одном регистре (32-х разрядная система).
// Передача в регистр трех чисел
movw %cx, %ax
5shll $ 16, %eax
movb %dl, %al
shlw $ 8, %ax
movb %bl, %al
Можно заметить, что, несмотря на то, что в обоих примерах было передано три числа в одном регистре, в случае использования 64-х разрядной архитектуры данные числа имеют большую разрядность, чем при использовании 32-х разрядной архитектуры.
Принцип передачи параметров в функции
С введением 64-х разрядной архитектуры был изменен способ передачи параметров в функции. Если, в случае 32-х разрядной архитектуры, параметры можно было передавать либо через стек, либо через регистры, то при использовании 64-х разрядной архитектуры первые четыре параметра (параметры должны быть целочисленными, указатель на класс (объектно-ориентированное программирование) считается целым числом и всегда помещается в регистр RCX) передаются через регистры RCX, RDX, R8, R9, а остальные через стек.
Листинг 5. Передача параметров в функцию в 64-х разрядной системе.
// Вызов функции с пятью аргументами
movq 5, dword ptr [%rsp+0×20] // Передаем пятый аргумент через стек
movq 4, %r9 // Передаем четвертый аргумент
movq 3, %r8 // Передаем третий аргумент
movq 2, %rdx // Передаем второй аргумент
movq 1, %rax // Передаем первый аргумент
call func // Вызываем функцию
func:
// …
// Код функции …
// …
addq 0×20, %rsp // Очищаем стек
ret // Возвращаем управление
Листинг 6. Передача параметров в функцию в 32-х разрядной системе.
// Вызов функции с пятью аргументами
pushl 5
pushl 4
pushl 3
pushl 2
pushl 1
call func
func:
// …
// Код функции …
Ret
Работа со стеком
В 64-разрядной архитектуре один элемент стека является 64-разрядным и меньшее значение туда положить нельзя. Стек выравнивается по границе в 16 Б, а не 8 Б в случае 32-разрядной архитектуры. Все остальные параметры работы со стеком остаются прежними, кроме того, что в 64-х разрядной архитектуре чаще всего применяется парадигма «резервирование пространства и повторное использование его», и именно из-за этого вызываемая функция не занимается чисткой стека. Этим должен заниматься вызывающий. При вызове функции обязательно должны сохраняться все регистры, кроме RAX, RCX, RDX, R8, R9, R10 и R11.
Адресация
программирование процессор архитектура адресация
Смена архитектуры никак не повлияла на смену способа адресации внутри программы. Адресация в 64-х разрядной системе строится по тому же принципу, как и в 32-х разрядной, и команда обращения к адресу занимает одинаковое количество байт и тактов.
Листинг 7. Адресация в 64-х разрядной системе.
// Загрузка опкода следующей машинной команды
movb [%rip], %al
nop
// Абсолютная адресация
xorq %r9, %r9
decb byte ptr (%r9+$ 777h)
Листинг 8. Адресация в 32-х разрядной системе.
// Загрузка опкода следующей машинной команды
call $ + 5
popl %ebx
addl $ 6, %ebx
movb (%ebx), %al
nop
// Абсолютная адресация
decb byte ptr ($ 777h)
3. Листинг программы для сравнения архитектур i686 и amd64
Листинг 9. Простейшая программа шифрования текста для архитектуры amd64..text
.globl crypt
.type crypt, @function
crypt:
.LFB0:
pushq %rbp
movq %rsp, %rbp
subq $ 32, %rsp
movq %rdi, -24(%rbp)
movq %rsi, -32(%rbp)
movl $ 0, -16(%rbp)
movl $ 0, -12(%rbp)
movq -24(%rbp), %rax
movq %rax, %rdi
call strlen
movq %rax, %rdi
call malloc
movq %rax, -8(%rbp)
jmp .L2
.L3:
movl -16(%rbp), %eax
movslq %eax, %rdx
movq -8(%rbp), %rax
addq %rax, %rdx
movl -16(%rbp), %eax
movslq %eax, %rcx
movq -24(%rbp), %rax
addq %rcx, %rax
movzbl (%rax), %ecx
movl -12(%rbp), %eax
movslq %eax, %rsi
movq -32(%rbp), %rax
addq %rsi, %rax
movzbl (%rax), %eax
xorl %ecx, %eax
movb %al, (%rdx)
addl $ 1, -16(%rbp)
addl $ 1, -12(%rbp)
movl -12(%rbp), %eax
movslq %eax, %rdx
movq -32(%rbp), %rax
addq %rdx, %rax
movzbl (%rax), %eax
testb %al, %al
jne .L2
movl $ 0, -12(%rbp)
.L2:
movl -16(%rbp), %eax
movslq %eax, %rdx
movq -24(%rbp), %rax
addq %rdx, %rax
movzbl (%rax), %eax
testb %al, %al
jne .L3
movq -8(%rbp), %rax
leave
ret
8.LFE0:
.size crypt, .-crypt
.section .rodata
.LC0:
.string «Hello, World!»
.LC1:
.string «My_key111»
.LC2:
.string «———————»
.text
.globl main
.type main, @function
main:
.LFB1:
pushq %rbp
movq %rsp, %rbp
subq $ 32, %rsp
movl %edi, -20(%rbp)
movq %rsi, -32(%rbp)
movq $.LC0, -16(%rbp)
movq $.LC1, -8(%rbp)
movq -16(%rbp), %rax
movq %rax, %rdi
call puts
movl $.LC2, %edi
call puts
movq -8(%rbp), %rdx
movq -16(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call crypt
movq %rax, -16(%rbp)
movq -16(%rbp), %rax
movq %rax, %rdi
call puts
movq -8(%rbp), %rdx
movq -16(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call crypt
movq %rax, -16(%rbp)
movl $.LC2, %edi
call puts
movq -16(%rbp), %rax
movq %rax, %rdi
call puts
movl $ 0, %eax
leave
ret
.LFE1:
.size main, .-main
Листинг 10. Простейшая программа шифрования текста для архитектуры i686. text
.globl crypt
.type crypt, @function
crypt:
.LFB0:
pushl %ebp
9movl %esp, %ebp
pushl %ebx
subl $ 36, %esp
movl $ 0, -12(%ebp)
movl $ 0, -16(%ebp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call strlen
movl %eax, (%esp)
call malloc
movl %eax, -20(%ebp)
jmp .L2
.L3:
movl -12(%ebp), %edx
movl -20(%ebp), %eax
addl %eax, %edx
movl -12(%ebp), %ecx
movl 8(%ebp), %eax
addl %ecx, %eax
movzbl (%eax), %ecx
movl -16(%ebp), %ebx
movl 12(%ebp), %eax
addl %ebx, %eax
movzbl (%eax), %eax
xorl %ecx, %eax
movb %al, (%edx)
addl $ 1, -12(%ebp)
addl $ 1, -16(%ebp)
movl -16(%ebp), %edx
movl 12(%ebp), %eax
addl %edx, %eax
movzbl (%eax), %eax
testb %al, %al
jne .L2
movl $ 0, -16(%ebp)
.L2:
movl -12(%ebp), %edx
movl 8(%ebp), %eax
addl %edx, %eax
movzbl (%eax), %eax
testb %al, %al
jne .L3
movl -20(%ebp), %eax
addl $ 36, %esp
popl %ebx
popl %ebp
ret
.LFE0:
.size crypt, .-crypt
.section .rodata
.LC0:
.string «Hello, World!»
.LC1:
.string «My_key111»
.LC2:
.string «———————»
.text
.globl main
.type main, @function
main:
10.LFB1:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $ 32, %esp
movl $.LC0, 28(%esp)
movl $.LC1, 24(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call puts
movl $.LC2, (%esp)
call puts
movl 24(%esp), %eax
movl %eax, 4(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call crypt
movl %eax, 28(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call puts
movl 24(%esp), %eax
movl %eax, 4(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call crypt
movl %eax, 28(%esp)
movl $.LC2, (%esp)
call puts
movl 28(%esp), %eax
movl %eax, (%esp)
call puts
movl $ 0, %eax
leave
ret
.LFE1:
.size main, .-main
4. Пример работы программы
Рисунок 1. Пример работы простейшей программы шифрования текста на архитектуре amd64.
Рисунок 2. Пример работы простейшей программы шифрования текста на архитектуре i686.
5. Сравнение программ
На таком простом примере сложно заметить прирост производительности «на глаз», но пример с шифрованием и дешифрованием данных был выбран неслучайно.
В большинстве алгоритмов шифрования и дешифрования данных, а также при составлении хэш-сумм требуется использование 64-х или более разрядных данных. Анализируя исходный код в примерах можно заметить, что использование 64-х разрядной архитектуры позволяет за один такт передать большее количество данных, а следовательно увеличить скорость работы алгоритма. При использовании многопоточных программ данный выигрыш будет заметен еще больше.
Вывод
В ходе выполнения данной работы был проведен сравнительный анализ основных отличий программирования на 32-х и 64-х разрядном ассемблерах.
Данный анализ показал, что использование 64-х разрядной архитектуры позволяет выполнять большинство задач быстрее, чем на 32-х разрядной архитектуре, но требует большего количество ресурсов компьютера и переучивания программиста. Стоит заметить, что для небольших математических задач и большинства бытовых возможностей 32-х разрядной архитектуры на данный момент хватает, но на данный момент стоит задуматься о том, чтобы уже делать приоритет на подготовку программистов для 64-х разрядных аппаратных платформ.
1. Ассемблер в Linux для программистов C http://ru.wikibooks.org/wiki/Ассемблер_в_Linux_для_программистов_C
2. Все, что нужно знать, чтобы начать программировать для 64-разрядных версий Windows, http://msdn.microsoft.com/ru-ru/library/dd335933.aspx
3. Архитектура x86−64 под скальпелем ассемблерщика, http://www.insidepro.com/kk/072/072r.shtml
4. Битва технологий: x64 против x86, http://www.platform64.net/x64blog/x64_soft/bitva_tehnologiy_x64_protiv_x86.h tml
5. Сравнение производительности веб-браузеров x86 и x64, http://www.platform64.net/x64blog/x64_soft/sravnenie_proizvoditelnosti_veb_br auzerov_x86_i_x64.html
6. Что лучше установить на ноутбук: Windows x86 или x64, http://www.interface.ru/home.asp?artId=23 789
7. Ассемблер в UNIX (мини-FAQ), http://www.insidepro.com/kk/209r.shtml
8. История соглашений вызова, часть 5: amd64, http://www.transl-gunsmoker.ru/2008/12/5-amd64.html
9. От С к Ассемблеру (gcc assembler), http://www.opennet.ru/base/dev/from_c_to_asm.txt.html