SOS assembly - peço dicas de leitura

25 respostas
L

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.

25 Respostas

A

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…

H

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í…

D

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

L

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

L

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

L

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

L

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

T

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.

L

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.

L

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

T

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.

L

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.

T

++

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.

L

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


L

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.

L

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.

L

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

T

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.

L

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?

L

Alguem ai já testou o JNode?

L

?

L

Silencio normalmente significa que ninguém aqui testou. O mais próximo que cheguei do JNode foram algumas experiencias com a JikesRVM.

L

Olá

<blockquote><div class="quote-author">Luiz Augusto Prado:</div>eax é pra unix,

int 21h (bios ruindows )

int 80h (kernel do linux)</blockquote>

Cuidado com estas generalizações. Interrupção da BIOS não tem nada a ver com interrupção do SO. E os registradores também são coisas do hardware.

Os manuais da Intel, os livros do Ray Duncan e muitos outros que estou vendo no alto da minha estante não são para quem quer aprender. Se eu fosse dar uma dica para um iniciante seria o antigo livro do Daniel Quadros que pode ser encontrado em http://dqsoft.blogspot.com/2007/09/pc-assember-volume-i.html

[]s
Luca (que escreveu programas em assembler desde os tempos de mainframe, que no início da era PC ganhou uma graninha escrevendo devices drivers, que todos os sistemas que fazia tinham sempre uma firula em asm mas que em 1996 escreveu uma lib usando masm para acessar impressoras ECF e prometeu a si mesmo que era a última coisa que faria usando assembler na vida)

L

Essa foi boa, Luca! :lol: :lol: :lol:

L

Olá!
Quero agradecer a todos pela ajuda e dicas que me deram.
Acho que peguei o embalo. Hehehe
ASM é muito massa!

O que eu tinha que fazer era buscar sobre as System calls.
Abaixo vai um exemplo que fiz aqui. Espero que
possa ajudar outros interessados.

; ARQUIVO char.asm
; NASM-linux
; uso:
; -f elf char.asm
; ld -s -o char char.o

;____________________________ macro CORPO ____________________________________
; CORPO nome do método
; 0 quantidade de parametros do metodo

%macro    CORPO    0

    ;________________________ mostra msg1

    mov     eax,     4        ; System call = 4: escrita na tela

    mov     ebx,     1        ;

    mov     ecx,     msg1    ; msg1

    mov     edx,     tam1    ; quantidade de caracteres da msg1

    int     80h                ;

    ;________________________ pega digitados
    mov     eax,     3        ; System call = 3: leitura de teclado
    mov     ebx,     0        ;
    mov     ecx,     digts    ; digitos que serão digitados
    mov     edx,     10        ; qt de gigitos esperados
    int     80h                ; chama
    
    ;________________________ armazena qt de numeros digitados no endereço [nc]
    mov     [nc],     eax        ; armazena no end a qt de digitos recebidos

;________________________ mostra msg2

    mov     eax,     4        ; System call = 4: escrita na tela

    mov     ebx,     1        ;

    mov     ecx,     msg2    ; msg2

    mov     edx,     tam2    ; quantidade de caracteres da msg2

    int     80h                ;

    

    ;________________________ imprime digitados

    mov     eax,     4        ; System call = 4: escrita na tela

    mov     ebx,     1        ;

    mov     ecx,     digts    ; caracteres que foram digitados

    mov     edx,     [nc]    ; endereço da quantidade de digitos

    int     80h                ;

%endmacro

;____________________________ reserva pedaço de memoria
section .bss
    digts    resb     10        ; reserva espaço para 10 digitos

;__________________ mensagens e seus tamanhos
section .data
    msg1     db         “digite 10 caracteres:”,10
    tam1    equ     $-msg1        
    msg2     db         “Voce digitou:”,10
    tam2    equ     $-msg2
    nc     dd         0
;__________________
section .text

global start
    ;
_______________________ label de inicio do programa
    _start:

    ;************************ armazena ecx da pilha. Será o contador
    push    ecx                ;

        CORPO                ; chama macro CORPO

    ;************************ testa condicional de loop
    pop     ecx                ; pega antigo ecx da pilha
    inc     ecx                ; incrementa ecx
    cmp     ecx,     3        ; limite do loop. REPETE 3 VEZES
    jne     _start            ; salta para label _start enquanto ecx!=3

;________________________ sai do programa

    mov     eax,     1        ; system call = 1: sair do programa

    mov     ebx,     0        ;

    int     80h                ;
Criado 23 de fevereiro de 2008
Ultima resposta 8 de mar. de 2008
Respostas 25
Participantes 8