Круглосуточное общение

Тема закрыта
Вы любите (хотите) водить автомобиль?
да (18)
51%
нет (17)
49%
Всего голосов: 35
101K
.
Сексуальность валенка
Буду писать о Си для linux
И так как обычно пишут программы на си?
int main() {

    return 0;
}

Простой каркас, в нем объявленная функция main которая возвращает значение - 0.
И программа заканчивается возвращая значение которое вернула функция main, но на самом деле это все илюзия, mai не точка входа, это все дело glibc, а как же на чистом Си все делается?
Настоящая точка входа в программу функция _start() и если вы просто зделаете:
int _start() { return 0; }

И скомпилируете с параметром -nostdlib то вы не получите работающих программу.
.
Сексуальность валенка
Вы получите ошибку сегментации, потому что программа не полная, точка входа есть, а завершения программы нет, что вы думмали завершить программу тоже не просто.
Завершается программа системным вызовом, что такое системный вызов можно прочесть в википедии, но вкраце системные вызовы это API к ядру
.
Сексуальность валенка
Так как же завершить программу правильно?
Завершить её с помощи Си нельзя бо системные вызовы это низкоуровненая штука к которой можно получить доступ только через Ассемблер и машинный код.
Нам нужен системный вызов #1 это системный вызов exit, у него есть один аргумент - код возврата, это тот код с которым закончится программа.
.
# Swank (13.08.2015 / 01:04)
Есть тут кто?
Yes
.
Swank
Сексуальность валенка
Так давайте же сделаем системный вызов.
Для этого нам нужно обратится к Асмемблеру.
Это можно сделать с Си кода, называется Асемблерна вставка, а делается она так:
asm("Код на Ассемблере");

А код выхода выглядеть так:
asm(
    "movl  $1, %eax;" //системный вызов № 1 — sys_exit
    "xorl  %ebx, %ebx;" //выход с кодом 0
    "int   $0x80;" //вызов ядра
);
.
Сексуальность валенка
Не тестировал но должно работать.
Давайте же разберёмся немного что мы сделали.
Мы поместили в регистр номер системного вызова 1 - exit
Далее указали параметр системному вызову - 0, это код успешного завершения
Далее обратились к ядру linux и оно выполнено прерывание
.
# Swank (13.08.2015 / 01:37)
Не тестировал но должно работать.
Давайте же разберёмся немного что мы сделали.
Мы поместили в регистр номер системного вызова 1 - exit
Далее указали параметр системному вызову - 0, это код успешно
А зачем это нужн0?
.
Сексуальность валенка
Перекусил немного.
Я обычно код тестирую на своём arm ноуте, да и пишу тамже, он у меня как тестовый полигон, поэтому я привык к arm синтаксису GNU Assembler, x86 не юзаю поэтому мне намного комфортней показывать примеры с arm ассемблером, последующие Ассемблерные вставки для arm процессора, переделать их вообще не сложно
Итоговая рабочая программа для arm будет выглядеть так:
void _start() {

    //Тут код программы

    // Выход
    __asm__(
        "mov  r0, #0;"  // Возращаемое значение - 0
        "mov  r7, #1;" // Номер системного вызова - 1 (exit)
        "swi  0;" // Системный вызов ядра
    );
}

Можно скомпилировать, только обязательно с опцией -nostdlib, эта опция убирает glibc
И запустить, все что сделает программа это за пуститься и остановится с кодом 0
Чего ж мы hello world то не написали, на самом деле просто вывести hello world нельзя, функции printf и puts, отсутствуют, да и вообще у нас есть всего несколько функций, одна из них __asm__ которая делает вставку кода на асме, абсолютно все нужно делать самому, все что у нас есть это системные вызовы, все делается через них, linux имеет более трёхсот системных вызовов и exit среди них.
Короче все, навеселился.
Пошел отдыхать
.
Сексуальность валенка
Кстати кто сможет посчитать длину данной переменной: char *str string = "tratata"; без вызова любых функций?
Дам +5 в карму тому кто справится
.
The Fast, Secure and Professional - Yii2
# Swank (13.08.2015 / 02:41)
Кстати кто сможет посчитать длину данной переменной: char *str string = "tratata"; без вызова любых функций?
Дам +5 в карму тому кто справится
На php?
Всего: 9963