11.4. Программирование с использованием libc

Все программы для UNIX, написанные на С, постоянно обращаются к различ­ным функциям, находящимся в libc.so или других стандартных или нестандарт­ных библиотеках. Программы и процедуры на ассемблере, естественно, могут де­лать то же самое. Вызов библиотечной функции выполняется обычной командой

call, а передача параметров осуществляется в соответствии с С-конвенцией: пара­метры помещают в стек справа налево и очищают стек после вызова функции. Единственная сложность здесь состоит в том, что к началу имени вызываемой функции в некоторых системах, например FreeBSD, приписывается символ под­черкивания, в то время как в других (Linux и Solaris) имя не изменяется. Если имена в системе модифицируются, то имена процедур, написанных на ассембле­ре, вклюнаяташ(), также должны быть изменены заранее.

Программирование с Hbc

Посмотрим на примере программы, выводящей традиционное сообщение Hello world, как это делается.

// helloelf.s

// Минимальная программа,  выводящая сообщение "Hello world".

// Для компилящии в формат ELF.

//

// Компиляция:

// as -о helloelf.o helloelf.s // Компоновка:

// (пути к файлу crti.o могут отлияаться на других системах) // Solaris с SunPro С

//   Id '-S -о helloelf.sol helloelf.o /opt/SUNWspro/SC4.2/lib/crt1.o -lc

// Solaris с GNU С

//    Id -s -o helloelf.gso helloelf.o

//   /opt/gnu/lib/gcc-lib/i586-cubbi-solaris2.5.1/2.7.2.3.f.1/crt1.o -lc

// Linux

//   Id -S -m elf i386 -o helloelf,lnx /usr/lib/crtl.о /usr/lib/crti.о //   -L/usr/lib/gcc-lib/i586-cubbi-linuxlibcl/2.7.2 helloelf.o -lc -Igcc // /usr/lib/crtn.o

// или gcc -o helloelf.lnx helloelf.o

.text

// Код,  находящийся в файлах crt*.о,  передаст управление на процедуру main // после настройки всех параметров.

.globl main

main:

// Поместить параметр   (адрес строки message)   в стек, pushl $message

//  Вызвать функцию puts (message).

call puts // Очистить стек от параметров.

popl Шх // Завершить программу.

ret

.data

message:

.string "Hello world\0"

В случае с FreeBSD придется внести всего два изменения - добавить символ подчеркивания в начало имен функций puts и main и заменить директиву .string на .ascii, так как версия ассемблера, обычно распространяемого с FreeBSD, .string не понимает.

//

// Минимальная программа, выводящая сообщение "Hello world".

// Для компиляции в вариант формата C0FF,  используемый во FreeBSD 2.2.

// Компиляция для FreeBSD:

// as -o hellocof.o hellocof.s

// Id -s -o hellocof.bsd /usr/lib/crtO.о hellocof.o -lc

_main

Smessage _puts %ebx

"Hello world\0"

Пользуясь этой техникой, можно создавать программы точно так же, как и на С, но выигрыш за счет того, что на ассемблере допускается соптимизировать програм­му на несколько процентов лучше, чем это сделает компилятор с С (при максималь­ной оптимизации), окажется небольшим по сравнению с потерей переносимости. Кроме того, при написании любой сколько-нибудь значительной программы це­ликом на ассемблере мы столкнемся с тем, что, как и в случае с Win32, нам при­дется создавать собственные включаемые файлы с определениями констант и структур, взятых из включаемых файлов для С. А поскольку эти ассемблеры не умеют работать со структурами данных, необходимо описывать их средствами ис­пользуемого препроцессора - срр или т4.

Лучшее применение ассемблера для UNIX (кроме собственно разработки ядра системы) все-таки остается за незначительными процедурами, требующими боль­шой вычислительной мощности, - кодированием, архивированием, преобразова­ниями типа Фурье, которые не очень сложны и при необходимости могут быть легко переписаны заново на ассемблере для другого процессора или на С.