Compare commits

...
Sign in to create a new pull request.

5 commits
main ... main

4 changed files with 211 additions and 44 deletions

View file

@ -80,40 +80,3 @@ As datas e tópicos podem mudar de acordo com o desenrolar do curso!
Ao final do curso, será fornecido um certificado de conclusão mediante a
apresentação de um projeto final.
* Inscrições e forma de pagamento
- *Inscrições:* até 27 de junho de 2025
- *Valor parcelado:* R$300,00 (em até 6x)
- *À vista no PIX:* R$270,00 (10% de desconto)
* Como se inscrever
** 1. Realize o pagamento pela forma escolhida
- *PIX (com desconto):* cursos@blauaraujo.com
- *Parcelamentos:* [[https://link.picpay.com/p/17500877656850385526c47][link de pagamento (PicPay)]]
** 2. Envie um e-mail com seus dados
*Destinatário:* cursos@blauaraujo.com
*Informações (obrigatórias):*
- Comprovante de pagamento
- Nome completo
- E-mail de contato
- CPF ou CNPJ
- Endereço postal completo com CEP
Esses dados são necessários para a emissão da nota fiscal.
** 3. Aguarde a resposta
Seu e-mail será respondido em até 24h para confirmar sua inscrição e dar algumas
informações sobre o início das aulas. Você também receberá a nota fiscal eletrônica
no e-mail informado.
* Outras informações e casos especiais
Envie um e-mail para cursos@blauaraujo.com ou me procure no [[https://t.me/blau_araujo][Telegram]].

View file

@ -6,7 +6,11 @@
* 0 -- Introdução à linguagem Assembly (NASM)
[[./aula-00.org][Texto]] | [[#][Vídeo]]
- [[./aula-00.org][Texto]]
- [[https://youtu.be/NsFUbSoz12c][Vídeo #0: Sobre o curso]]
- [[https://youtu.be/LUuNAMezDOM][Vídeo #1: O que é Assembly]]
*Conteúdo:*
- O que é Assembly
- Linguagem dependente da arquitetura
@ -21,8 +25,11 @@
* 1 -- Arquitetura de computadores
[[./aula-01.org][Texto]] | [[#][Vídeo]]
- [[./aula-01.org][Texto]]
- [[https://youtu.be/nW1OrIisvV0][Vídeo #2: Arquiteturas]]
*Conteúdo:*
- Modelo de von Neumann
- Arquiteturas x86
- Componentes de uma CPU x86_64

View file

@ -4,6 +4,11 @@
#+options: toc:3
*Vídeos relacionados:*
- [[https://youtu.be/NsFUbSoz12c][Sobre o curso]]
- [[https://youtu.be/LUuNAMezDOM][O que é Assembly]]
* Objetivos
- Apresentar as características e os elementos básicos da linguagem Assembly.
@ -12,6 +17,110 @@
- Aprender as instruções e diretivas essenciais para começar a programar.
- Criar executar um primeiro programa em Assembly.
* Máquina de Turing
No começo do século 20, surge uma questão no campo da matemática: até onde
seria possível solucionar problemas seguindo estritamente um conjunto de
regras fixas estabelecidas em um /algoritmo/?
#+begin_quote
*Nota:* em matemática, /algoritmos/ são sequências finitas de ações executáveis
que visam obter soluções para determinados tipos de problema.
#+end_quote
Nos anos 1930, o matemático Alan Turing estava trabalhando em um problema de
lógica formal (campo que estuda a estrutura de enunciados e suas regras). Como
parte do que estava tentando demonstrar, ele precisava encontrar uma forma
geral para descrever como algoritmos poderiam ser implementados e executados
mecanicamente.
A partir disso, ele formulou o conceito matemático de uma máquina abstrata que
manipularia automaticamente os símbolos em uma fita de acordo com uma tabela
de regras: a sua /a-machine/ (de /"automatic machine"/), mais tarde chamada de
/Máquina de Turing/ por seu orientador de doutorado -- termo que utilizamos
até hoje.
Então, a Máquina de Turing é um modelo matemático que descreve um dispositivo
muito simples que seria capaz de expressar computações arbitrárias e, com
isso, explorar as propriedades e as limitações da computação mecânica.
#+begin_quote
*Nota:* /modelos matemáticos computacionais/ são modelos que descrevem como a
saída de uma função matemática é computada a partir de uma dada entrada.
#+end_quote
Turing descreveu a imagem física de sua máquina como consistindo de...
- Uma fita dividida em células contendo símbolos ou espaços vazios;
- Um cabeçote para ler e escrever símbolos na fita;
- Um registrador de estados, para armazenar o estado corrente de um conjunto
finito de estados possíveis;
- Uma tabela de instruções que, dado o estado atual e o que estiver sendo
lido na fita, diz à máquina o que fazer na sequência.
Por exemplo:
#+begin_example
Estado atual: q1
Fita:
┌───┬───┬───┬───┬───┬───┬───┐
│ ␣ │ 1 │ 1 │ 0 │ ␣ │ ␣ │ ␣ │
...└───┴───┴───┴───┴───┴───┴───┘...
Cabeçote
Regra:
Se (q1, 0) -> escreva 1, mova para a direita, mude estado para q2
#+end_example
*Ilustração moderna:* [[https://www.youtube.com/watch?v=E3keLeMwfHY][vídeo de Mike Davey]]
Esse modelo simples, apesar de abstrato, revelou-se poderoso o suficiente para
representar qualquer cálculo que possa ser feito por um algoritmo. Contudo,
a computação sequencial das células de uma fita é lenta demais para aplicações
práticas modernas. Mesmo assim, a máquina que Turing descreveu tornou-se uma
das principais inspirações para a construção das /unidades de processamento/,
utilizadas nos computadores até os nossos dias.
** Uma longa fita de bits
Na computação moderna, os nossos programas ainda podem ser vistos como uma
fita contendo uma longa sequência de bits (valores binários =0= e =1=). Mas,
diferente da máquina de Turing:
- Os bits são armazenados na memória principal do computador, onde podem ser
acessados de forma aleatória e quase instantânea;
- Em vez de símbolos individuais por célula e uma tabela de estados, os bits
são interpretados em blocos de tamanho fixo, expressando as instruções
que a CPU deve executar e os dados envolvidos nessas operações;
- A tabela de estados agora está incorporada nos processadores na forma de
um conjunto fixo de instruções específico de cada CPU, conhecido como ISA
(/Instruction Set Architecture/).
Portanto, /escrever um programa/ significa, em essência, representar, nessa
longa fita de bits, os códigos relativos aos dados e instruções que uma
máquina em particular será capaz de interpretar e executar. Isso é o que
chamamos de /código de máquina/ (ou, popularmente, /linguagem de máquina/) e,
em vários momentos da história da computação, os programas foram escritos
desta forma.
Obviamente, escrever diretamente o código de máquina é um processo demorado,
tedioso e propenso a erros. Por isso, já nos anos 1950, começaram a ser
criados programas dedicados à tradução de representações simbólicas de
instruções para as representações binárias do código de máquina. Na prática,
o que esses programas fazem é utilizar as representações simbólicas como um
"manual de instruções" para montar o código de máquina correspondente -- daí
serem chamados de /montadores/ (ou /assemblers/, em inglês).
Vale observar que, inicialmente, essas representações simbólicas não eram
escritas em arquivos de texto como fazemos hoje. Em geral, os códigos das
instruções e dados eram registrados fisicamente, em fitas ou cartões
perfurados, que depois eram lidos por máquinas. Assim, uma /linguagem de
montagem/ (/assembly language/) já existia, mas ainda se passava por uma longa
fase onde o processo de escrita de programas era manual e bastante sujeito
a erros mecânicos e operacionais.
* O que é Assembly
Assembly é uma linguagem de programação que oferece formas de representar, em
@ -162,7 +271,7 @@ quantos bytes quisermos, em qualquer endereço, desde que tenhamos permissão
do sistema.
#+end_quote
** Por que aprender Assembly?
* Por que aprender Assembly?
*** Entendimento do funcionamento de computadores
@ -434,7 +543,7 @@ Quando escrevemos programas em NASM que serão ligados com outros módulos,
como bibliotecas externas ou arquivos objeto, nós precisamos informar ao
editor de ligações quais símbolos devem ser /exportados/ para esses módulos
e quais devem ser /importados/ de outros lugares. No NASM, isso é feito com
as diretivas =global= (importação) e =extern= (exportação).
as diretivas =global= (exportação) e =extern= (importação).
No GNU/Linux, especialmente quando não usamos uma linguagem de mais alto
nível (como C), nós precisamos especificar manualmente o ponto de entrada
@ -738,7 +847,7 @@ imul destino, origem (resultado em destino)
imul destino, origem, imediato (resultado em destino)
#+end_example
- Multiplica =origem= pelo valor de =imediato= e armazena o resultado em =origem=.
- Multiplica =origem= pelo valor de =imediato= e armazena o resultado em =destino=.
- Se o resultado exceder a capacidade de =destino=, apenas os bytes mais
baixos serão armazenados (não há extensão de registradores).
- Afeta as flags =CF= e =OF= no caso de estouro da capacidade de =destino=.
@ -1249,19 +1358,20 @@ instalados no seu sistema:
- Um editor de código da sua preferência (Vim, Emacs, Geany, etc)
- =git=
- =nasm=
- =nasm= e =ndisasm=
- =gcc=
- =as=
- =ld=
- =gdb=
- =readelf=
- =objdump=
- =objcopy=
- =nm=
- =ldd=
- =hexedit=
- =xxd= (geralmente instalado com o editor Vim)
No Debian, a maioria deles é instalada com os comandos:
No Debian e derivados, a maioria deles é instalada com os comandos:
#+begin_example
sudo apt update

87
docs/prefixo-rex.org Normal file
View file

@ -0,0 +1,87 @@
* Prefixos REX na arquitetura Intel 64 (x86-64)
O prefixo REX é um byte opcional usado no modo 64 bits para:
- Acessar registradores estendidos (~r8r15~)
- Usar operandos de ~64~ bits
- Estender campos ~ModR/M~, ~SIB~ ou ~opcode~
** Formato geral do prefixo REX (1 byte)
#+begin_example
Bits: 7 6 5 4 | 3 | 2 | 1 | 0
0 1 0 0 W R X B
#+end_example
| Bit | Nome | Função |
|-----+------+--------------------------------------------------------------------|
| ~74~ | ~0100~ | Identifica o byte como prefixo REX |
| ~3~ | ~W~ | ~1~ = operandos de ~64~ bits |
| ~2~ | ~R~ | Estende o campo ~Reg~ no byte ~ModR/M~ |
| ~1~ | ~X~ | Estende o campo ~Index~ no byte ~SIB~ |
| ~0~ | ~B~ | Estende o campo ~Base~ no ~ModR/M~, ~SIB~ ou campo ~reg~ em certos opcodes |
** Tabela dos 16 prefixos REX possíveis (~0x400x4F~)
| Hex | Binário | ~W~ | ~R~ | ~X~ | ~B~ | Significado resumido |
|------+----------+---+---+---+---+-------------------------------------------------|
| ~0x40~ | ~01000000~ | ~0~ | ~0~ | ~0~ | ~0~ | Sem extensão nem ~64~-bit |
| ~0x41~ | ~01000001~ | ~0~ | ~0~ | ~0~ | ~1~ | ~B = 1~ (extensão do campo Base) |
| ~0x42~ | ~01000010~ | ~0~ | ~0~ | ~1~ | ~0~ | ~X = 1~ (extensão do campo Index) |
| ~0x43~ | ~01000011~ | ~0~ | ~0~ | ~1~ | ~1~ | ~X = 1~, ~B = 1~ |
| ~0x44~ | ~01000100~ | ~0~ | ~1~ | ~0~ | ~0~ | ~R = 1~ (extensão do campo Reg) |
| ~0x45~ | ~01000101~ | ~0~ | ~1~ | ~0~ | ~1~ | ~R = 1~, ~B = 1~ |
| ~0x46~ | ~01000110~ | ~0~ | ~1~ | ~1~ | ~0~ | ~R = 1~, ~X = 1~ |
| ~0x47~ | ~01000111~ | ~0~ | ~1~ | ~1~ | ~1~ | ~R = 1~, ~X = 1~, ~B = 1~ |
| ~0x48~ | ~01001000~ | ~1~ | ~0~ | ~0~ | ~0~ | ~W = 1~ (operandos de ~64~ bits) |
| ~0x49~ | ~01001001~ | ~1~ | ~0~ | ~0~ | ~1~ | ~W = 1~, ~B = 1~ |
| ~0x4A~ | ~01001010~ | ~1~ | ~0~ | ~1~ | ~0~ | ~W = 1~, ~X = 1~ |
| ~0x4B~ | ~01001011~ | ~1~ | ~0~ | ~1~ | ~1~ | ~W = 1~, ~X = 1~, ~B = 1~ |
| ~0x4C~ | ~01001100~ | ~1~ | ~1~ | ~0~ | ~0~ | ~W = 1~, ~R = 1~ |
| ~0x4D~ | ~01001101~ | ~1~ | ~1~ | ~0~ | ~1~ | ~W = 1~, ~R = 1~, ~B = 1~ |
| ~0x4E~ | ~01001110~ | ~1~ | ~1~ | ~1~ | ~0~ | ~W = 1~, ~R = 1~, ~X = 1~ |
| ~0x4F~ | ~01001111~ | ~1~ | ~1~ | ~1~ | ~1~ | ~W = 1~, ~R = 1~, ~X = 1~, ~B = 1~ (todas as extensões) |
** Observações
- O prefixo REX só é válido no modo 64 bits.
- Pode ser necessário mesmo com operandos de 32 bits se registradores estendidos
forem usados.
** Exemplo de desmontagem
#+begin_example
48 89 c8 => mov rax, rcx
#+end_example
Nesse caso:
- ~48~: É o prefixo REX com ~W = 1~, ~R = 0~, ~X = 0~, ~B = 0~ (operandos de 64 bits).
- ~89~: OpCode ~mov r/m, reg~ (como primeiro operando é ~r/m~, temos que ver o byte ModR/M).
- ~c8~: Byte ModR/M, onde...
#+begin_example
Bits: 7 8 | 5 4 3 | 2 1 0
modo | origem | destino
c8 → 11 | 001 | 000
regs | rcx | rax
#+end_example
Portanto... ~48 89 c8 => mov rax, rcx~
** Tabela de registradores no byte ModR/M
O modo ~11~ indica que os dois operandos estão em registradores. Os 3 bits
dos campos ~reg~ e ~r/m~ indicam os registradores, com ou sem extensão via
prefixo ~REX~.
| Código | Reg. | ~REX.R~ ou ~REX.B~ |
|--------+------+----------------|
| ~000~ | ~rax~ | ~r8~ |
| ~001~ | ~rcx~ | ~r9~ |
| ~010~ | ~rdx~ | ~r10~ |
| ~011~ | ~rbx~ | ~r11~ |
| ~100~ | ~rsp~ | ~r12~ |
| ~101~ | ~rbp~ | ~r13~ |
| ~110~ | ~rsi~ | ~r14~ |
| ~111~ | ~rdi~ | ~r15~ |