quinta-feira, 22 de outubro de 2015

GTK & PostgreSQL usando C

Vamos Criar uma tela de Login, para tal precisamos de algumas dependências para começar o jogo...

Procure pelas Bibliotecas: libpq-fe, gtk-+3

No caso de estiver usando o Debian entre como root no terminal e Execute:

apt-get install libpq-dev libgtk-3-dev
Para que possamos Testar recomendo a Instalação dos:

apt-get install postgesql pgadmin3
                             ________________________________________


Vamos começar com a GUI do Software.

crie um arquivo teste.c  e adicione os códigos a seguir:
Verificamos se as Bibliotecas foram encontradas.

                             ________________________________________
#include <gtk/gtk.h>
#include <libpq-fe.h>
#include <string.h>
int
main(int argc, char **argv){
    return 0;
}

                             ________________________________________

Crie o Arquivo Makefile que vai ser utilizado para compilar.

FileC = teste
CC = gcc
pgFalgs = -I /usr/include/postgresql -lpq
CFlags = `pkg-config --cflags --libs gtk+-3.0`



all:$(FileC)

$(FileC):$(FileC).o
$(CC) $(FileC).o -o $(FileC) $(CFlags) $(pgFalgs)

$(FileC).o:$(FileC).c
$(CC) -c $(FileC).c $(CFlags) $(pgFalgs)
@echo "O Arquivo $(FileC).o está Pronto"

clean:
rm $(FileC) $(FileC).o

run:$(FileC)
./$(FileC)


 ________________________________________

Para Compilar e rodar abra o terminal na Pasta no arquivo teste.c e Makefile, e rode o comando

$    make run

Agora vamos criar a janela em GTK.

 ________________________________________
/*Arquivo teste.c*/

#include <gtk/gtk.h>
#include <libpq-fe.h>
#include <string.h>

GtkWidget* window;

static void
activate (GtkApplication *app, gpointer user_data){
    /* Construimos a Janela */
    window = gtk_application_window_new (app);
    gtk_window_set_title(GTK_WINDOW(window), "Tela de Login");
    gtk_window_set_default_size (GTK_WINDOW (window), 100, 100);
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

    gtk_widget_show_all (window);//mostramos tudo que esta na janela

}

int
main(int argc, char **argv){
    GtkApplication *app;
    int status;
    app = gtk_application_new ("login.teste", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);
    return status;
}


 ________________________________________

O código acima ira criar uma janela, com o titulo "Tela de Login", do tamanho 100x100.
Agora vamos inserir o resto dos componentes a GUI.



 ________________________________________
/*Arquivo teste.c*/

#include <gtk/gtk.h>
#include <libpq-fe.h>
#include <string.h>

GtkWidget* window;
static GtkWidget
    *password_entry,
    *user_entry;
static void
activate (GtkApplication *app, gpointer user_data){
    GtkWidget *button, *combo_db;
    GtkWidget *conteudo, *conteudo1, *conteudo2;
    GtkWidget *label_user, *label_password;
    /* Construimos a Janela */
    window = gtk_application_window_new (app);
    gtk_window_set_title(GTK_WINDOW(window), "Tela de Login");
    gtk_window_set_default_size (GTK_WINDOW (window), 100, 100);
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

    // Container Principal
    conteudo=gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_container_add(GTK_CONTAINER(window), conteudo);

    // Area Do Banco de Dados
    combo_db = gtk_combo_box_text_new ();
    gtk_widget_set_tooltip_text(combo_db, "Banco de Dados.");
 
    gtk_combo_box_set_active (GTK_COMBO_BOX (combo_db), 0);
    gtk_container_add(GTK_CONTAINER(conteudo), combo_db);
 
    // Area do Usuario
    conteudo1=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_container_add(GTK_CONTAINER(conteudo), conteudo1);
    label_user = gtk_label_new("Usuario: ");
    gtk_box_pack_start(GTK_BOX(conteudo1), label_user, FALSE, FALSE, 5);
 
    user_entry=gtk_entry_new();
    gtk_widget_set_tooltip_text(user_entry, "Usuario do Sistema.");
    gtk_entry_set_placeholder_text(GTK_ENTRY(user_entry), "Usuario");
    gtk_box_pack_start(GTK_BOX(conteudo1), user_entry, FALSE, FALSE, 2);
 
    // Area da Senha
    conteudo2=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_container_add(GTK_CONTAINER(conteudo), conteudo2);
    label_password = gtk_label_new("Senha: ");
    gtk_box_pack_start(GTK_BOX(conteudo2), label_password, FALSE, FALSE, 5);
 
    password_entry=gtk_entry_new();
    gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE);
    gtk_widget_set_tooltip_text(password_entry, "Senha do Usuario do Sistema.");
    gtk_entry_set_placeholder_text(GTK_ENTRY(password_entry), "Senha");
    gtk_box_pack_start(GTK_BOX(conteudo2), password_entry, FALSE, FALSE, 14);
 
    // Inserir Botão
    button = gtk_button_new_with_label("Entrar");

    gtk_container_add(GTK_CONTAINER(conteudo), button);
    gtk_widget_show_all (window);//mostramos tudo que esta na janela

}

