Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 августа!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Возможности языков семейства Си по истине безграничны, однако, в этой свободе кроются и недостатки: всегда нужно программисту держать ухо востро и контроллировать "переполнение буфера", чтобы потом программа не вылетала в "синий экран" на массе разнообразных версий Windows и железа у пользователей. Те же крэкеры и реверсеры специально ищут в коде программ на Си уязвимости, куда можно подсадить любой вирусный код, об этом более подробно автор рассказывал в своём видеокурсе здесь. Я там многое узнал и теперь мой код стал значительно более безопасный.
.. ASM под Unix  //dev0id

"Как вы думаете, какой язык программирование является лучшим?" - на этот вопрос можно можно наткнутся во многих голосовалках и форумах. Конечно же это вопрос риторический, но все же, давайте подумаем. Как известно, для каждой цели хорошо свое решение, так и в программировании: для написания скриптов используют перл, пхп, асп... для написания более сложных прикладных программ-языки высокого уровня, такие как паскаль, делфи... для написания низкоуровневых приложений используют С/С++, асм. Мы поговорим об ассемблере. В переводе на русский это слово переводится как "сборка", "конструирование"... Данный язык восновном применяется для написания программ работающих вплотную с оборудованием. Для доса и виндоус этот язык вообще незаменим, так как сама операционная система писалась на нем. Но мы поговорим об ассемблере под юникс-подобные операционные системы. Все мы знаем, что юникс писался на С, следовательно этот язык является низкоуровневым в этой системе (на С можно делать обсолютно все в юниксе, даже читать побайтно с жесткого диска, так как все устройства являются файлами, то и обращение к ним через системный вызов SYS_open()). "Но причем тогда здесь ассемблер?" - спросите вы. А все очень просто. Дело в том, что на асме мы попрежнему можем очень тесно работать с процессором, как то: работа с регистрами, стэком... ну и конечно же переводить его в защищенный режим. На С все это можно было делать вставляя инструкции на том же асме (пусть это и называлось по другому, но в заголовочных файлах все открыто и ясно) - вспомните функцию __asm(); И так, начнем.

Конечно же ассемблер под юникс отличается от ассемблера под доc или виндоуз. В то время как в асме под эти операциоyные системы использовался синтаксис навязанный интеллом, изобилующий разными неопределенностями (неоднозначностями, если хотите), решающимися за счет приведения типа (byte ptr, word ptr, dword ptr), в асме под никс использовался сиснтексис AT&T и SysV/386, который разрабатывался специально для устранения неоднозначности толкования команд. Конечно же существуют ассемблеры, под юникс с интелловским синтаксисом, такие как NASM, но в данной статье будет рассмотрен синтаксис ассемблеров стандартных для данной платформы.

Вообще, конечно же стоило бы начать с правил. Мы так и поступим. В ассемблере, использующем AT&T синтаксы, для работы используются все латинские буквы, цифры, а также дополнительные символы, такие как процент, запятая, точка, подчеркивание, звездочка, значек доллара. Команды процессора: любая последовательность разрешенных символов, начинающаяся не со спец.знака либо цифры и не заканчивающаяся двоеточием, считается ассемблером командой процессора:

 //останов процессора
 hlt
если же такая последовательность начинается со знака процента, то это регистр процессора:
 pushl %eax
 // помещает содержимое регистра %eax в стэк
а если начинается с доллара ($), то это непосредственный операнд. Нижеприведенный код помещает в стэк число 0, 10h, и адрес переменной qwerty:
 pushl         $0
 pushl    $0x10
 pushl $qwerty
если последовательность начинается с точки, то это считается дерриктивой ассемблера:
 .aling 2
ну а если последовательность заканчивается двоеточием, то это метка (используется точно также как и в ассемблере под доc и виндоуз). Стоит отметить специальную метку точка - эта метка, как и в асме под доc характеризует текущий адрес.
Команды преобразованя типов в синтексисе AT&T имеют названия из четырех букв: С, размер источника, Т, размер приемника:
 //cbw
 	cbtw
 //cwde
 	cwtl
 //cwd
 	cwtl
 //cdq
 	cltd
 где:
 b-                               байт
 w-                              слово
 l-                      двойное слово
 q-                 учетверенное слово
 s- 32битное число с плавающей запятой
 l-64битное число с плавайющей запятой
 t- 80битное число с плавайщей запятой
Одно из важнейших отличий в ассемблерах это запись премника и источника, а отличае от дос-асма, в юниксе операнд-источник записывается всегда на первой позиции
 //mov ax,bx
 	movw	%bx,%ax
 //imul eax,ecx,16
 	imull $16,%ecx,%eax
Виды адресаций: как уже говорилось ранее, регистровый операнд и непосредственный различаются прейиксами % и $:
 //xor ebx,ebx
 	xorl %ebx,%ebx
 //mov edx,offset qwerty
 	movl $qwerty,%edx
При косвенной адресации используется немодифицированное имя переменной, как это было в интелловском варианте:
 //push dword ptr qwerty
 	pushl $qwerty
Более сложные способы адресации лучше рассматривать на базе операций со сдвигом, по базе и индексированием:
 //mov eax,base_addr[ebx+edi*4]
 	movl base_addr(%ebx+%edi*4),%eax
 //lea eax,[eax,eax*4]
 	leal (%eax,%eax*4),%eax
 //mov ax,word ptr [bp-2]
 	movw -2(%ebp),%ax
 //mov edx,dword ptr [edi*2]
 	movl (%edi*2),%edx
Непосредственно сам процесс программирования разделяется на программирование с использованием библиотеки libc и на программирование без ее использования. Так как сама система написанна на С и многие функции обращаются к этой библиотеке, то и программы написанные на ассемблере имеют возможность обращаться к ней. Вызов библиотечной функции осуществляется при помощи команды call. Но есть одна проблема: так как не все юникс системы схожи, то в некоторых системах перед библиотечной функцией нужно ставить знак подчеркивания. Рассмотрим следующую программу, выводящую знаменитую фразу:
 .text
 .globl main
 main:
 	pushl $message
 	call puts
 	popl %ebx
 	ret
 .data
 message:
 	.string	"Hello world!\0"
Без использования glibc программа будет выглядить слудующим образом:
 .text
 .globl _start
 _start:
 	movl 	$4,eax
 	xorl 	%ebx.%ebx
 	incl 	%ebc
 
 	movl	$message,%ecx
 	movl	$mesg_len,%edx
 	int 	$0x80
 
 	xorl	 %eax,%eax
 	incl 	 %eax
 	xorl	 %ebx,%ebx
 	int 	$0x80
 
 	hlt
 .data
 message:
 	.string	"Hello World!\012"
 mesg_len= .-message
 
В данном примере мы ипользовали для вывода на экран два системных вызова: write и exit. Вызову write соответсвует помещение в регистр %eax значения 4-значения под которым данная функция записанна в таблице системных вызовов, о которой я писал в своей статье о написании модулей ядра.
Вызывается данная функция путем вызова прерывания $0x80 Выходу из программы, т.е. ее завершению соответсвует системный вызов $1. Так же стоит заметить, что программирование и компиляция программ, написанных под разные *никс системы, немного отличается, так что я не буду указывать на различия, вам будет полезнее почитать такие документы как man страницы и HOW-TO документы.

<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS