SOS assembly - peço dicas de leitura

Olá interessados!

alguem ai poderia me dar algumas dicas sobre assembly?

Tenho buscado informação pela internet, mas o material
que encontrei é muito fraquinho. Muita teoria e pouca
pratica… poucos exemplos.

Sou o tipo do cara que tem que meter a mão na massa
pra aprender no embalo.

Por exemplo:
tentei buscar tutoriais que mostrassem exemplos
simples de como fazer um “if” um “else” um “for” …
e não encontrei.

Outra duvida que tenho é:
como relacionar a numeracao hexadecimal com
as instruções, endereços e registradores.

Não sou de comprar livros…
se temos a internete por que não?
Mas neste caso especificamente,
acho que terei que reavaliar minha decisão.
Existe algum livro de assembly que corresponda
esse meu interesse?

Estou usando o ubuntu e o nasm e a maioria do
material que tenho encontrado está em tasm, masm, ou
mesmo em nasm (só que para ruindows).

Eu achava que os assemblers tinham
uma linguagem e sintaxe padrão e vi que não é bem assim.

if, else, for em assembly?
acorda cara…
só ha MOV, JMP, AND, LEA e outros…ACORDA PARA REALIDADE!!! :twisted:

nao há println bonito e CTRL+SPACE para o java te completar o codigo…

so registos e pilhas…é sofrimento cara…

Opa…

Pelo que entendi vc precisa de Assembly para Linux, certo? Só trabalhei com Assembly para microcontroladores e FPGAs, mas uma vez encontrei um livro de Assembly Linux neste site: http://www.ebookee.com/.

Dá uma olhada aí…

http://webster.cs.ucr.edu/

Valeu davidbuzatto e Hagar!
Vou olhar com calma os endereços.

Claro que to ligado na realidade !
To acostumado com Wittigenstein,
Chomsky e Godel…Isso sim é que é coisa pra doido.
Serei só um bostinha a mais que saberá essa besteira…

“Até hoje não sabem como os egipcios construiram as piramides”.

Use gcc -S e leia o código gerado.

OBRIGADU louds!

Perfeito!
Não podia esperar melhor.
Vou utilizar somente o gcc.

Para qualquer outra duvida só eu fazer um
reverse engineering

.file	"hello.c"
.section	.rodata

.LC0:
.string “Valeu pela dica!”
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
movl $.LC0, (%esp)
call puts
leave
ret
.size main, .-main
.ident “GCC: (GNU) 4.0.3 (Ubuntu 4.0.3-1ubuntu5)”
.section .note.GNU-stack,"",@progbits

Luiz, fora isso, tem os manuais da intel que eu uso no meu dia-a-dia. A única coisa ruim é que o dissambly do GCC é no formato AT&T e os manuais usam a notação da intel.

Para resolver isso você pode usar objdump nos .o ou binarios finais assim “objdump -d -m i386:intel vm_tests.o”. O gcc provavelmente tem algum parâmetro que te permite passar o “-m i386:intel”.

a) Para exemplos de programas Assembly interessantes, veja:
http://www.byte.com/abrash/
Baixe o livro e veja os exemplos em:
http://www.byte.com/abrash/chapters/gpbb8.pdf

b) Quando comecei a aprender C++ e me confundir com as coisas que o compilador fazia sozinho (que operador está sendo chamado? Que construtor está sendo chamado? Onde o destrutor está sendo chamado? ) eu tirava um monte de listagens Assembly da saída do compilador para entender o que estava acontecendo.

Pois é louds,
eu tenho notado uma grande variedade na sintaxe
assembly: AT&T, intel, AT&T (UNIX), intel (UNIX)…

Estou me preparando pra fazer um
compilador e disassembly e para isso
tenho que entender como funciona o assembly no
unix e no DOS para somente mais tarde me aventurar
em SOs.
A ideia inicialmente é fazer arquivos o mais
simples possivel. sem cabeçalhos, comentarios…
Começei com o unix e já estou sacando algumas coisas:

eax é pra unix,
int 21h (bios ruindows )
int 80h (kernel do linux)

Cheguei a utilizar o gcc para gerar o arquivo.s
e o executavel. mas ao ver as diferenças entre
o codigo gerado pelo gcc a partir de um .c e
o .asm em nasm eu desanimei de usar o gcc.

