O C compila para Linguagem de Máquina ou Assembly?

9 respostas
I

Amigos,
To sem projeto…atoa…e bateu uma dúvida xD

O C compila para Assembly ou Linguagem de Máquina?
O arquivo “.exe” gerado, dentro dele…tem linguagem de máquina que consegue conversar direto com o hardware do computador ou Assembly?

Me falavam que o arquivo “.exe” gerado pelo C era compilação da linguagem para Assembly…
Porém, “minha visão e talves ignorancia do momento é:”
Assembly ainda não é linguagem de máquina e sim uma intermediaria de nivel mais baixo para que nós possamos entender, e se o .exe fosse assembly o processadorr não ia intender o.O. Sendo assim, o C compila para limguagem de máquina e não assembly?

Isso também quer dizer que Placas microcontroladoras que entendem assembly, na verdade não entendem…e sim possuem um compilador para transformar o assembly em linguagem de máquina real para depois entender?

Pessoal, quem for responder e me ajudar com as dúvidas por favor tente explicar de forma racional e detalhista e não só postar algo objetivo sem fundamento…por favor hehe.

9 Respostas

F

‘‘Linguagens como C e C++ são compiladas estaticamente, e seus códigos fontes são transformados diretamente em linguagem de máquina.’’ by http://henriquebastos.net/2008/09/06/diferencas-entre-linguagem-compilada-e-linguagem-interpretada/

J

o assembly é na verdade um passo para a linguagem de máquina. Isso quer dizer que as instruções são mostradas como mnemônicos para fins de visualização. Por exemplo:

a instrução move seria -> 001 // isso é uma suposição

move x, 10 poderia ser

então o montador converte o mnemônico para :

001 x 10

É um exemplo grosseiro de como funciona.

F

e só uma correção do que você falou - > Linguagem de Alto nível -> Compilador -> Linguagem Assembly -> Montador -> Linguagem de Máquina, no caso não é o compilador responsável por transformar linguagem assembly em linguagem de máquina e sim o Montador(Assembler).
Valeu :smiley:

J

Importante ressaltar também que o .EXE é um formato de executavel hoje utilizado no Windows, e há outras particularidades no processo de compilação e não simplesmente uma tradução de alto nivel -> assembly -> máquina… inclusive há processos de otimização durante a compilação.

Uma forma interessante de entender isso é baixar um disassembler (por exemplo o ollydbg no windows), criar um programa bobo em C, compilar e depois abrir no disassembler para ver o código assembly encima do código de máquina gerado pelo compilador.

R

E microcontroladores não entendem Assembly, eles entendem linguagem de máquina…

E

O compilador C converte o programa original em C para uma forma intermediária (que depende muito do compilador e que muitas vezes não depende do processador.).

Essa forma intermediária nem sempre aparece em arquivos, às vezes é só construída em memória.

Exemplos de compiladores que usam a forma intermediária: o gcc (onde a forma intermediária pode ser usada também por compiladores Java, C++, Ada etc. - e nesse caso temos o gcj, g++, gnat etc.) e o clang (compilador da Apple, que usa uma forma intermediária chamada LLVM)… A forma intermediária gerada pelo compilador da Microsoft não está documentada publicamente, mas também tem essa finalidade (é algo que é relativamente independente do processador final, que pode ser x86, x64, MIPS, ARM etc.)

Essa forma intermediária, por sua vez, pode ser convertida para Assembly (ou seja, uma listagem com extensão .asm ou .s ) ou então diretamente para as instruções do processador. Depende muito das opções que você passa para o compilador.
o compilador
Como a forma intermediária é algo que proporciona muitas oportunidades para otimização do programa completo, muitas vezes o compilador só gera o formato intermediário, e é o linker que, ao juntar os diversos arquivos .obj (ou .o), chama a fase final do compilador para a partir da forma intermediária, fazer a otiimização global do programa, e então gerar o código de máquina.

J

entanglement:
O compilador C converte o programa original em C para uma forma intermediária (que depende muito do compilador e que muitas vezes não depende do processador.).

Essa forma intermediária nem sempre aparece em arquivos, às vezes é só construída em memória.

Exemplos de compiladores que usam a forma intermediária: o gcc (onde a forma intermediária pode ser usada também por compiladores Java, C++, Ada etc. - e nesse caso temos o gcj, g++, gnat etc.) e o clang (compilador da Apple, que usa uma forma intermediária chamada LLVM)… A forma intermediária gerada pelo compilador da Microsoft não está documentada publicamente, mas também tem essa finalidade (é algo que é relativamente independente do processador final, que pode ser x86, x64, MIPS, ARM etc.)

Essa forma intermediária, por sua vez, pode ser convertida para Assembly (ou seja, uma listagem com extensão .asm ou .s ) ou então diretamente para as instruções do processador. Depende muito das opções que você passa para o compilador.
o compilador
Como a forma intermediária é algo que proporciona muitas oportunidades para otimização do programa completo, muitas vezes o compilador só gera o formato intermediário, e é o linker que, ao juntar os diversos arquivos .obj (ou .o), chama a fase final do compilador para a partir da forma intermediária, fazer a otiimização global do programa, e então gerar o código de máquina.

