twitter facebook

Programovanie v assemblery pre procesory x86 pod linuxom #1

asmV tomto článku sa budeme venovať programovaniu v assemblery pre procesory x86 kompatibilné. Článok bude rozdelený na 2 časti. V prvej bude popísané systémové volanie a v druhom si ukážeme ako prepojovať assembler s vyšším programovacím jazykom, konkrétne jazykom C.
Ako kompilátor som sa rozhodol použit NASM (Netwide ASM) je rozšírený ako medzi linuxovými užívateľmi tak medzi užívateľmi windowsu. Používa intel syntax ktorá mi príde prehľadnejšia ako tá AT&T ktorú používa napríklad GAS, taktiež má bohatú podporu makier ktoré sa veľmi podobaju tým z gcc. A nakoniec ako objektový formát si zvolíme ELF (Executable Linked Format) ktorý je pod týmto systémom najpoužívanejší

Systémové volanie

Ak máme potrebné hodnoty uložené v daných registroch môžeme zavolat prerušenie. Prerušenie na volanie systému ma v linuxe číslo 0×80.
Čísla všetkých systémových volaní môžeme nájst v súbore /usr/include/asm/unistd.h na niektorých systémoch to môže byť aj /usr/include/asm/unistd_32.h.

Ako to teda vlastne vyzerá:


vl4kn0@cybernode /usr/include/asm $ cat unistd_32.h
#ifndef _ASM_X86_UNISTD_32_H
#define _ASM_X86_UNISTD_32_H

/*
* This file contains the system call numbers.
*/

#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
...

tých volaní je tam samozrejme viac (okolo 334). Aké číslo budeme potrebovať zistíme ak od mena konštanty odstraníme prefix __NR_ čize napríklad na vypnutie programu zavolám __NR_exit ktoré ako vidíme má číslo jedna.
Aby sme zistili aké preberá argumenty zavoláme na pomoc man

man 2 exit

Dostaneme manuálovú stránku k tomuto volaniu a zameriame sa na konkrétne túto časť:

NAME
_exit, _Exit - terminate the calling process

SYNOPSIS
#include <unistd.h>
void _exit(int status);

Ako vidíme máme tu krátky popis funkcie a definíciu. void _exit(int status); tu vidíme, že nevracia žiadnu hodnotu a preberá ako parameter status ukončenia programu.
Krátky príklad:

section .text
global _start

_start:
mov eax,1 ; ulozime cislo volania (exit)
mov ebx,0 ; ulozime status
int 0x80 ; zavolame prerusenie operacneho systemu

Tento príklad nespraví nič iné ako to, že sa vypne. Pre doplnenie dodám, že global _start sa dava na to aby linker (ld) vedel kde program začína.
Na to aby sme to skompilovali to zapíšeme do súboru napríklad example.asm a skompilujeme príkazom:

nasm -f elf -o example.o example.asm

prepínačom -f povieme nasm, že ide o formát elf a prepínačom -o hovoríme aký názov bude mať výstupný súbor.
vsetko co treba urobit teraz je program nalinkovat to urobíme programom ld:

ld -o example example.o

Tak to je všetko, máme spustiteľný súbor ktorý nerobí vôbec nič.

Teraz ked vieme čo a ako ukážme si pár príkladov. Čo by sme boli za tutoriál keby sme tu nemali “Hello world” príklad. Podme sa naňho pozriet bližšie.
Ako vieme v linuxe rozlisujeme 3 základné súbory: stdin, stdout, stderr. Tieto súbory sú väčšinou nalinkované do práve otvoreného terminálu. Vidieť to môžeme tu:

cybernode ~ # ls -l /dev | grep std
lrwxrwxrwx. 1 root root 15 2009-08-05 13:08 stderr -> /proc/self/fd/2
lrwxrwxrwx. 1 root root 15 2009-08-05 13:08 stdin -> /proc/self/fd/0
lrwxrwxrwx. 1 root root 15 2009-08-05 13:08 stdout -> /proc/self/fd/1|

Ako vidíme každý z týchto súborov je link. Keď sa pozrieme čo sa za tým linkom skrýva:

cybernode ~ # ls -l /proc/self/fd/0
lrwx------. 1 root root 64 2009-08-05 23:39 /proc/self/fd/0 -> /dev/pts/0

