Tradutor Python - Assembly - semelhante do GCC

219 views
Skip to first unread message

Fabio Bairros

unread,
Jun 24, 2021, 7:54:37 AM6/24/21
to python...@googlegroups.com
Bom dia pessoal.

O gcc possui algumas diretivas que permitem traduzir os comandos do C para o Assembly (gerando um arquivo dos comandos), mostrando como isso será feito em mais baixo nível.
A pergunta é se existe o mesmo para o Python, ou seja, que mostre os comandos equivalentes em Assembly.


Obrigado
Fabio Bairros

António Abracos

unread,
Jun 24, 2021, 8:42:34 AM6/24/21
to python...@googlegroups.com
Olá

O Python é uma linguagem interpretada por um programa que foi escrito maioritariamente em C!
Se analisarmos por exemplo o "if" do Python no código fonte do interpretador que é escrito em C, tu não vais encontrar comandos equivalentes em C mas um algoritmo complexo, ou seja quando escreves o "if" em Python na verdade não estás a chamar o if do C mas todo o programa interpretador.
Por isso não sei se irás conseguir ter a equivalência do Python para Assemby!

António


--
--
------------------------------------
Grupo Python-Brasil
https://wiki.python.org.br/AntesDePerguntar
 
<*> Para visitar o site do grupo na web, acesse:
http://groups.google.com/group/python-brasil
 
<*> Para sair deste grupo, envie um e-mail para:
python-brasi...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "Python Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para python-brasi...@googlegroups.com.
Para ver essa discussão na Web, acesse https://groups.google.com/d/msgid/python-brasil/CALZ%2BQOoKbhUrTJ-xcKY4BbFRm6HPx20%3D9FizOp8tGWxRJBfr9w%40mail.gmail.com.

Fabio C. Barrionuevo da Luz

unread,
Jun 24, 2021, 8:52:16 AM6/24/21
to python...@googlegroups.com
Não existe até onde eu sei. 
Diferentemente de C/C++, Go, Rust que são linguagens que compilam para código de máquina, Python, assim também como Java, JavaScript, Ruby, PHP são linguagens interpretadas, e não são compiladas diretamente para código de máquina.
Isso quer dizer que no lugar do código de máquina, é gerado um código intermediário, chamado bytecode e esse é interpretado por um programa especial chamado interpretador.

Ou seja, em Python puro, o mais baixo nível que você pode ter acesso é o código bytecodes gerados pelo compilador Python.

Você pode ver a descrição textual deles usando o modulo "dis" da biblioteca padrão https://docs.python.org/3/library/dis.html

Exemplo:

from dis import dis

def a():
    return list([1, 2, 3])

def b():
    return [1, 2, 3]

print(dis(a))
print(dis(b))


A execução do código acima ira gerar:

print(dis(a))
  2           0 LOAD_GLOBAL              0 (list)
              2 BUILD_LIST               0
              4 LOAD_CONST               1 ((1, 2, 3))
              6 LIST_EXTEND              1
              8 CALL_FUNCTION            1
             10 RETURN_VALUE

print(dis(b))
  3           0 BUILD_LIST               0
              2 LOAD_CONST               1 ((1, 2, 3))
              4 LIST_EXTEND              1
              6 RETURN_VALUE


Isso quer dizer que linguagens interpretadas são mais lentas que linguagens compiladas?
Meu entendimento atual é sim e não.

O Python puro é mais lento que se a mesma funcionalidade fosse implementada em C/C++, Go e Rust.
Só que desempenho extremo na grande maioria dos casos não importa muito.
O que importa é facilidade de manutenção e custo de manutenção.

Para resolver o problema do desempenho, muitas linguagens interpretadas implementam compiladores JIT (Just-In-Time), 
que acabam por gerar bytecodes que serão interpretados na mesma velocidade que linguagens compiladas e em algumas vezes até mais rápido.