int
main(int argc, char **argv){
    GtkApplication *app;
    int status;
    app = gtk_application_new ("login.teste", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);
    return status;
}


 ________________________________________


Agora Vamos Inserir os métodos e Funções SQL.



 ________________________________________
/*Arquivo teste.c*/

#include <gtk/gtk.h>
#include <libpq-fe.h>
#include <string.h>
typedef char* String;
/*Objeto de conexão*/
static PGconn *conn = NULL;
/*Ponteiro de resultado*/
static PGresult *result;

static GtkWidget
    *password_entry,
    *user_entry;

GtkWidget* window;
static void
MsgBox(String txt, GtkWindow *window);

int
conexao(String dbName){
    String pghost="localhost",
           pgport="5432",
           pgoptions=NULL,
           pgtty=NULL,
           login="",
           pwd="";
    if (!dbName)
        dbName = "postgres";
    conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, login, pwd);
    if(PQstatus(conn) == CONNECTION_OK){
        printf("Conexão efetuada com sucesso.\n");
    }else{
        printf("Falha na conexão. Erro: %s\n", PQerrorMessage(conn));
        PQfinish(conn);
        return 1;
    }
    return 0;
}

void
exit_conexao(){
    /*Libera o nosso objeto*/
    if (result)
        PQclear(result);
    /*Verifica se a conexão está aberta e a encerra*/
    if(conn != NULL)
        PQfinish(conn);
}

static void
complet_combo_db(GtkWidget *combo_box){
    if (conexao(NULL))
        return;
    /*Executa o comando*/
    result = PQexec(conn, "select datname from pg_database where datistemplate=False;");
 
    if(!result)
    {
        printf("Erro executando comando. ");
    }
    else
    {
        switch(PQresultStatus(result))
        {
            case PGRES_EMPTY_QUERY:
                printf("Nada aconteceu.\n");
                break;
            case PGRES_TUPLES_OK:
                printf("A query retornou %d linhas.\n", PQntuples(result));
                break;
            case PGRES_FATAL_ERROR:
                printf("Erro na Consulta: %s\n", PQresultErrorMessage(result));
                break;
            case PGRES_COMMAND_OK:
                printf("%s linhas afetadas.\n", PQcmdTuples(result));
                break;
            default:
                printf("Algum outro resultado ocorreu.\n");
                break;
        }
    }
 
    /* Pegamos a Quantidade de campos capturados */
    int campos = PQnfields(result);
    int count  = PQntuples(result);
 
    int i,j;
    for(i = 0; i < count; i++)
    {
        // Percorre todas as colunas
        for (j = 0; j < campos; j++)
        {
            // Imprime o valor do campo
            gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo_box), PQgetvalue(result, i, j));
        }
    }
    return exit_conexao();
}

static void
login_action (GtkButton *button,
                gpointer   user_data)
{
    const char *paramValues[2];
 
    int status_conn;
    String senha, usuario;
    senha   = (String) gtk_entry_get_text( GTK_ENTRY( password_entry ) );
    usuario = (String) gtk_entry_get_text( GTK_ENTRY( user_entry     ) );
    /* Verificamos se os campos Login e Senha estão preenchidos */
    if ( strcmp( usuario, "" ) == 0){
        MsgBox("O Campo Usuario Não foi Preenchido...", GTK_WINDOW(window));
        return;
    }
 
    if ( strcmp( senha, "" ) == 0){
        MsgBox("O Campo Senha Não foi Preenchido...", GTK_WINDOW(window));
        return;
    }
 
    /* Agora Abrimos a conexao */
    String dbName = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT(user_data));
    if (conexao(dbName))
        return;
 
    /*Executa o comando*/
    paramValues[0] = usuario;
    paramValues[1] = senha;

    result = PQexecParams(conn,
                       "SELECT count(*) FROM users WHERE login = $1",
                       1,       /* one param */
                       NULL,    /* let the backend deduce param type */
                       paramValues,
                       NULL,    /* don't need param lengths since text */
                       NULL,    /* default to all text params */
                       0);      /* ask for binary results */
    if (PQresultStatus(result) != PGRES_TUPLES_OK)
    {
        printf( "SELECT Falho: %s", PQerrorMessage(conn));
        exit_conexao();
        printf("O sistema Não Foi Instado na Base: %s\n",dbName);
        return;
    }
 
    /* Verificamos se o User Existe*/
    int num_records, i;
    num_records = PQntuples(result);
    for(i = 0 ; i < num_records ; i++)
    {
        if (strcmp(PQgetvalue(result, i, 0),"0" ) == 0){
            MsgBox("Usuario Não existe...", GTK_WINDOW(window));
            exit_conexao();
            return;
        }
    }
 
    /* Verificamos a Senha do Usuario */
    result = PQexecParams(conn,
                       "SELECT count(*) FROM users WHERE login = $1 and password = $2",
                       2,       /* two param */
                       NULL,    /* let the backend deduce param type */
                       paramValues,
                       NULL,    /* don't need param lengths since text */
                       NULL,    /* default to all text params */
                       0);      /* ask for binary results */
    if (PQresultStatus(result) != PGRES_TUPLES_OK)
    {
        printf( "SELECT failed: %s", PQerrorMessage(conn));
        exit_conexao();
    }
    num_records = PQntuples(result);
    for(i = 0 ; i < num_records ; i++)
    {
        if (strcmp(PQgetvalue(result, i, 0),"0" ) == 0){
            MsgBox("Senha Errada...", GTK_WINDOW(window));
            exit_conexao();
            return;
        }
    }
    exit_conexao();
}