o mesmo codigo feito em nasm que gera um
Hello world! é umas 20 vezes menor.
exemplo nasm (unix):

7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
02 00 03 00 01 00 00 00 80 80 04 08 34 00 00 00
f4 00 00 00 00 00 00 00 34 00 20 00 02 00 28 00
05 00 04 00 01 00 00 00 00 00 00 00 00 80 04 08
00 80 04 08 a2 00 00 00 a2 00 00 00 05 00 00 00
00 10 00 00 01 00 00 00 a4 00 00 00 a4 90 04 08
a4 90 04 08 0e 00 00 00 0e 00 00 00 06 00 00 00
00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b8 04 00 00 00 bb 01 00 00 00 b9 a4 90 04 08 ba
0e 00 00 00 cd 80 bb 00 00 00 00 b8 01 00 00 00
cd 80 00 00 48 65 6c 6c 6f 2c 20 57 6f 72 6c 64
21 0a

não vou nem perder tempo colocando o gerado
pelo gcc… gigante de mais pra um cocozinho desses…
mesmo sem eu inserir a biblioteca stdio.h e o printf.
Somente ometodo main, vazio, já gera um absurdo de codigo.

Encontrei uma apostila da qual pude
tira um resumo interessante:
http://www.planetpdf.com/codecuts/pdfs/aoa.pdf
pagina 126

binario para hexadecimal:

| i | i | i | R | R | r | r | r | + [ andress (16 bits)]

if( iii != 000 )
{
    instructions:
    _____________________________________________________
    iii
    001 = or
    010 = and
    011 = cmp
    100 = sub
    101 = add
    110 = mov reg, mem/reg/const
    111 = mov mem, reg

    reg. target:
    _____________________________________________________
    RR
    00 = ax
    01 = bx
    10 = cx
    11 = dx
    

    reg. origem:
    _____________________________________________________
    rrr
    000 = ax
    001 = bx
    010 = cx
    011 = dx
    100 = [bx]
    101 = [xxxx+bx]
    110 = [xxxx]
    111 = const
    

    exemplo:
    _____________________________________________________
    ins reg reg= iii RR rrr
    mov ax, bx ; 110 00 001
    11000001 = c1h
}

if( iii == 000 )
{
    instructions zero operands if(RR==00):
    ______________________________________________________
    | 0 | 0 | 0 | 0 | 0 | r | r | r |+[ andress (16 bits)]
    rrr
    000 = illegal
    001 = illegal
    010 = illegal
    011 = brk
    100 = iret
    101 = halt
    110 = get
    111 = put

    jump if(RR==01):
    ______________________________________________________
    | 0 | 0 | 0 | 0 | 1 | r | r | r |+[ andress (16 bits)]
    rrr
    000 = je        if equal
    001 = jne        if not equal
    010 = jb        if below
    011 = jbe        if below or equal
    100 = ja        if above
    101 = jae        if above or equal
    110 = jmp        if unconditional jump
    111 = illegal

    not if(RR==10):
    ______________________________________________________
    | 0 | 0 | 0 | 1 | 0 | r | r | r |+[ andress (16 bits)]
    rrr
    000 = ax
    001 = bx
    010 = cx
    011 = dx
    100 = [bx]
    101 = [xxxx+bx]
    110 = [xxxx]
    111 = const

    illegal if(RR==11):
    ______________________________________________________
    | 0 | 0 | 0 | 1 | 1 | r | r | r |+[ andress (16 bits)]
}

O problema dessas apostilas que tenho encontrado é que
não é mostrado as diferenças binarias entre
AH AL BH BL CH CL DH DL…,
eax ebx ecx edx… e
ax bx cx dx…

Não é dito as diferenças nem se elas
são relevantes ou não.
por exemplo:
sei que ax é composto por ah e al,
e na apostila da fonte
https://www.twiki.im.ufba.br/pub/MAT149/WebHome/Parte3.pdf pagina 22
tem:

MOV AH,1h
INT 21h

até ai blz, mas ai vem a duvida se posso reescrever:

mov eax, 1h
int 80h

Outra coisa interessante são as primeiras linhas
do executavel gerado :
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Nenhuma apostila que encontrei fala sobre elas, mas
ao ler em alguns sites é dito que são elas quem
determinam se o arquivo é um executal ou não.
Determina o tipo do arquivo. Mas em nenhum site
ou apostila diz como funciona, onde termina esse
cabeçalho e onde começa o nosso codigo.