tento náš súbor ukazuje na práve otvorený terminál. Ale to bola len omáčka naokolo. Takže keď to zhrnieme. Každý otvorený súbor v linuxe má svoje ID. Toto ID je doležíté na rozoznávanie súborov s ktorýmy pracujeme. Je dôležité si zapamätať, že ID 0,1,2 sú vyhradené pre stdin, stdout, stderr.
Stdin má ID 0 a je to štandardný vstup. Používať ho budeme najmä na vstup z klávesnice. Stdout má ID 1 a budeme ho používať na výstup na obrazovku a stderror má ID 2 a budeme ho používať na vypisovanie chybových správ.

Omáčka je za nami poďme sa pozrieť na náš hello world príklad:
Program bude postupovať takto:
načítame premenné, zavoláme systémové volanie write, zistíme veľkost premennej a vypíšeme na obrazovku. Nakoniec zavoláme systémové volanie exit. Zistíme teda niečo o systémovom volaní exit:

cybernode ~ # cat /usr/include/asm/unistd_32.h | grep write
#define __NR_write 4

Vidíme teda, že write má číslo 4. Dalej zistíme niečo o parametroch:

cybernode ~ # man 2 write
...
NAME
write - write to a file descriptor

SYNOPSIS
#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);
...

Parametre teda budú ID súboru kam chceme premennú zapísať, v našom prípade to bude 1(stdout). Druhý parameter bude adresa premennej, a posledný bude veľkosť. Podme sa teda pozrieť na hotový príklad:

section .data
hello db "Hello world",0xa,0x0 ; Premenna s textom hello world zakoncena novym riadkom a nulovym znakom
len equ $ - hello ; dlzka nasho retazca, znak $ znamena aktualnu adresu

section .text
global _start

_start:
mov eax,4 ; cislo systemoveho volania
mov ebx,1 ; prvy parameter: id suboru
mov ecx,hello ; adresa prveho znaku retazca
mov edx,len ; dlzka retazca
int 0x80 ; zavolame prerusenie nech sa o to postara system

mov eax,1 ; zavolame exit
mov ebx,0 ; ktory prebera ako parameter status
int 0x80 ; zavolame system

uložíme do súboru hello.asm a skompilujeme pomocou prikazov:

nasm -f elf -o hello.o hello.asm

zlinkujeme

ld -o hello hello.o

spustíme:

cybernode ~ # ./hello
Hello world
cybernode ~#

Toto bude zatial všetko. V dalšej časti si povieme o linkovaní C a asm. Ak sa vám článok páčil napíšte to do komentárov, ak nie napíšte čo by ste chceli zmeniť.

Zdieľaj:
  • Print
  • email
  • vybrali.sme.sk
  • Linkuj.cz!
  • Jaggni to!
  • Pozrisi.sk
  • Top Články.cz
  • MediaBlog.cz
  • Blogus.cz
  • Bookmarky.cz
  • Google Bookmarks
  • MojeLinky.sk
  • TOPodkazy.cz
  • Park.sk
  • MySpace
  • Twitter
  • Facebook



2 Odpovedí v “Programovanie v assemblery pre procesory x86 pod linuxom #1”

Si ty ale sikula, len tak dalej. Skoda, ze uz mi to nic nehovori, assembler som neusoval uz nejaky ten piatok.

 
 
 

* Email nebude nikde uverejnený.


Pravidlá: Tie su jednoduché, vyhni sa invektívam a spamovaniu, a môžeš si byť istý, že tvoj komentár tu zostane. Tu si tykáme.

Môžeš použiť tieto tagy: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">


Chceš sa zaregistrovať, alebo si stratil heslo?

Komentáre

Úvod do Cydie

ByteLeak - pred 11 minutami
To zalezi od repozitara, ktory chces pridat.. napriklad http://cydia.hackulo.us

Úvod do Cydie

nejde to - pred 16 minutami
Vyplníme adresu a po potvrdení sa nám overí repozitár. Ak je všetko v poriadku, počkáme kým ...

Obnovenie starého facebooku? Nie je problém!

ByteLeak - 10.11.2009 23:04
@J1mmy vzdy lepsie facebook ako azet :) ano uz ani facebook nie je to co na zaciatku, ked tam boli LEN ...

Obnovenie starého facebooku? Nie je problém!

J1mmy - 10.11.2009 21:41
ja facebook nemam a asi ani mat nebudem,cize je mi to jedno :D ps:"socialna siet pre socialne pripady", ...

Obnovenie starého facebooku? Nie je problém!

ByteLeak - 03.11.2009 14:32
@Midnite najidealnejsie riesenie je mat pomaly Firefox, v nom GreaseMonkey a povyhadzovat si z Live ...
ByteLeak.com
Hore
16 queries in 0.563 seconds.