Após isso ainda existe o “loader” que carrega os programas do disco para a memória quando são executados.

existe um gráfico legal que mostra isso:

http://www.tenouk.com/ModuleW.html

Existe outra coisa interessante que queria mostrar, mas não me lembro onde li sobre isso. Java hotspot usa llvm. Vou ver se encontro o artigo e posto aqui.

J
jmmenezes:
Importante ressaltar também que o .EXE é um formato de executavel hoje utilizado no Windows, e há outras particularidades no processo de compilação e não simplesmente uma tradução de alto nivel -> assembly -> máquina... inclusive há processos de otimização durante a compilação.

Uma forma interessante de entender isso é baixar um disassembler (por exemplo o ollydbg no windows), criar um programa bobo em C, compilar e depois abrir no disassembler para ver o código assembly encima do código de máquina gerado pelo compilador.

Reforçando o que você disse, um executável nada mais é que uma estrutura de dados "específica" de plataforma. Uma estrutura que inclui registros que guardam versão, sistema e também o programa em si que é o assembly

ELF Header:

  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00

  Class:                                  ELF32

  Data:                                   2's complement, little endian

  Version:                                1 (current)

  OS/ABI:            UNIX - System V

  ABI Version:              0

  Type:              REL (Relocatable file)

  Machine:           Intel 80386

  Version:           0x1

  Entry point address:      0x0

  Start of program headers: 0 (bytes into file)

  Start of section headers: 672 (bytes into file)

  Flags:                    0x0

  Size of this header:      52 (bytes)

  Size of program headers:  0 (bytes)

  Number of program headers:       0

  Size of section headers:         40 (bytes)

  Number of section headers:       11

  Section header string table index:      8

 

Section Headers:

  [Nr] Name          Type          Addr     Off        Size     ES Flg Lk Inf Al

  [ 0]               NULL          00000000 000000 000000 00      0   0  0

  [ 1] .text         PROGBITS      00000000 000034 0000de 00  AX   0   0  4

  [ 2] .rel.text     REL           00000000 00052c 000068 08      9   1  4

  [ 3] .data         PROGBIT       00000000 000114 000000 00         WA  0   0  4

  [ 4] .bss          NOBIT         00000000 000114 000000 00  WA  0   0  4

  [ 5] .rodata              PROGBITS      00000000 000114 00010a 00      A  0   0  4

  [ 6] .note.GNU-stack      PROGBITS      00000000 00021e 000000 00      0   0  1

  [ 7] .comment      PROGBITS      00000000 00021e 000031 00      0   0  1

  [ 8] .shstrtab     STRTAB 00000000 00024f 000051 00       0   0  1

  [ 9] .symtab              SYMTAB 00000000 000458 0000b0 10     10  9  4

  [10] .strtab              STRTAB 00000000 000508 000021 00      0   0  1

Key to Flags:

  W (write), A (alloc), X (execute), M (merge), S (strings)

  I (info), L (link order), G (group), x (unknown)

  O (extra OS processing required) o (OS specific), p (processor specific)

 

There are no program headers in this file.

 

Relocation section '.rel.text' at offset 0x52c contains 13 entries:

 Offset       Info                 Type   Sym.Value  Sym. Name

0000002d  00000501 R_386_32 00000000   .rodata

00000032  00000a02 R_386_PC32      00000000   printf

00000044  00000501 R_386_32 00000000   .rodata

00000049  00000a02 R_386_PC32      00000000   printf

0000005c  00000501 R_386_32 00000000   .rodata

00000061  00000a02 R_386_PC32      00000000   printf

0000008c  00000501 R_386_32 00000000   .rodata

0000009c  00000501 R_386_32 00000000   .rodata

000000a1  00000a02 R_386_PC32      00000000   printf

000000b3  00000501 R_386_32 00000000   .rodata

000000b8  00000a02 R_386_PC32      00000000   printf

000000cb  00000501 R_386_32 00000000   .rodata

000000d0  00000a02 R_386_PC32      00000000   printf

 

There are no unwind sections in this file.

 

Symbol table '.symtab' contains 11 entries:

   Num:    Value     Size Type    Bind        Vis             Ndx Name

     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND

     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS testprog1.c

     2: 00000000     0 SECTION LOCAL  DEFAULT    1

     3: 00000000     0 SECTION LOCAL  DEFAULT    3

     4: 00000000     0 SECTION LOCAL  DEFAULT    4

     5: 00000000     0 SECTION LOCAL  DEFAULT    5

     6: 00000080     94 FUNC   LOCAL  DEFAULT    1 display

     7: 00000000     0 SECTION LOCAL  DEFAULT    6

     8: 00000000     0 SECTION LOCAL  DEFAULT    7

     9: 00000000     128 FUNC  GLOBAL DEFAULT    1 main

    10: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf

 

No version information found in this file.
E

No caso de um microcontrolador, onde o programa não costuma ser carregado por um “Loader” e sim ficar presente em uma determinada região de memória apenas de leitura (EEPROM, ROM, memória FLASH etc.) você precisa de um programa adicional que já deixa todas as referências fixas no código a ser “queimado” nessa memória apenas de leitura.

Criado 13 de setembro de 2012
Ultima resposta 13 de set. de 2012
Respostas 9
Participantes 6