Ассемблер в Unix (assembler linux freebsd)
Ключевые слова: assembler , linux , freebsd , (найти похожие документы )
From: marlyn <adain@mail.ru >
Newsgroups: http://www.wasm.ru
Date: Mon, 9 Dec 2003 14:31:37 +0000 (UTC)
Subject: Ассемблер в Unix
Оригинал: http://www.wasm.ru/print.php?article=asminunix
Ассемблер в Unix
#Введение
Так исторически сложилось, что программирование на ассемблере под unix
почти не востребовано, и занимаются им только кодеры-маньяки,
дзен-буддисты и прочие настоящие ассемблерщики.
Настоящий ассемблерщик - зверь крайне редкий, практически нигде и не
встретишь его, разве что в заповеднике - http://wasm.ru. Unix-ассемблерщик
еще более редкий подвид, практически вымерший, если не считать,
западный, http://linuxassembly.org.
Для исправления такой плачевной ситуации, и была написана эта статья,
а точнее цикл статей, которые по задумке автора, должны привлечь в
ряды адептов-юникс-дзена множество новых членов.
В первой части (которую вы сейчас читаете) я имею честь познакомить
вас с прекрасным миром unix-программирования, что выльется в написание
простейшего helloworld. В следующей части - мы разберем несколько,
более сложных примеров. И под конец, наверное, будет программирование
под x-windows.
#Инструменты
Для нормально функционирования нам понадобятся следующие вещи:
1. Собственно какая-либо unix-совместимая ось. (например linux, или
лучше FreeBSD ),
2. Компилятор fasm. ( http://www.flatassembler.net )
3. Линкер ld ( есть почти в любом дистрибутиве unix ),
4. Особый склад ума, причем последнее - самое главное. Если у вас
этого нет, то ни один, даже самый последний RedHat на пару со
свежим fasm'ом вам не поможет.
И еще, о компиляторах - в 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:
int 0x80
ret
start:
push msg_len ; размер строки
push msg ; адрес строки
push 1 ; stdout
mov eax,4 ; номер системной функции - sys_write
call sys_call
add esp,4*3 ; очищаем за собой стек
Впрочем, от функции sys_call можно отказаться, достаточно просто
помещать в стек лишний dword:
start:
push msg_len ; размер строки
push msg ; адрес строки
push 1 ; stdout
mov eax,4 ; номер системной функции - sys_write
push eax ; все что угодно
int 0x80
add esp,4*3 ; очищаем за собой стек
Также FreeBSD поддерживает конвенцию вызова, применяемую в linux. Для
это необходимо включить linux emulation. Еще эта эмуляция потребуется
для запуска fasm. А еще нужна утилита brandelf (наверняка она у вас
есть). Дело в том, что пока не существует версии fasm'а конкретно для
BSD систем. Но это легко исправить, вот так:
Brandelf -t Linux fasm
Если это не сработает (а такое возможно из-за не совместимости
форматов), придется перекомпилировать fasm, заменив формат файла
"format PE executable" на простой "format ELF", а потом слинковать ld.
Linux
В линуксе используется fastcall конвенция. Номер функции, все так же,
помещается в eax, а вот параметры, вместо стека, помещаются в
регистры. Пример:
mov edx,msg_len
mov ecx,msg
mov ebx,1
mov eax,4
int 0x80
Порядок размещения параметров такой:
No. параметра Регистры
1
ebx
2 ecx
3 edx
4
esi
5
edi
6 ebp
Как видите максимальное количество параметров - 6. Если их больше,
приходиться помещать все параметры в структуру и передавать ее адрес в
ebx.
#Описание системных функций
После того как вы разобрались с вызовом функций, будет логичным
вопрос: "А где взять описание этих самых функций?".
Ничего похожего на msdn, в unix среде к сожалению не существует, но не
нужно забывать: unix - система с открытым исходном кодом и все нужное,
можно найти там.
Для linux:
arch/i386/kernel/entry.S
include/asm-i386/unistd.h
include/linux/sys.h
Для FreeBSD:
i386/i386/exception.s
i386/i386/trap.c
sys/syscall.h
Для каждой функции можно посмотреть описание, используя 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, или на форум http://wasm.ru/forum/
До встречи.
Примеры к статье:
http://www.opennet.dev/soft/asminunix.zip
(http://www.wasm.ru/pub/28/files/asminunix.zip )
[C] marlyn
© 2002 wasm.ru - all rights reserved and reversed
1.1 , Voodoo (? ), 15:55, 14/02/2004 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
Странно, но у меня на FreeBSD 4.9 и 5.0 ни один из скачанных FASM'ов не заработал. Говорит бинарник корявый и все тут.
2.2 , das (? ), 14:47, 23/04/2004 [^ ] [^^ ] [^^^ ] [ответить ]
+ /–
хм, а с чего это Линуксовый Эльф у тебя под БСД вдруг заработать должен?
2.8 , BoMBeR (? ), 12:39, 27/06/2007 [^ ] [^^ ] [^^^ ] [ответить ]
+ /–
>Странно, но у меня на FreeBSD 4.9 и 5.0 ни один из
>скачанных FASM'ов не заработал. Говорит бинарник корявый и все тут.
Я делал так:
- скачал LibC версию FASM 1.66
- слинковал имеющийся объектник fasm.o под FreeBSD с помощью "ld -o fasm fasm.o"
- далее запускал полученный экзешник под FreeBSD
2.9 , Maxim (?? ), 16:32, 18/07/2007 [^ ] [^^ ] [^^^ ] [ответить ]
+ /–
Приветик. В Бсд системе лучше пользоваьтся as и ld ну полюбому знаешь.
я не знаю как подключть препроцессор m4 если знаешь как черкани.
Fasm лучше не пользовать так как Linux системы и традиционные разновидности Unix не поддреживают даже некоторые жизненно важные команды ассемблера.
Я долго над этим мучался. Решил воспользоваться С. Вообще я разачаровался юниксовым ассемблером. Хочу найти информацию по нему для своей оси бсд 6.0.
Если знаешь где напиши. Заранее рад. Пока.
1.3 , dimus (?? ), 14:02, 04/08/2004 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
И вы думаете, что человек, ни разу в глаза не видевший ассемблера, что-то из Вашей статьи для себя вынесет?
1.4 , проходивший мимо (? ), 16:38, 23/02/2005 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
to dimus: не такая уж плохая статья, по крайней мере понятно о чем написано. А тому кто асма в глаз не видел надо учебник читать, а не статьи
1.10 , rickert (? ), 05:33, 21/11/2007 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
Вот я, занимался раньше асмом под дос/винду. И из вашей статьи нифигища не понял. Что, откуда, куда, зачем? Просто обрывки какие-то вывалили и всё.
1.11 , anonymous (?? ), 21:41, 10/01/2008 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
>Вот я, занимался раньше асмом под дос/винду. И >из вашей статьи нифигища не понял. Что, откуда, >куда, зачем? Просто обрывки какие-то вывалили и >всё.
// GPL v3
if ( winOS == nixOS ) {
we = "fullASS";
} else {
return UNIXWAY;
}
1.12 , havanagila (? ), 00:59, 27/12/2008 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
Вот тут очень много информации, правда придется со словарем посидеть, благо не китайско-санскритским + санскрит-русским, - я имею в виду, что кому нужно - осилит, все доступно и просто. Собственно о чем весь месаг: http://asm.sourceforge.net/howto/Assembly-HOWTO.html
На русском языке искать подобную литереатуру, во всяком случае подобного качества, бесполезно. Только истый маньяк мог написать, хотя бы перевод в нашей могучей и щедрой. Если я не прав, рад сокрушиться метким комментом.
1.14 , Сева (? ), 23:49, 14/12/2010 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
Приветствую тебя! Как посмотреть линукс ядро в машинном коде (враскрытом виде). с уважением Всеволод
1.15 , hacker (? ), 11:56, 17/07/2016 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
Ну, если параметров больше 6, то их оставшиеся можно в стек разложить, не обязательно упаковывать в структуру. Таков стандарт вызовов в Linux