Warning
This page is located in archive.

Systémová volání a inline assembler

Cílem tohoto cvičení je detailně se seznámit s tím, jak aplikace volá služby operačního systému a jak lze systémová volání volat přímo, bez použití knihoven jako libc. Tato znalost se vám bude hodit v dalších cvičeních.

Domácí příprava

Seznamte se se základními instrukcemi architektury x86 a způsobem, jakým vkládat instrukce assembleru přímo do zdrojového kódu v jazyce C/C+ +. Projděte si tuto prezentaci a připomeňte si první a druhou přednášku.

Dále se seznamte s nástroji strace a ltrace. Doporučujeme si oba nástroje vyzkoušet na následujícím programu:

#include <stdio.h>
 
int main(int argc, char *argv[])
{
	printf("Hello world\n");
	return 0;
}

Pokud vás zajímají podrobnosti o kombinovaní assembleru a C, podívejte se do dokumentace překladače GCC. Mimo jiné tam najdete popisy obecných omezení a omezení závislých na architektuře CPU (hledejte sekci “x86 family”).

Zadání

Vytvořte program, který čte ze standardního vstupu celá nezáporná dekadická čísla oddělená mezerami nebo konci řádků a vypíše je na standardní výstup v hexadecimální podobě oddělená koncem řádku. Program nesmí používat žádnou standardní knihovnu jako např. libc. Předpokládejte, že maximální hodnota čísla bude 2^32-1.

Jinými slovy vytvořte program fungující podobně jako program níže, ale tak, aby šel přeložit s přepínači kompilátoru -nostdlib -nostdinc -static -m32 -Wall -g -O2.

#include <stdio.h>
 
int main()
{
	unsigned num;
	while (scanf("%u", &num) == 1)
		printf("0x%x\n", num);
	return 0;
}

Do BRUTE nahrávejte soubor hexconv.c se svou implementací.

Nápověda

  • Pro vyvolání služeb jádra potřebujete znát ABI (application binary interface) jádra OS. To se dočtete v man syscall v řádcích architektury i386.
  • Čísla jednotlivých systémových volání najdete v souboru /usr/include/asm/unistd_32.h.
  • Pozor! Jak ABI, tak čísla systémových volání se liší mezi 32- a 64-bitových jádrem. 64-bitové jádro je možné volat pomocí obou ABI, ale v této úloze používejte 32-bitové ABI, protože program je kompilován s přepínačem -m32.
  • Můžete vyjít z kódu níže, který již obsahuje náhradu funkce scanf.
  • Pro tisk i načítání můžete použít pole pevné délky např. 20 (maximální výstup má 8 hexadecimálních znaků).

#include <unistd.h> /* TODO: write your own system call wrappers for read, write, exit */
#include <stdio.h>  /* TODO: sprintf -- convert number to hex string */
#include <string.h> /* TODO: strlen -- length of output for write */
 
int isnum(char ch)
{
        return ch >= '0' && ch <= '9';
}
 
int isspc(char ch)
{
        return ch == ' ' || ch == '\n';
}
 
static void print(unsigned num)
{
        char buf[20];
        /* TODO: Get rid of sprintf() and strlen() */
        sprintf(buf, "0x%x\n", num);
        int ret = write(STDOUT_FILENO, buf, strlen(buf));
        if (ret == -1)
                _exit(1); // TODO your new exit
}
 
 
/* TODO: main() is called by libc. Real entry point is _start(). */
int main()
{
        char buf[20];
        unsigned num = 0;
        int i;
        int num_digits = 0;
        unsigned chars_in_buffer = 0;
 
        for (/* no init */; /* no end condition */; i++, chars_in_buffer--) {
                if (chars_in_buffer == 0) {
                        int ret = read(STDIN_FILENO, buf, sizeof(buf));
                        if (ret < 0)
                                return 1; // TODO replace by exit
                        i = 0;
                        chars_in_buffer = ret;
                }
                if (num_digits > 0 && (chars_in_buffer == 0 /* EOF */ || !isnum(buf[i]))) {
                        print(num);
                        num_digits = 0;
                        num = 0;
                }
                if (chars_in_buffer == 0 /* EOF */ || (!isspc(buf[i]) && !isnum(buf[i])))
                        return 0; // TODO: replace by exit
 
                if (isnum(buf[i])) {
                        num = num * 10 + buf[i] - '0';
                        num_digits++;
                }
        }
}

Materiály

courses/b4b35osy/cviceni/cviceni8_asm-syscalls.txt · Last modified: 2018/11/16 08:13 by sojkam1