static void
activate (GtkApplication *app, gpointer user_data){
    GtkWidget *button, *combo_db;
    GtkWidget *conteudo, *conteudo1, *conteudo2;
    GtkWidget *label_user, *label_password;
    /* Construimos a Janela */
    window = gtk_application_window_new (app);
    gtk_window_set_title(GTK_WINDOW(window), "Tela de Login");
    gtk_window_set_default_size (GTK_WINDOW (window), 100, 100);
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);

    // Container Principal
    conteudo=gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_container_add(GTK_CONTAINER(window), conteudo);

    // Area Do Banco de Dados
    combo_db = gtk_combo_box_text_new ();
    gtk_widget_set_tooltip_text(combo_db, "Banco de Dados.");
    complet_combo_db(combo_db);// o Encarregado de Preencher o ComboBox
    gtk_combo_box_set_active (GTK_COMBO_BOX (combo_db), 0);
    gtk_container_add(GTK_CONTAINER(conteudo), combo_db);
 
    // Area do Usuario
    conteudo1=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_container_add(GTK_CONTAINER(conteudo), conteudo1);
    label_user = gtk_label_new("Usuario: ");
    gtk_box_pack_start(GTK_BOX(conteudo1), label_user, FALSE, FALSE, 5);
 
    user_entry=gtk_entry_new();
    gtk_widget_set_tooltip_text(user_entry, "Usuario do Sistema.");
    gtk_entry_set_placeholder_text(GTK_ENTRY(user_entry), "Usuario");
    gtk_box_pack_start(GTK_BOX(conteudo1), user_entry, FALSE, FALSE, 2);
 
    // Area da Senha
    conteudo2=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_container_add(GTK_CONTAINER(conteudo), conteudo2);
    label_password = gtk_label_new("Senha: ");
    gtk_box_pack_start(GTK_BOX(conteudo2), label_password, FALSE, FALSE, 5);
 
    password_entry=gtk_entry_new();
    gtk_entry_set_visibility(GTK_ENTRY(password_entry), FALSE);
    gtk_widget_set_tooltip_text(password_entry, "Senha do Usuario do Sistema.");
    gtk_entry_set_placeholder_text(GTK_ENTRY(password_entry), "Senha");
    gtk_box_pack_start(GTK_BOX(conteudo2), password_entry, FALSE, FALSE, 14);
 
    // Inserir Botão
    button = gtk_button_new_with_label("Entrar");
    g_signal_connect (GTK_BUTTON (button),
                    "clicked",
                    G_CALLBACK (login_action),
                    G_OBJECT (combo_db));
    gtk_container_add(GTK_CONTAINER(conteudo), button);
    gtk_widget_show_all (window);//mostramos tudo que esta na janela

}