vou ver esse "objdump"
acho que isso pode me ajudar mais
Valeu pela dica!

O executável, no caso do Linux e vários Unix, é descrito pelo formato ELF.
No caso do Windows, é descrito pelo formato COFF.

Como é difícil gerar algo em formato ELF ou COFF (tipicamente isso é deixado a cargo do linker), normalmente o que se faz é gerar um arquivo .ASM (no Windows) ou .s (no Linux), usar o assembler (ml no Windows, as ou outra coisa no Unix/Linux) para gerar o .OBJ ou .o, e efetuar a link-edição. Eu não me preocuparia em gerar diretamente o arquivo executável porque isso é muito trabalhoso e você pode ter uma surpresa desagradável.

A diferença entre o nasm e o gcc normalmente é pelo formato usado. No linux o gcc gera código PIC com ELF. nasm vai produzir a.out, que é incrivelmente mais compacto para softwares pequenos.

Quanto a aprender gerar instruções x86, use o manual da intel, é super prático. Eu aprendi e fiz usando eles.

++

Lá no manual você vai aprender que o registrador A (8 bits) (do 8080) foi estendido para AX (16 bits) (com as partes AH e AL) no 8086 e a seguir estendido mais uma vez para EAX (32 bits) no 80386, e recentemente estendido para 64 bits pela AMD e Intel, que o chama agora de RAX.

Acabei de fazer o download do manual.
Agora, é só come-lo.
Até lá vai demorar um pouco pra ter mais dúvidas.

Esse link é interessante:
sistema operacinal


Luiz, você pode dar uma olhada no em http://sourceforge.net/projects/s3o, é um kernel escrito em C++ que é bootavel que simplesmente escreve uns trecos no console e para. Bem didático no sentido de te permitir começar a brincar com o negócio.

Heheheh
alguns “trecos” ?

dei uma olhada lá.
Vcs tão reescrevendo algumas bibliotecas?
tem coisas que eu não entendi.
Eu tenho interesse em tentar rodar
aqui em casa. Como eu faço isso?
é só pegar todos os arquivos e
compilar aqui no gcc?
tem algum macete pra eu fazer isso rapido?

Não entendo muito de linux, mas pela sintaxe dos
comandos que vi parece ser um. estou certo?
Eu to aprendendo a usar o linux só agora,
Tenho interesse em acompanhar o
projeto de vcs. Se eu pegar do inicio pode
ser que eu aprenda algo e talvez consiga dar
algumas sugestões.

Depois que conheci o java, eu abandonei o C.
Faz uns 3 anos que não faço nada grande em C.
Só algumas trivialidades.
parei porque começou a dar muito conflito
entre as bibliotecas de video. por isso eu to curioso…
vcs vão por modo grafico?

quanto ao assembly, eu to acompanhando
um exemplo daqui:
http://www.numaboa.com/content/view/740/228/
No primeiro momento foi chato, mas depois que
vcs me deram as dicas consegui fazer tudo.
É mais facil que eu pensava.

esse exemplo tambem escreve
alguns “trecos” no console.
assembly é muito doido!
acho que o assembly é o que tá mais proximo
da maquina de turing.

É um antigo projeto de faculdade que está morto a coisa de meia década. Para construir ele basta usar os Makefiles alí dentro. Você vai precisar aprender a criar link scripts e outras coisas se quiser escrever SOs. Tem muita coisa para aprender.

No meu tempo de faculdade eu usei aquele Tanenbaum que tinha uma listagem imensa do Minix. (A versão atual é esse que parece um livro infantil: - usei a primeira edição, há 20 anos atrás. )
Tinha um pouquinho de assembler (notação gcc), e quase tudo em C.

Tanenbaum… 20 anos?
então vou dar uma olhada num sebo por aqui perto.
arpoveitar pra trocar meus livros de quimica por ele.

Fiz download do manual da intel.
Gigante! tem interrupção que não acaba mais…

fiz uns exemplos com mouse. Interessantes.
Só tenho encontrado referencias assembly-mouse
em M$-DOS.

se instrução INT 33h não funciona no linux,
Como devo fazer? Existe alguma interrupção
resposnavel por isso no linux ou deve ser feita
alguma chamada exterior?