Опубликован: 01.03.2016 | Уровень: для всех | Доступ: платный
Лекция 2:

Hello, world!

< Лекция 1 || Лекция 2 || Лекция 3 >

При изучении нового языка принято писать самой первой программу, выводящую на экран строку Hello, world!. Сейчас мы не ставим перед собой задачу понять всё написанное. Главное - посмотреть, как оформляются программы на ассемблере, и научиться их компилировать.

Вспомним, как вы писали Hello, world! на Си. Скорее всего, приблизительно так:


Вот только printf(3) - функция стандартной библиотеки Си, а не операционной системы. "Чем это плохо?" - спросите вы. Да, в общем, всё нормально, но, читая этот учебник, вы, вероятно, хотите узнать, что происходит "за кулисами" функций стандартной библиотеки на уровне взаимодействия с операционной системой. Это, конечно же, не значит, что из ассемблера нельзя вызывать функции библиотеки Си. Просто мы пойдём более низкоуровневым путём.

Как вы уже, наверное, знаете, стандартный вывод (stdout), в который выводит данные printf(3), является обычным файловым дескриптором, заранее открываемый операционной системой. Номер этого дескриптора - 1. Теперь нам на помощь придёт системный вызов write(2).

WRITE(2)        Руководство программиста Linux        WRITE(2)

ИМЯ
        write - писать в файловый дескриптор
ОБЗОР
        #include <unistd.h>

        ssize_t write(int fd, const void *buf, size_t count);
ОПИСАНИЕ
        write пишет count байт в файл, на который ссылается файловый

дескриптор fd, из буфера, на который указывает buf.

А вот и сама программа:


Почему sizeof(str) - 1? Потому, что строка в Си заканчивается нулевым байтом, а его нам печатать не нужно.

Теперь скопируйте следующий текст в файл hello.s. Файлы исходного кода на ассемблере имеют расширение .s.

.data                         /* поместить следующее в сегмент данных
                                                                    */
 
hello_str:                    /* наша строка                        */
        .string "Hello, world!\n"
 
                              /* длина строки                       */
        .set hello_str_length, . - hello_str - 1
 
.text                         /* поместить следующее в сегмент кода */
 
.globl  main                  /* main - глобальный символ, видимый
                                 за пределами текущего файла        */
.type   main, @function       /* main - функция (а не данные)       */
 
 
main:
        movl    $4, %eax      /* поместить номер системного вызова
                                 write = 4 в регистр %eax           */
 
        movl    $1, %ebx      /* первый параметр - в регистр %ebx;
                                 номер файлового дескриптора 
                                 stdout - 1                         */
 
        movl    $hello_str, %ecx  /* второй параметр - в регистр %ecx;
                                     указатель на строку            */
 
        movl    $hello_str_length, %edx /* третий параметр - в регистр
                                           %edx; длина строки       */
 
        int     $0x80         /* вызвать прерывание 0x80            */
 
        movl    $1, %eax      /* номер системного вызова exit - 1   */
        movl    $0, %ebx      /* передать 0 как значение параметра  */
        int     $0x80         /* вызвать exit(0)                    */
 
        .size   main, . - main    /* размер функции main            */

Напомним, сейчас наша задача - скомпилировать первую программу. Подробное объяснение этого кода будет потом.

[user@host:~]$ gcc hello.s -o hello
[user@host:~]$

Если компиляция проходит успешно, GCC ничего не выводит на экран. Кроме компиляции, GCC автоматически выполняет и компоновку, как и при компиляции программ на C. Теперь запускаем нашу программу и убеждаемся, что она корректно завершилась с кодом возврата 0.

[user@host:~]$ ./hello
Hello, world!
[user@host:~]$ echo $?
0

Теперь было бы хорошо прочитать последнюю лекцию про отладчик. Он вам понадобится для исследования работы ваших программ. Возможно, сейчас вы не всё поймёте, но эта лекция специально расположена в конце, так как задумана больше как справочная, нежели обучающая. Для того, чтобы научиться работать с отладчиком, с ним нужно просто работать.

< Лекция 1 || Лекция 2 || Лекция 3 >
Константин Белюстин
Константин Белюстин
Украина, г. Киев
Максим Барашков
Максим Барашков
Россия, Якутск