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ť.




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="">


Komentáre

Mark Zuckerberg chce spoplatniť Facebook

schusterr - 31.07.2010 04:17
ten Mark Zuckerberger je miliardar , ten uz moc lowe k zivotu nepotrebuje :)

Ako na zvonenie pre iPhone?

ByteLeak - 16.07.2010 10:39
Jednoducho si najdes priecinok zo zvoneniami (pravy klik na ten upraveny song, a Show in windows Explorer) ...

Ako na zvonenie pre iPhone?

andrea - 16.07.2010 08:16
nie som velmi technicky typ teda, ale zda sa mi to celkom logicke :) ale tak ci tak som natrafila na ...

Mark Zuckerberg chce spoplatniť Facebook

Baribylina - 04.07.2010 11:41
Či už je to pravda alebo nie..existuje mnoho podobných(i lepších)blogov, na ktore sa da bez problemov ...

Ako na zvonenie pre iPhone?

Lukáš - 11.06.2010 14:49
bohužial nemam tam takú možnosť create AAC version..
ByteLeak.com
Hore
38 queries in 0.478 seconds.