int
main(int argc, char **argv){
    GtkApplication *app;
    int status;
    app = gtk_application_new ("login.teste", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
    status = g_application_run (G_APPLICATION (app), argc, argv);
    g_object_unref (app);
    return status;
}

static void
on_response (GtkDialog *dialog,
             gint       response_id,
             gpointer   user_data){
  gtk_widget_destroy (GTK_WIDGET (dialog));
}

static void
MsgBox(String txt, GtkWindow *window){
    g_print("%s\n",txt);
    GtkWidget *dialog;
    GtkWidget *content_area;
    GtkWidget *label;

    gint response_id;

    dialog = gtk_dialog_new_with_buttons ("Aviso...",
                                        window,
                                        GTK_DIALOG_MODAL,
                                        GTK_STOCK_OK,
                                        GTK_RESPONSE_OK,
                                        NULL);

    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
    label = gtk_label_new (txt);
    gtk_container_add (GTK_CONTAINER (content_area), label);
    gtk_widget_show_all (dialog);
    g_signal_connect (GTK_DIALOG (dialog),
                    "response",
                    G_CALLBACK (on_response),
                    NULL);
}
 ________________________________________




Para concluir a brincadeira você precisa criar no PostgreSQL a Tabelas users, com os campos login e password, os dois do tipo varchar.

sábado, 4 de julho de 2015

Nova Versão do SteamOS 2.0 "Brewmaster" Beta


    A Nova Versão do SteamOS de codinome "Brewmaster" e com base na mais recente versão estável do Debian 8.1

Para baixar o SteamOS 2.0 Brewmaster

Brewmaster
Brewmaste

A Anterior versão do SteamOS 1.0 é a "Alchemist".

Para Download do SteamOS 1.0 Alchemist

Alchemist

quarta-feira, 20 de maio de 2015

SteamOS o Sistema Operacional para Jogos


SteamOS GNU/Linux

Atualmente, Data:"20/05/2015" SteamOS tem suporte a mais de 2.000 jogos.
Alguns Desenvolvedores ainda usam tecnologias que amarram os jogos ao Windows - como é o caso dos jogos que usam o DirectX ou Direct3D. Para quebrar esse paradigma é que a Valve está investindo no SDL e a próxima geração da API OpenGL, a "Vulkan", para ajudar a aumentar o padrão dos jogos multiplataforma, já que o OpenGL roda em todas As Plataformas.

SteamOS Download  -   OpenVR:

Requisitos SteamOS
   



SteamVR


SteamVR - Steam ControllerSteam Machine

 

 

C/C++ In SteamOS

Primeiro vamos precisar instalar o GCC assim:

1. Abra o terminal
2. Instalar o GCC
    $ sudo apt-get install gcc g++

Logo após iremos criar o arquivo e iserir o codigo:

1. Utilizaremos o Nano para criar e salvar o arquivo teste02.cpp
    $ nano teste02.cpp

2. Insira o Codigo:
#include <iostream>
using namespace std;
class Time {
    public:
        Time();
        int x;
    private:
        int y;
    protected:
        int z;
};
Time::Time(){ x = 0; }
int main(){
    Time t;
    cout<<"Valor x: ";
    t.x = 12;
    cout<<""<<t.x<<endl;
    return 0;
}
<Ctrl+o> para salvar, <Ctrl+x> para sair



3. Para Compilar:
    $ g++ teste02.cpp -o teste02
4. executar:
    $ ./teste02



sábado, 2 de maio de 2015

Assembly No GNU/Linux

     Assembly é uma Linguagem mais próximo do hardware, por isso é dito ser uma linguagem de baixo nível.


Softwares de alto nível:


    Aqui é onde está a maioria dos usuários de computadores, tipicamente lidando com aplicações gráficas, clicando em botões, menus, minimizando, maximizando, fechando janelas, navegando na web e outras infinidades de coisas.
     Nesse estágio, as coisas são bem simples e voltadas para o usuário leigo.
Não é necessário saber absolutamente nada sobre o funcionamento interno dos sistemas. E, de fato, a grande maioria dos usuários não sabe.
     Para o usuário, é tudo a mesma coisa, não importa se ele esteja no Windows, MacOS, Linux, Android ou TV Digital: ele quer ver menus, botões, clicar, arrastar, fechar e o mesmo de sempre.
    Uma mera tela preta Terminal do Linux, já seria motivo de espanto e repúdio.
     A grande maioria das pessoas não tem motivos para entender o que se passa por debaixo dos panos desses Software.

Softwares de baixo nível:

    Linguagem de programação de baixo nível trata-se de uma linguagem de programação que compreende as características da arquitetura do computador. Assim, utiliza somente instruções do processador, para isso é necessário conhecer os registradores da máquina. Nesse sentido, as linguagens de baixo nível estão diretamente relacionadas com a arquitetura do computador
    Para programar em Assembly precisamos saber que tipo de arquitetura vamos trabalhar.
    
     Isso porque os comandos e códigos da linguagem Assembly são diferentes e específicos para cada tipo de processador. Ou seja, o nível de abstração da camada da linguagem Assembly é dependente do sistema.
É tão dependente que até precisamos saber como é organizada e o funcionamento da memória da máquina onde vamos programar.

A camada do código de máquina

     Você já deve ter ouvido falar que tudo, absolutamente tudo, em computação, é feito de números 1 e 0. E isso é verdade.
O computador (no sentido bem baixo da palavra, ou seja, o metal, as peças eletrônicas) só entende e obedece a esses comandos, que nada mais são que uma série de números binários (1’s e 0’s). Porém, quantas vezes você já programou ou ouviu falar de alguém que programa em binário?
     O objetivo da linguagem Assembly é suprir esse problema da alta complexidade do binário.
     Com o Assembly escrevemos de uma maneira mais ‘humana’, mais fácil e compreensível, e esse código é convertido para o código de máquina.
     Esse é o limite dos programadores. Porém, há muito, mas muito mais abaixo do Assembly, que envolvem coisas de elétrica e eletrônica digital (latches, flip-flops, transistores, circuitos integrados etc).

Assembly é eficiente:

     Se você mandar duas pessoas, equipes ou empresas, fazerem os mesmos softwares, verá que é impossível o código delas serem iguais. Programar é raciocinar, é criatividade, depende do intelecto, experiência e raciocínio dos programadores e chefes.
     É por isso que existem navegadores Web bons e ruins, Sistemas Operacionais lentos e rápidos, jogos bem feitos e mal feitos etc.
     Isso tudo é eficiência: fazer um programa que rode mais rápido, que consuma pouco processamento ou que exija o mínimo de memória possível. E isso o Assembly é único.
Um programa bem feito em Assembly é simplesmente imbatível.
  Não é à toa que é Assembly é uma linguagem muito usada em situações críticas, como em alguns trechos da construção de sistemas operacionais, como o Linux (em sua grande parte é feito em C, mas em algumas partes é necessário usar Assembly).

Compilador Assembly:

Você precisa Instalar o nasm pela sua Central de Aplicativos.
Instalar Nasm Para o Ubuntu ou Debian (Com software-center instalado)



Código do Hello World em Assembly:

   Crie um arquivo de texto com o nome "hello.asm" e escreve o seguinte código dentro dele:


section .data
  msg     db      'Olá Mundo', 0AH
  len     equ     $-msg ; Tamanho da string hello
 
section .text
  global  _start
_start: mov     edx, len ; Argumento que indica o tamanho da string
        mov     ecx, msg ; Argumento que indica o endereço da string
        mov     ebx, 1 ; Argumento que indica modo de escrita
        mov     eax, 4 ; Interrupção de escrita (sys_write)
        int     80h ; Chamada da interrupção
 
        mov     ebx, 0  ; Argumento da interrupção
        mov     eax, 1 ; Interrupção exit (sys_exit)
        int     80h ; Chamada da interrupção






Caso seja 32 bits, vá no diretório do hello.asm e digite o seguinte código no terminal:
    $ nasm -f elf32 hello.asm

Caso seja 64 bits, digite:
    $ nasm -f elf64 hello.asm

Se você notar bem, foi criado um arquivo com extensão .o, é o hello.o

    $ ld hello.o -o hello
    $ ./hello



Sections & _start:


    Quando um executável vai rodar, ele precisa saber a partir de onde, no código, ele começa a rodar.

    Em programação, começar do começo não é algo comum.
   Tendo em vista esses dados sobre a informação da ordem das coisas em um código, vamos falar neste tutorial de Assembly sobre as seções (sections) de um arquivo-fonte em Assembly.


Deixando seu código organizado

    Programas feitos na linguagem de baixo nível Assembly tem uma características em comum: eles são grandes.

    Sim, programar em Assembly é escrever bastante, pois é uma linguagem totalmente crua, onde muito pouco 'existe' e muito, quase tudo, é necessário criar.
   Para se fazer um simples programa de cálculos matemáticos simples (somar, subtrair etc) é necessário que fazer uma rotina, manualmente, para essa tarefa, usando somente as instruções nativas do processador.

    Em linguagens de alto nível, como C e Java, isso já vem totalmente pronto.
    Não é necessário criar nada, somente utilizar.

    Então, mais que todas as outras linguagens, é necessário ter organização para programar em Assembly. Seu código deve ser legível, organizado e comentado.

    Visando essa organização, existe um comando (ou simplesmente rótulo, ou marcador) chamado section, que serve para definirmos seções em nosso código.
Para declarar uma section fazemos:

section .nomeDaSecao


Como dividir um código Assembly: .data, .bss e .text

    De uma maneira geral, os programadores Assembly utilizam três sections para organizar seus códigos. Seguir esses passos é interessante, visto que fará com que seus programas sejam organizados da maneira padrão, da maneira que é universalmente usada.

    Na .data section, como o nome sugere, é uma região do código que será usada para tratar as informações, os dados, as variáveis.
Nesse trecho (geralmente o inicial), declaramos e inicializamos as variáveis.

    Fazemos algo parecido na .bss section, porém não inicializamos as informações.

    Por fim, a .text section é o local onde irá ficar armazenado suas instruções, que irão trabalhar com os dados previamente declarados.
    Essa é a única seção obrigatória, pois conterá a label (rótulo) _start, que é o local onde os executáveis são inicializados.

    Se já estudou C, C++ ou Java, por exemplo, a _start seria o main().
Logo, o esqueleto dos códigos em Assembly é:

section .dat
  ;declaração e inicialização de dados
 
section .bss
  ;declaração sem inicialização das informações que serão usadas
 
section .text
  ;o programa começa a rodar aqui, a partir da _start

Se comunicando com o mundo externo: global

    Como as memórias e processadores estão ficando cada vez mais modernos e maiores (em relação ao tamanho da memória), está possível, cada vez mais, usar linguagens de alto nível (principalmente o C), para tarefas que eram feitas exclusivamente em Assembly.

    Uma prova disso é o sistema operacional Linux, onde sua gigantesca parte é feita em C, com algumas pitadas em Assembly.
    Essa pitada de Assembly no Kernel é justamente na parte que é necessária uma maior eficiência da máquina, pois como sabemos, em termos de eficiência nenhuma outra linguagem bate nossa amada linguagem.

    Por isso, é bem comum a interação entre Assembly e outras linguagens. Um exemplo disso são os games de alto desempenho, que possuem rotinas feitas em Assembly, que se comunica com o resto do programa.

    Uma maneira de fazer essa interação é através da diretiva (explicaremos o que é isso em breve) global.
    A diretiva global mostra que o label relacionado é global, ou seja, é passível de uso externamente.
    Geralmente usamos para declarar o label principal, o _start.

Portanto, o nosso esqueleto de código será:



section .dat
  ;declaração e inicialização de dados
 
section .bss
  ;declaração sem inicialização das informações que serão usadas
 
section .text
global _start
 
_start:
  ;o programa começa a rodar aqui, a partir daqui

O que é e como usar um Label (rótulo) em Assembly:

     A tradução de label é 'rótulo', é uma nomenclatura que damos para dar nome a um trecho de código em Assembly.


    O label, por exemplo, serve (como o nome diz) para rotular, nomear uma seção do código, para que possamos definir uma região do código através de um rótulo, de um nome que quisermos.

     Para criar uma label, basta digitar o nome desse rótulo seguido de dois pontos, ' : '.
     Em seguida, escrevemos nossas linhas de código em Assembly.

A sintaxe é a seguinte, então:


label:
 ;aqui vem o código
 ;que vai ser nomeado
 ;de 'label'


     Imagine que você criou uma rotina de códigos, suponha que você criou um trecho de código que vai repetir várias vezes durante seu programa em Assembly.  Ou seja, esse código se repete, você vai usar mais de uma vez.

Vamos então criar um label chamado 'rotinaBase'.


rotinaBase:
  ;código


     O que o label faz é nomear essa porção de linhas de código.
Para executar elas, em vez de escrever todas elas de novo em outra parte, você apenas se refere a "rotinaBase", e o trecho de código que você usou abaixo da label 'rotinaBase' será executado.

    Lembrando que a linguagem Assembly está em baixo nível, ela sempre trata tudo em relação aos endereços na memória.Os labels estão intrinsecamente ligados com endereços de memória.

    Um label serve para representar o endereço de um determinado trecho no código (ou para inicializar variáveis e constantes que podem ter seus endereços realocados).
Assim, se usarmos esse trecho de código várias vezes, em vez de repeti-lo basta voltar ao ponto (endereço) na memória que tem esses códigos.

     Porém, é complicado para os humanos tratarem os endereços de memórias como números (em binário, hexadecimal ou mesmo decimal), por isso damos um nome a esse endereço de memória, um rótulo, e passamos a chamar esse local da memória pelo seu label. Bem mais simples, não?

    No nosso código do Hello World em Assembly, usamos o label '_start', que serve para definir para o NASM onde vai começar nosso programa.
Como outro exemplo do uso de label em nossos códigos Assembly, vamos supor que durante a execução de um programa seja necessário incrementar uma variável 'numero' várias vezes.

O código para incrementar é:


inc numero ;numero++


     Onde 'inc' é um mnemônico, ou seja, representa a operação de incrementação (adicionar +1 à variável 'numero'). Vamos criar um label para definir esse trecho de código, a label: 'incrementa'.
Ela ficaria assim:

incrementa:
  inc numero ;incrementa 'numero' em uma unidade


     Pronto, agora podemos incrementar a variável número apenas invocando o label.

Labels internas ou Labels locais

    O uso de labels é altamente recomendável, visto que os programas em baixo nível sempre são enormes, com códigos 'obscuros', números hexadecimais e outras complicações visuais.

     Em sistemas mais complexos, onde é necessário o uso de centenas ou milhares de linhas de código, será interessante usar labels internas.
Você usará labels que vão representar centenas de linhas de código, e pode ser necessário usar labels dentro destas labels, e provavelmente que tenham o mesmo nome.

     O NASM, que é o Assembler que estamos usando, permite a definição de labels locais.
Para isso, basta colocar um ponto, ' . ', antes do nome da label.

labelNormal -> label normal, sem ponto
.labelInterna -> label local, com ponto, ela está dentro('pertence) a label 'labelNormal'

     Por exemplo, uma representação de um código que duas labels internas, de mesmo nome, mas em locais diferentes, que fazem a mesma coisa (incrementar), mas incrementam variáveis diferentes:

trecho1:
 ;trecho 1 do código
.incrementa:
 inc numero1 
 
 ;continuação trecho 1
 
trecho2:
 ;trecho 2 do código
.incrementa:
 inc numero2
 
 ;continuação do trecho 2

     Note que uma label local se refere a label 'geral', imediatamente superior.
Cuidado para não se confundir.


Define - Como alocar memória Assembly 

RES - como reservar memória


    Se você estudou somente linguagens de altíssimo nível, como as de linguagens de script, com certeza nunca se preocupou em alocar memória, pois é tudo feito automaticamente por debaixo dos panos.

     Se estudou linguagens como C ou Java, você alocava espaço na memória ao declarar variáveis e estruturas (em C é possível ainda, a alocação dinâmica de memória).

     Nesse tutorial de nosso curso de Assembly, vamos aprender como reservar espaço em disco em Assembly, ver quais as diferenças e peculiaridades nessa linguagem de baixo nível.

Alocação de memória em programação

    Em outras linguagens de programação, para declarar variáveis precisávamos definir o tipo antes.

    Por exemplo, em C ou C++, escrevíamos 'int' para inteiros, 'float' ou 'double' para decimais, 'char' para caracteres, dentre outros tipos.

    Ao fazermos isso, sem saber (diferente do Assembly, em que vemos claramente como as coisas são feitas), estamos dizendo muito mais do que simplesmente a alocação de memória em si.


    O resultado de uma operação entre um inteiro e um decimal não é totalmente previsível, depende da variável em que vamos armazenar, da linguagem e de outras regra específicas.
     Quando declaramos uma variável do tipo double ou float, já fica sub-entendido que haverá uma vírgula (ou ponto), representado sua parte decimal. Além disso, há divisões no espaço alocado de memória, para armazenar a parte inteira e a parte decimal.

   Enfim, acontece muito mais do que simplesmente reservar um espaço de memória. Muitas rotinas úteis, que facilitam a vida de programador acontecem por debaixo dos panos.

Alocação de memória em Assembly - A diretiva define

 Obviamente, em Assembly as coisas são um pouco diferente.

     Essas coisas que atuam sem o conhecimento do programador simplesmente não existem, e o profissional que programa em Assembly ficará a cargo de tudo.
     Em Assembly, você realmente irá alocar espaço em memória. E somente isso.

     Por exemplo, usamos o comando ADD para adicionar um número a outro. Mas ele não vai simplesmente adicionar todos e quais números automaticamente como costumamos fazer em outras linguagens.
     Se o resultado der mais de dois dígitos, por exemplo, você terá que fazer uma rotina para exibir esses dois dígitos (sabe quando você soma no papel, fazendo continha e o valor da soma dá mais que 9, aí 'vai 1' ou 'sobe 1' ? é algo parecido) ; ao somar, ter cuidado para saber se somou o caractere '1' ou realmente o número 1. Case seja caractere, ou queira exibir, terá que fazer alterações, e por aí vai.

    Como enfatizamos, Assembly é em baixo nível.
     Trabalhamos com bits e bytes. E nesse nível, as coisas não vem prontas.
     O programador Assembly é que o tem o poder e responsabilidade de absolutamente tudo. Por isso, ao alocar memória, temos que definir o número de bytes que vamos usar.

     Vamos usar as seguintes variações da diretiva define: DB, DW, DD, DQ e DT.
Eles significam e alocam determinados número de bytes, veja:

DB = Define Byte            -> aloca 1 byte
DW = Define Word           -> aloca 2 bytes
DD = Define Doubleword  -> aloca 4 bytes
DQ = Define Quadword    -> aloca  8 bytes
DT = Define Ten              -> aloca 10 bytes

     Sabendo disso, poderemos agora mostrar como é a sintaxe de uma instrução em Assembly para alocar memória:
Nome_da_Variavel diretiva_define valor

     Por exemplo, para alocar espaço para o caractere 'A', fazemos:
letra1 DB 'A'

     Lembramos que, na verdade, embora tenhamos escrito o caractere 'A', tudo são números.
     Então, como na tabela ASCII o valor de 'A', em hexadecimal é 41, poderíamos ter feito:
letra1 DB 41H

     Colocamos a letra H ao final do número para dizer que estamos representando em Hexadecimal.
     Se fossemos colocar em binário, temos que colocar a letra B ao final:
letra1 DB 01000001B

Um pouco de matemática

     Em Assembly, trabalhamos sempre com bytes, onde um byte equivale a 8 bites.
     Cada bit desse pode ser 0 ou 1, então podemos representar até: 2^8 = 256 caracteres com um byte.

     Em Hexadecimal, podemos representar esses 256 caracteres usando os números 00H até FFH.
Ou seja, 41H caberia em um byte, pois é menor que FFH.
     Agora 2112H só caberia em dois bytes, onde um armazenaríamos o byte 12H e no outro o byte 21H.

     Vamos armazenar uma senha na variável 'senha', ela conterá 4 dígitos decimais: 1234
Esse número, em hexadecimal equivalem a 4660H.
Precisamos, então, definir dois bytes, ou uma palavra (word). Um byte armazena o 60H e o outro armazena o 46H.
Para alocar memória para essa senha, faríamos:
senha DW 466H

     Outras maneiras de alocar memória em Assembly
E se quiséssemos alocar uma palavra, como 'curso', por exemplo?
Poderíamos alocar letra por letra:
letra1 DB 'c'
letra2 DB 'u'
letra3 DB 'r'
letra4 DB 's'
letra5 DB 'o'

    Porém, seria muito trabalhoso, e há maneira mais fáceis de se fazer isso.
    Em vez de ter que dar um nome para cada letra (isso não faz o menor sentido!), poderíamos dar um nome só para o conjunto de letras:
curso DB 'c'
DB 'u'
  DB 'r'
  DB 's'
  DB 'o'

     E sempre que usarmos a variável curso, o Assembly saberá que se trata de conjunto de caracteres.

     A maneira mais prática e utilizada para armazenar uma string, é utilizando a define DB e escrevendo uma string (que nada mais é que um texto, um conjunto de caracteres).
O Assembly irá alocar, automaticamente, todos os caracteres, como se tivéssemos feito o exemplo passado.

No exemplo do "Hello, wolrd" em Assembly, Bem mais prático, não?

Reservando memória em Assembly

     Até agora, usando a diretiva define e suas variações (DB, DW, DD, DQ e DT), alocamos memória em Assembly para armazenar e INICIALIZAR variáveis!
    Porém, nem sempre vamos inicializar, apenas queremos alocar.
    Isso é comum para armazenar variáveis cujos valores serão fornecidos posteriormente, pelo seu programa, pelo usuário ou um dispositivo de entrada e saída.

Para reservar memória, usamos a diretiva RES, ao mesmo molde da diretiva DEFINE:
RESB = Reserve Byte             -> reserva 1 byte
RESW = Reserve Word            -> reserva 2 bytes
RESD = Reserve Doubleword   -> reserva 4 bytes
RESQ = Reserve Quadword     -> reserva 8 bytes
REST = Reserve Ten               -> reserva 10 bytes

     A sintaxe é um pouco diferente da DEFINE, já que não vamos inicializar.
     Assim, em vez de valor inicial, temos que dizer quanto de espaço queremos reservar, dependendo da diretiva que usamos.
Sintaxe para reservar memória:
nome_da_variavel diretiva_res numero_de_unidades

Por exemplo:
variavel1 RESB 1 ; nesse caso, reservamos apenas 1 byte
variavel2 RESB 2 ; aqui, reservamos 2 bytes
variavel3 RESW 3 ; 3 palavras são reservadas, o que nos dá 3*2 = 6 bytes
variavel4 REST 10 ; reservamos 10 unidades, de 10 bytes cada


segunda-feira, 27 de abril de 2015

O Ciclo continua: a Versão Jessie é Stable

Debian Jessie 8.0


    Após quase 24 meses de constante desenvolvimento, testes e implementações, o projeto Debian tem o orgulho de apresentar a sua nova versão estável 8 (codinome Jessie) que será suportada durante os próximos 5 anos, graças ao trabalho combinado da equipe de Segurança do Debian e da equipe de Suporte de Longo Prazo do Debian.


Jessie 8.0
Jessie 8.0

    A Jessie vem com um novo sistema init padrão, o systemd. A suíte systemd fornece muitos recursos interessantes, tais como inicialização mais rápida, cgroups para serviços, a possibilidade de isolar parte dos serviços. O sistema init sysvinit já existente ainda está disponível na Jessie.




Wheezy 7.0
Wheezy 7.0
     O suporte à UEFI (Unified Extensible Firmware Interface) introduzido na Wheezy também foi bastante melhorado na Jessie. Isso inclui soluções alternativas para vários bugs conhecidos de firmware, suporte à UEFI em sistemas de 32 bits e suporte a kernels de 64 bits com firmware UEFI de 32 bits (com o último estando incluído apenas em nossa mídia de instalação multi-arch amd64/i386).


Esta versão inclui vários pacotes de software atualizados, tais como:

  • Apache 2.4.10
  • Asterisk 11.13.1
  • GIMP 2.8.14
  • uma versão atualizada do ambiente de área de trabalho GNOME 3.14
  • Coleção de Compiladores GNU 4.9.2
  • Icedove 31.6.0 (uma versão sem marca do Mozilla Thunderbird)
  • Iceweasel 31.6.0esr (uma versão sem marca do Mozilla Firefox)
  • áreas de trabalho KDE Plasma e aplicativos KDE 4.11.13
  • LibreOffice 4.3.3
  • Linux 3.16.7-ckt9
  • MariaDB 10.0.16 e MySQL 5.5.42
  • Nagios 3.5.1
  • OpenJDK 7u75
  • Perl 5.20.2
  • PHP 5.6.7
  • PostgreSQL 9.4.1
  • Python 2.7.9 e 3.4.2
  • Samba 4.1.17
  • Tomcat 7.0.56 e 8.0.14
  • Xen Hypervisor 4.4.1
  • o ambiente de área de trabalho Xfce 4.10
  • mais de 43.000 outros pacotes de software prontos para uso, construídos a partir de cerca de 20.100 pacotes fonte.

     Com esta ampla seleção de pacotes e seu tradicional amplo suporte de arquiteturas, o Debian mais uma vez se mantém fiel ao seu objetivo de ser o sistema operacional universal. Ele é apropriado para muitos casos diferentes de uso: de sistemas desktop a netbooks; de servidores de desenvolvimento a sistemas de cluster; e para servidores de bancos de dados, web ou armazenamento. Ao mesmo tempo, esforços adicionais para garantia de qualidade, como instalação automática e testes de atualização para todos os pacotes do repositório do Debian asseguram que a "Jessie" satisfaz as altas expectativas que os usuários têm de uma versão estável do Debian.

    Um total de dez arquiteturas é suportado: PC 32 bits / Intel IA-32 (i386), PC 64 bits / Intel EM64T / x86-64 (amd64 ), Motorola/IBM PowerPC (powerpc para hardware mais antigo e ppc64el para o novo de 64 bits (little-endian)), MIPS (mips (big-endian) e mipsel (little-endian)), IBM S/390 (s390x 64 bits) e para ARM, armel e armhf para hardware antigo e novo de 32 bits, além do arm64 para a nova arquitetura "AArch64" de 64 bits.


Mais o Trabalho não pode para, obviamente sendo iniciado o lançamento Teste ("testing")  que terá o codinome de "stretch" .


stretch 9.0
stretch 9.0


Versões/Lançamentos Debian

O Debian sempre tem pelo menos três versões em manutenção ativa: estável (stable), testing e instável (unstable).
infographic 2014.deb
estável (stable)
A distribuição estável (stable) contém a última versão oficialmente lançada do Debian.
Esta é a versão de produção do Debian.
A atual distribuição estável (stable) do Debian é a versão 8, codinome jessie. Ela foi inicialmente lançada como versão 8 em 25 de Abril de 2015 e sua última atualização, versão 8.0, foi lançada em 25 de Abril de 2015.
Teste ("testing")
A distribuição testing contém pacotes que ainda não foram aceitos na versão estável (stable), mas estão na fila para tanto. A principal vantagem de usar esta distribuição é que ela possui versões mais recentes de software.
A atual distribuição testing é stretch.
instável (unstable)
A distribuição instável (unstable) é onde o desenvolvimento ativo do Debian ocorre. Geralmente, esta distribuição é utilizada por desenvolvedores e por aqueles que gostam de viver no limite.
A distribuição instável (unstable) é chamada sid.