O interpretador Python padrão (conhecido como CPython) não tem um JIT... Esse espaço foi preenchido por um interpretador python alternativo chamado PyPy (https://www.pypy.org/)
Também existem projetos como o Nuitka (https://github.com/Nuitka/Nuitka), que transpilam o código Python para C++, que depois podem ser compilados para código de máquina.

Alem disso, como falei, desempenho extrema não é um requisito na grande maioria dos projetos.
Para resolver o problema de desempenho em partes especificas de projetos, Python tem um amplo ecossistema de alternativas.
Por exemplo, você pode usar Cython ( https://cython.org/ ) para reimplementar as partes que precisam de desempenho.
Cython é uma linguagem hibrida entre C e Python, que no final gerá código C que usa a libpython.
Os modulos implementados em Cython podem ser usados diretamente a partir do código Python.


Outros links:

http://numba.pydata.org/
https://cffi.readthedocs.org/



--

Sergio Garcia

unread,
Jun 24, 2021, 5:45:27 PM6/24/21
to python...@googlegroups.com
Fabio,

O Python gera um código intermediário, e assim como Java e .net, você não consegue acessar as instruções nativas diretamente.

Existem alternativas, mas cada uma vai da aplicação que você quer.

Se me permite perguntar, qual seria o uso que você pretende fazer?




--

Fabio Bairros

unread,
Jun 24, 2021, 6:11:23 PM6/24/21
to python...@googlegroups.com
Boa noite Sérgio e agradeço o retorno.

Estou tentando descobrir como algumas linguagens (entre elas o Python) fazem para desmembrar algumas operações aritméticas. Por exemplo o mod ou % (resto inteiro de uma divisão).

Um dos colegas indicou o seguinte site (abaixo) onde são mostradas as operações equivalentes usando um determinado set de comandos em assembly (dependendo da arquitetura escolhida). Mas no caso do Python ele mostra apenas uma linha indicando "BINARY_MODULO", para o caso da operação módulo. "BINARY_ADD", para o caso de uma soma, e assim por diante. Sem mostrar internamente como é interpretado.




Obrigado
Fabio Bairros


Felipe Torres

unread,
Jun 24, 2021, 6:35:11 PM6/24/21
to python...@googlegroups.com
Fala Fabio,

Dentro do Python voce tem muitas bibliotecas.

Numpy, Pandas entre outras que voce pode usar pra fazer isso. Alem disso, devem ter muitas outras bibliotecas/funcoes que irao te ajudar.

marcos silva

unread,
Jun 24, 2021, 6:37:39 PM6/24/21
to python...@googlegroups.com
Sim. Estou usando algumas biblioteca.
Vou continuar as pequenas.
Como q página é dinâmico não estou conseguindo pegar a informação da tabela por ter um Javascript.


---
Você recebeu essa mensagem porque está inscrito no grupo "Python Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para python-brasil+unsubscribe@googlegroups.com.

--
--
------------------------------------
Grupo Python-Brasil
https://wiki.python.org.br/AntesDePerguntar
 
<*> Para visitar o site do grupo na web, acesse:
http://groups.google.com/group/python-brasil
 
<*> Para sair deste grupo, envie um e-mail para:

---
Você recebeu essa mensagem porque está inscrito no grupo "Python Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para python-brasil+unsubscribe@googlegroups.com.

--
--
------------------------------------
Grupo Python-Brasil
https://wiki.python.org.br/AntesDePerguntar
 
<*> Para visitar o site do grupo na web, acesse:
http://groups.google.com/group/python-brasil
 
<*> Para sair deste grupo, envie um e-mail para:

---
Você recebeu essa mensagem porque está inscrito no grupo "Python Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para python-brasil+unsubscribe@googlegroups.com.

--
--
------------------------------------
Grupo Python-Brasil
https://wiki.python.org.br/AntesDePerguntar
 
<*> Para visitar o site do grupo na web, acesse:
http://groups.google.com/group/python-brasil
 
<*> Para sair deste grupo, envie um e-mail para:

---
Você recebeu essa mensagem porque está inscrito no grupo "Python Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para python-brasil+unsubscribe@googlegroups.com.
Para ver essa discussão na Web, acesse https://groups.google.com/d/msgid/python-brasil/CAHMVQ52946qZLR8saYURd8PUaKtLquC%3DdaELHXD%2Bhk1F%2BoPa0A%40mail.gmail.com.

Sergio Garcia

unread,
Jun 24, 2021, 6:44:19 PM6/24/21
to python...@googlegroups.com
Assim, considerando arquitetura x86, basicamente o que ele faz são 3 passos:
 * tranformar o arquivo *.py em uma versão bytecode (um código intermediário), isso pode ser feito previamente gerando os arquivos *.pyc
 * o interpretador lê esse código intermediário e transforma em código nativo x86
 * o código nativo é armazenado em memória, o bloco de memória e marcado como executável (algo semelhante a carregar uma dll) é então executado

No fim, o que vai ser executado é uma instrução DIV ou IDIV.

Essa é uma explicação bem simplista.

O bytecode gerado, por ser executado em outros interpretadores que não o CPython (o padrão), como IronPython, GraalVM, piston e afins ou conter otimizações.

No site que você colocou com exemplo, use esses dois blocos de código C por exemplo e veja a saída deles

int mod1(int a, int b) { return a % b; }
int mod2(int a) { return a % a; }

mod1:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov DWORD PTR [rbp-8], esi
mov eax, DWORD PTR [rbp-4]
cdq
idiv DWORD PTR [rbp-8]
mov eax, edx
pop rbp
ret
mod2:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, 0
pop rbp
ret

O primeiro tem uma instrução IDIV para calcular o módulo, o segundo foi gerado uma otimização em tempo de compilação, já que modulo de ele mesmo é sempre 0.

Fugindo do exemplo mais simples, não é uma boa ideia estudar o compilador comparando sua saida.





Fabio Bairros

unread,
Jun 25, 2021, 9:15:05 AM6/25/21
to python...@googlegroups.com
Bom dia Sérgio e agradeço.

Estes bytecodes gerados (.pyc) são em algum formato de mnemônico ? (como no assembly). Ou já são as instruções codificadas (por exemplo em hexadecimal) ? ou alguma outra coisa ?

Como posso fazer esta conversão ? .py para .pyc ?


Obrigado
Fabio Bairros


Sergio Garcia

unread,
Jun 25, 2021, 12:03:15 PM6/25/21
to python...@googlegroups.com

O arquivo *.pyc é similar a um executável, os op codes estão em seu formato binário (por exemplo. 22 / 0x16 / 0001 0110) para ser entendido direto pelo interpretador, enquanto na versão disassembly estão em mnemonicos (ex: BINARY_MODULO) para ser compreendido por humanos.

O *.pyc também tem metadados para o interpretador saber onde está cada coisa.

Caso queira ir afundo, a lista dos opcodes está aqui:
https://github.com/python/cpython/blob/eecbc7c3900a7f40d8498b151db543a202c72f74/Include/opcode.h
E eles são interpretados aqui:
https://github.com/python/cpython/blob/0a7dcbdb13f1f2ab6e76e1cff47e80fb263f5da0/Python/ceval.c#L1464

Para compilar de *.py para *.pyc é usado o módulo compileall (https://docs.python.org/pt-br/3/library/compileall.html) e você poderia distribuir somente o pyc se quisesse. De modo geral, você não precompila por que o python faz isso sozinho para você.

Pode ser o caso de você querer forçar a precompilação caso você use microserviços e querer que a primeira execução seja mais rápida (já que muitos microserviços tem o tempo de vida de um request).






Reply all
Reply to author
Forward
0 new messages