Re: lug-bg: C++ & Assembler
- Subject: Re: lug-bg: C++ & Assembler
- From: Viktor Vasilev <viktor@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Sun, 17 Oct 2004 06:45:28 +0200
- Mail-followup-to: lug-bg@xxxxxxxxxxxxxxxxxx
On Sun, Oct 17, 2004 at 12:14:15AM +0300, Dimitar Terziev wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Имам за задача да направя програмка на асемблер, дето от три числа
> извежда най-голямото. С писането на кода нямах проблем - писах го
> във Visual C++ в Бозата. Ама вкъщи нямам боза.... та въпроса е как
> във KDevelop например се въвеждат асемблерски инструкции? Кода е
> следният:
Въпросът не е пряко свързан с KDevelop, а с компилатора, който
използваш. Това, което те интересува е как се използва inline
assembly с GCC[1]. С google ще намериш достатъчно документация по
въпроса.
> <Cut>
> Това нещо бачка в бозата. Обаче хич не ми се иска да си инсталирам
> боза само за да пиша простотии на асеомблер, а искам да си ги правя
> в Линукс. Въпроса ми е как? Пробвах да запиша инструкциите по
> следния начин:
>
> __asm__ (
>
> "mov eax,a"
> .....
> .....
> .....
> );
Почти си улучил синтаксиса на GCC :) Понеже GCC използва gas[2] (GNU
assembler) за асемблер, ще трябва да ползваш неговия синтаксис.
Програмата, която си приложил е писана за MASM (Microsoft assember),
който използва Intel синтаксис, докато gas използва АТ&Т синтаксис.
Ето един пример[3] за GCC:
__asm__ ("
movl $1, %eax // exit syscall
xor %ebx, %ebx // exit status 0
int $0x80 // call kernel
");
Освен това, при inline assembly с GCC не можеш да се обръщаш към
аргументите на функцията по начина, по който го правиш с VC++ (mov
eax,a). Трябва да провериш в каква последователност аргументите биват
бутани в стека, за да можеш да ги преместиш после в регистри.
Обикновено това става в обратен синтактичен ред, за да може
лесно да ги извадиш. Ако имаш
foo(int bar, char *baz, float *moo)
би трябвало викащата функция да вкара (pushl) в стека първо moo, после
baz и накрая bar, за да може във функция foo с popl %eax да вземе
първия аргумент - bar. Отново - провери в документацията каква
конвенция се използва или деасемблирай някоя програмка и виж с очите
си :)
Ако използваш системни повиквания[4], конвенцията за викане е следната:
номерът на повикването се слага в EAX, a аргументите отиват подред в
регистрите EBX, ECX, EDX, ESI, EDI и EBP. Т.е. ако имаш
write(int d, const void *buf, size_t nbytes)
'int d' отива в EBX, 'const void *buf' в ECX и 'size_t nbytes' в EDX.
Ако имаш системно повикване с повече от 6 аргумента ще трябва да
правиш магии със стека :)
По-екзотичен е разширения синтаксис за GCC inline assembly:
__asm__("<asm routine>" : output : input : modify);
При него може да задаваш кои променливи ще служат за вход и изход,
както и кои ще бъдат променени. Прегледай документацията по темата.
След като издумах всичко това, да ти дам и едно предложение, което
може да ти спести ходенето по мъките с gas. Ако си инсталираш NASM
(Netwide assembler) ще можеш да пишеш на асемблер с Intel синтаксис,
както си му свикнал сега. А вместо да използваш inline assembly,
можеш направо да си напишеш на асемблер отделна функция, после да я
компилираш и линкнеш с главната програма.
Поздрави,
Виктор
[1]http://gcc.gnu.org/onlinedocs/gcc-3.4.2/gcc/
[2]http://sources.redhat.com/binutils/docs-2.15/as/index.html
[3]http://nuieee.fe.up.pt/~ee97034/la/linasm.html
[4]http://www.win.tue.nl/~aeb/linux/lk/lk-4.html
--
Linux is for those who hate Windows.
FreeBSD is for those who love UNIX.
============================================================================
A mail-list of Linux Users Group - Bulgaria (bulgarian linuxers).
http://www.linux-bulgaria.org - Hosted by Internet Group Ltd. - Stara Zagora
To unsubscribe: http://www.linux-bulgaria.org/public/mail_list.html
============================================================================
|