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


макет программы, определяющей номера системных вызовов в Linux и BSD


Теперь лезем в man ("man 2 write") и смотрим какие параметры этот вызов принимает. Ага: write(int d, const void *buf, size_t n_bytes). То есть, мы должны занести #4 в eax, файловый дескриптор – в ebx, указатель на выводимую строку – в ecx и количество выводимых байт – в edx, после чего вызвать прерывание INT 80h.

BSD-системы используют гибридный механизм: прерывание INT 80h и FAR CALL 0007h:00000000h. Номера системных вызовов так же как и в Linux помещаются в регистр eax, а вот параметры передаются через стек по Си-подобному соглашению (то есть, первым заносится крайний правый параметр, последним в стек ложится фиктивный dword, стек чистит за собой вызывающий код). Поскольку, номера базовых системных вызовов в обоих системах совпадают, можно исхитриться и написать программу, работающую под обоими операционными системами: Linux не обращает внимание на стек, а BSD — на регистры, что позволяет нам продублировать параметры и там, и там. Естественно, это увеличивает размер программы, но, к нашему счастью, BSD позволяет эмулировать Linux-интерфейс, достаточно дать команду "brandelf ?t Linux имя_файла", после чего нам останется только запустить его! А Linux в свою очередь умеет эмулировать BSD, SunOS и еще много чего!

Но довольно слов, переходим к делу! Перепишем нашу программу, чтобы она выводила приветствие через системный вызов write без использования libc. Стартовый код в этом случае исчезает и точкой входа в программу становится метка _start, объявленная как global. Ну а сама программа выглядит так:

.text

.globl        _start

_start:

       movl   $4,%eax              ; // системный вызов #4 "write"

       movl   $1,%ebx              ; // 1 -- stdout (xorl %ebx,%ebx/incl %ebx)

       movl   $msg,%ecx     ; // смещение выводимой строки

       movl   $len,%edx     ; // длина строки

       int    $0x80         ; // write(1, msg, len);

      

       movl   $1, %eax      ; // системный вызов #1 "exit"

       xorl   %ebx,%ebx     ; // код возврата

       int    $0x80         ; // exit(0);

.data

       msg: .ascii "hello,elf\n"

       len

= . - msg



Содержание раздела