[C] marlyn #ВведениеТак исторически сложилось, что программирование на ассемблере под unix почти не востребовано, и занимаются им только кодеры-маньяки, дзен-буддисты и прочие настоящие ассемблерщики. Настоящий ассемблерщик - зверь крайне редкий, практически нигде и не встретишь его, разве что в заповеднике - wasm.ru. Unix-ассемблерщик еще более редкий подвид, практически вымерший, если не считать, западный, linuxassembly.org. Для исправления такой плачевной ситуации, и была написана эта статья, а точнее цикл статей, которые по задумке автора, должны привлечь в ряды адептов-юникс-дзена множество новых членов. В первой части (которую вы сейчас читаете) я имею честь познакомить вас с прекрасным миром unix-программирования, что выльется в написание простейшего helloworld. В следующей части - мы разберем несколько, более сложных примеров. И под конец, наверное, будет программирование под x-windows. #ИнструментыДля нормально функционирования нам понадобятся следующие вещи:
И еще, о компиляторах - в unix обычно используются AS с AT&T синтаксисом, который для многих людей, выросших на tasm'е и masm'е, кажется полной абракадаброй. Поэтому, для начала, мы будем использовать привычные компиляторы с Intel'овским синтаксисом (fasm или nasm). Хотя позже, если найдутся желающие, можно будет рассмотреть и AT&T asm. #Общие сведенияUnix, который мы будем использовать - 32 битная система, работающая в защищенном режиме, и использующая плоскую модель памяти. Как и большинство операционных систем, Unix предоставляет программе набор различных функций (по другому - Api). Но, в отличие от, например, WinAPI, где вызовы производятся с помощью call'ов, в unix - больше свободы: можно вызывать функция ядра напрямую, а можно использовать многочисленные библиотеки. Рассмотрим для начала первый способ. Системный вызов производится с помощью прерывания 0x80 (чаще всего). К сожалению, (а может и к счастью) существует несколько конвенций вызова, что приводит к несовместимости кода между многими unix-like осями. Я рассмотрю только две, самые популярные платформы: Linux и *BSD. FreeBSD (а также OpenBSD и NetBSD) Эта система использует традиционную unix конвенцию вызова: номер функции помещается
в eax, параметры в стек, вызов производится с помощью функции содержащей int
0x80, а результат возвращается в eax. sys_call: Впрочем, от функции sys_call можно отказаться, достаточно просто помещать в стек лишний dword: start: Также FreeBSD поддерживает конвенцию вызова, применяемую в linux. Для это необходимо включить linux emulation. Еще эта эмуляция потребуется для запуска fasm. А еще нужна утилита brandelf (наверняка она у вас есть). Дело в том, что пока не существует версии fasm’а конкретно для BSD систем. Но это легко исправить, вот так: Brandelf –t Linux fasm Если это не сработает (а такое возможно из-за не совместимости форматов), придется перекомпилировать fasm, заменив формат файла “format PE executable” на простой “format ELF”, а потом слинковать ld.
Linux mov edx,msg_len Порядок размещения параметров такой:
Как видите максимальное количество параметров - 6. Если их больше,
#Описание системных функцийПосле того как вы разобрались с вызовом функций, будет логичным вопрос: "А где взять описание этих самых функций?". Ничего похожего на msdn, в unix среде к сожалению не существует, но не нужно забывать: unix - система с открытым исходном кодом и все нужное, можно найти там. Для linux: Для каждой функции можно посмотреть описание, используя man(2).
#Пример программы. Hello worldПришло время написать, тот самый, жутко всем надоевший - HelloWorld. Я приведу пример только FreeBSD версии, переписать это под linux - будет вашим домашним заданием. (для самых ленивых - см. примеры к статье) ------------------[cut]----------------------------------- format ELF section '.text' executable public _start _start: push msg_len ; size of message push msg ; offset of message push 1 ; stdout mov eax,4 ; 4 = sys_write push eax int 0x80 add esp,4*3 ; очищаем за собой стэк xor eax,eax push eax ; код выхода inc eax ; 1 = sys_exit int 0x80 section '.data' writeable msg db "Hello world",0 msg_len = $-msg ------------------[end cut]-------------------------------
Сборка. fasm hello.asm hello.o А потом слинкуем: ld -o hello hello.o А теперь посмотрите на размер. 600 байт, впечатляет?! ( размер можно еще очень сильно уменьшить, но об этом, как-нибудь в другой раз)
#Использование библиотеки libcНекрасивый и совсем не дзенский способ, но все же мы его рассмотрим - для полноты картины. Итак, libc (c library) - это стандартная библиотека с для UNIX. Она содержит в себе кучу полезных функций, типа printf, и используется почти во всех обычных программах (кстати сказать, многие функции этой библиотеки - простые обертки над вызовами ядра). В FASMе существуют удобные макросы, для вызова си функций..., но я не буду их использовать, отдав предпочтение чистому ассемблеру. Пример: ------------------[cut]----------------------------------- format ELF section '.text' executable extrn printf public main main: push msg call printf add esp,4 ret section '.data' writeable msg db "Hello world!\n",0 ------------------[end cut]------------------------------- Компилируется это дело так: fasm hellolib.asm hellolib.o gcc -o hellolib hellolib.o Заключение. Ну вот вы и написали свою первую программу на ассемблере под UNIX. Все на много проще чем кажется, неправда ли? Eсли у вас возникнут какие-либо вопросы, пишите мне на adain@mail.ru, или на форум WASM.RU. До встречи. Примеры к статье прилагаются
|
|||||||||||||||||||||