Эльфы большие и маленькие

             

Программирование с libc— семейная идиллия - часть 2


Структурно, программа состоит из секции кода, объявленной директивой ".text" и секции данных (".data"), которые могут располагаться в любом порядке, на размер сгенерированного файла это никак не влияет, все равно линкер переставит их по-своему.

Объявлять вызываемые libc-функции "внешними" (директива ".extern"), как это советует целый ряд авторов, совершенно необязательно. Имена функций пишутся как они есть, то есть без всяких там символов прочерка, на которые в частности ссылается Зубков в своей книге "Assembler — язык неограниченных возможностей", дескать иначе под BSD программа ассемблироваться не будет. Ничего подобного! Все работает только так!

Точка входа в программу означается меткой main, которая обязательно должна быть объявлена как global. В действительности, при запуске программы, первым управление получает стартовый код библиотеки libc, который уже и вызывает main. Если же такой метки там не окажется, линкер сообщит о неразрешимой ссылке и все.

Выходить из main можно как по exit(err_code), так и по машинной команде RET, возвращающей нас в стартовый код, корректно завершающий выполнение. Это короче, однако, в последнем случае мы теряем возможность передавать код возврата, который можно "подсмотреть" командой "echo $?"

после завершения работы программы.

Согласно Си-соглашению, аргументы функций заносятся в стек справа налево, стек "чистит" вызывающий код. Вот, собственно, и все. С полученным "багажом" знаний уже можно писать программу. В нашем случае она будет выглядеть так (см. листинг 1).

.text

// используемые функции объявлять внешними необязательно

//.extern write

//.extern exit

.global main

main:

       pushl  $len

       pushl  $msg

       pushl  $1

       call   write

       addl   $12, %esp

      

       ret

      

.data

       msg: .ascii "hello,elf\n"

       len = . - msg




Содержание  Назад  Вперед