<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas Wasilewski</title>
    <description>The latest articles on DEV Community by Lucas Wasilewski (@wasix).</description>
    <link>https://dev.to/wasix</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1203636%2Fb0a39b77-53e9-4827-97da-0332e10af69e.jpeg</url>
      <title>DEV Community: Lucas Wasilewski</title>
      <link>https://dev.to/wasix</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wasix"/>
    <language>en</language>
    <item>
      <title>Criando uma Runtime</title>
      <dc:creator>Lucas Wasilewski</dc:creator>
      <pubDate>Fri, 25 Oct 2024 22:40:01 +0000</pubDate>
      <link>https://dev.to/wasix/criando-uma-runtime-4i2d</link>
      <guid>https://dev.to/wasix/criando-uma-runtime-4i2d</guid>
      <description>&lt;p&gt;Olá, meu nome é Lucas Wasilewski e assim como coloquei na descrição do projeto no meu &lt;a href="https://github.com/WasixXD/done" rel="noopener noreferrer"&gt;github&lt;/a&gt; desde que eu comecei a programar com o NodeJS (lá no início de 2021) eu sempre quis escrever algo que parecesse com a ferramenta, isso só aumentou depois que eu assisti o &lt;a href="https://www.youtube.com/watch?v=LB8KwiiUGy0" rel="noopener noreferrer"&gt;documentário&lt;/a&gt; sobre o projeto e fiquei de boca aberta em como o mundo open source pode ter várias reviravoltas e se mostrar muito acolhedor quando quer. E depois de uma semana de muita bateção de cabeça resolvi escrever esse artigo para que assim os futuros &lt;del&gt;loucos&lt;/del&gt; programadores que quiserem esse desafio não cometam os mesmos erros que eu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtimes de Javascript
&lt;/h2&gt;

&lt;p&gt;Esse termo pode facilmente enganar qualquer pessoa que não entenda muito do assunto e então é preciso de uma boa definição:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Uma runtime de Javascript é uma ferramenta que permite executar a linguagem fora do navegador&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hoje em dia existem 3 runtimes populares: NodeJS, Deno (Node Killer) e o Bun (Deno Killer), mas elas basicamente fazem a mesma coisa: permitem você usar o javascript longe do navegador e usam de outras bibliotecas para criar funcionalidades novas, e isso é muito bom, uma vez que você pode usar qualquer uma delas para subir um servidor, criar bibliotecas e até mesmo aplicações mobile ou de terminal.&lt;/p&gt;

&lt;p&gt;Ambos Node e Deno foram criados pela mesma pessoa: Ryan Dahl, e ele lá em 2009 criou a ferramenta para possibilitar que os desenvolvedores pudessem criar aplicações "async IO", ou seja, que não bloqueassem a thread principal mas ainda continuassem respondendo aos pedidos, com isso em mente ele criou a &lt;a href="https://libuv.org/" rel="noopener noreferrer"&gt;Libuv&lt;/a&gt; uma biblioteca que faz justamente isso. Até ai o projeto era apenas um grande amontoado de C e se ele quisesse mas pessoas usando a ferramenta ele precisava de alguma linguagem mais fácil de entender e usar, coincidentemente, nessa mesma época o Google lança a V8, que de um modo geral é um compilador ultra rápido de javascript, isso fez ele unir os dois e assim criar o Node.&lt;/p&gt;

&lt;p&gt;Algum bom tempo depois (9 anos mais especificamente), Ryan saí do projeto e vai trabalhar em outras coisas que considerava mais interessante, isso fez ele perceber alguns vários erros que podiam ser corrigidos no Node, mas a comunidade já estava muito grande e ter que dar um grande passo para trás era impossível, então, determinado a fazer um trabalho melhor ele cria o Deno, outra runtime IO que promete ser muito superior ao Node, até a data de hoje (2024) o Deno está na versão 2.0 e está bem estável para projetos e comunidade.&lt;/p&gt;

&lt;p&gt;Toda essa história fez mais pessoas entrarem na comunidade das runtimes e isso também nos levou a criação do Bun, e muito melhor, da minha e da sua runtime! Agora vamos ao que interessa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compilando a V8
&lt;/h2&gt;

&lt;p&gt;Como dito anteriormente a V8 é o motor do Node, por isso vamos ter que realmente baixá-la e compilar manualmente para assim ter acesso as suas bibliotecas e &lt;em&gt;headers&lt;/em&gt;. Por ser um projeto do Google eles tem os próprios métodos de baixar e compilar, então pra isso vamos ter que seguir o manual deles: &lt;a href="https://v8.dev/docs/build" rel="noopener noreferrer"&gt;link&lt;/a&gt;, apenas copiar e colar vai te levar ao comando finais.&lt;/p&gt;

&lt;p&gt;Porém, aqui eu cometi um erro que demorou 3 dias para me tocar que estava fazendo tudo de errado. Após gerar os arquivos de configuração de build com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tools/dev/v8gen.py x64.release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você precisar tomar muito cuidado com o arquivo &lt;code&gt;args.gn&lt;/code&gt; dentro da pasta &lt;code&gt;out.gn/x64.release/&lt;/code&gt; porque nele tem a configuração de build que o ninja (ferramenta de compilação) vai utilizar para gerar os arquivos da biblioteca, alguns tutoriais antigos usam o parâmetro &lt;code&gt;v8_monolithic = true&lt;/code&gt;, mas nas versões recentes isso não é mais utilizado. De acordo com &lt;a href="https://stackoverflow.com/questions/71213580/cant-get-v8-monolith-to-genorate" rel="noopener noreferrer"&gt;esse comentário&lt;/a&gt; do StackOverflow, nós precisamos agora usar o parâmetro &lt;code&gt;is_component_build = true&lt;/code&gt; para gerar os arquivos certos e modificar as flags ao compilar o arquivo, algo muito bobo que se você não prestar atenção pode gastar um tempo precioso.&lt;/p&gt;

&lt;p&gt;Após colocar o resto das flags corretamente, apenas precisamos rodar o comando para compilar o projeto&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ninja -C out.gn/x64.release&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Enquanto isso vá comer alguma coisa, porque a V8 é um projeto bem extenso e com inúmeros testes, dependendo da sua máquina esse processo pode facilmente levar 1 hora ou mais, então deixe rodando e continue lendo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cadê o console.log?
&lt;/h2&gt;

&lt;p&gt;Após compilar você pode dar uma olhada no &lt;code&gt;v8/samples/hello-world.cc&lt;/code&gt; e já começar a ter uma ideia de como compilar javascript, mas especificamente essas linhas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NewFromUtf8Literal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"'Hello' + ', World!'"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Compile the source code.&lt;/span&gt;
&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
          &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Script&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;ToLocalChecked&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vá em frente e dê uma brincada com a string que contêm o "Hello World", crie funções, loops, condicionais e se veja maluco ao perceber que se você incluir o clássico &lt;code&gt;console.log()&lt;/code&gt; vai receber um &lt;code&gt;undefined&lt;/code&gt;, isso primeiramente me deixou perplexo, eu sempre achei que o objeto console fazia parte da própria V8, mas na verdade quem o inclui é o próprio Node e os navegadores o incluem como parte do DOM (&lt;a href="https://stackoverflow.com/questions/14086675/which-browsers-support-console-log" rel="noopener noreferrer"&gt;post&lt;/a&gt; de 2012 falando que o console.log provavelmente não é suportado pelos navegadores), ou seja, vamos ter que criá-lo nós mesmos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Olá, Mundo!
&lt;/h2&gt;

&lt;p&gt;Para conseguir criar nossas próprias funções primeiro precisamos entender que a V8 trabalha com vários escopos, um deles é o de contexto, onde é através dele que a runtime sabe onde e como executar o script de forma individual, dentro dele pode haver um objeto global que é compartilhado entre todos os outros, e é dentro dele que vamos inserir nossas funções customizadas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ObjectTemplate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ObjectTemplate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetIsolate&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetIsolate&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"print"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetIsolate&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetIsolate&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com essas linhas conseguimos criar um objeto que se chama &lt;code&gt;global&lt;/code&gt;, inserimos um template de função "print" que ao ser executado chama a função &lt;code&gt;Print&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FunctionCallbackInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HandleScope&lt;/span&gt; &lt;span class="n"&gt;handle_scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetIsolate&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Utf8Value&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetIsolate&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
         &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ToCString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;fflush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A função Print recebe esse parâmetro maluco que contém informações sobre a chamada da função dentro do javascript e é através dele que iteramos sobre todos os itens dentro dela, os transformamos em uma string C e printamos na tela, bem direta, bem simples e que cumpre com seu papel, isso já é o suficiente para colocar em um arquivo, lê-lo e jogar para a V8 (deixo essa em suas mãos).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test.js&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Olá, mundo!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Libuv
&lt;/h2&gt;

&lt;p&gt;Bom, espero que até aqui você esteja conseguindo acompanhar e até tenha parado de ler para fazer algumas implementações únicas para o seu Node caseiro, porém a V8 só vai nós levar até certo ponto, para conseguirmos chegar mais perto de uma runtime profissional precisamos fazer com que o javascript consiga realizar mais operações, para tal vamos utilizar da Libuv que foi criada justamente para isso.&lt;/p&gt;

&lt;p&gt;Você pode achar o tutorial para instalar e compilar &lt;a href="https://github.com/libuv/libuv" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;. O importante a se notar aqui é que ela nos dá a liberdade de fazer operações assíncronas, ou seja, sem bloquear a thread principal, permitindo assim que o programa continue executando enquando faz um trabalha mais pesado (como abrir um arquivo ou esperar por requisições em um socket de servidor).&lt;/p&gt;

&lt;p&gt;Ela mesma já vem embutido com a funcionalidade de criar um servidor http, então só precisamos sincronizá-la com as chamadas da V8. Não se engane, isso não é uma tarefa fácil, até porque a interface das duas bibliotecas se diferem bastante então é difícil conectar ambas, mas sempre há um jeito e o código fonte do node é aberto então certifique-se de roubar algumas ideias de lá &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusões
&lt;/h2&gt;

&lt;p&gt;Chegamos ao final de mais um artigo e com eles vamos a alguns detalhes que eu percebi durante a implementação. A primeira com certeza é a complexidade, claro, não é um projeto simples, mas depois que você entender como interagir com a interface da V8 as coisas andam bem rápido.&lt;/p&gt;

&lt;p&gt;Esse projeto me fez entender o Node muito melhor também. A questão que a runtime é apenas um conglomerado de bibliotecas se comunicando faz ser muito fácil entender como as coisas mais complexas (como o "event-loop") funcionam.&lt;/p&gt;

&lt;p&gt;Caso você queira olhar o que eu fiz de certo, ou provavelmente de muito errado, por favor dê uma olhada no projeto pelo github: &lt;a href="https://github.com/WasixXD/done" rel="noopener noreferrer"&gt;done&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Talk is cheap, show me the code - Linus Torvalds&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;## Refêrencias &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/libuv/libuv" rel="noopener noreferrer"&gt;https://github.com/libuv/libuv&lt;/a&gt;&lt;br&gt;
&lt;a href="https://v8.dev/docs" rel="noopener noreferrer"&gt;https://v8.dev/docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/71213580/cant-get-v8-monolith-to-genorate" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/71213580/cant-get-v8-monolith-to-genorate&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/ErickWendel/myownnode" rel="noopener noreferrer"&gt;https://github.com/ErickWendel/myownnode&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/WasixXD/done" rel="noopener noreferrer"&gt;https://github.com/WasixXD/done&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>node</category>
      <category>v8</category>
      <category>javascript</category>
    </item>
    <item>
      <title>20 milhões de linhas em 20s</title>
      <dc:creator>Lucas Wasilewski</dc:creator>
      <pubDate>Wed, 09 Oct 2024 18:08:12 +0000</pubDate>
      <link>https://dev.to/wasix/20-milhoes-de-linhas-em-20s-5in</link>
      <guid>https://dev.to/wasix/20-milhoes-de-linhas-em-20s-5in</guid>
      <description>&lt;p&gt;Olá, meu nome é Lucas Wasilewski e recentemente me propus a começar a programar com mais limitações, tanto no sentido de máquina quanto no sentido de programas auxiliares, dito isso, o ecossistema do JDK tem alguns gerenciadores de pacotes muito bem conhecidos como: Gradle e o Maven, porém, como você conecta uma das linguagens mais populares do mundo com um banco de dados sem eles? É isso que eu quis resolver.&lt;/p&gt;

&lt;h2&gt;
  
  
  JNI e libpq
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Bem, como eu não tenho acesso a nenhuma outra biblioteca que faça a conexão ao Postgres, basta eu escrever uma eu mesmo?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sim, e é bem mais fácil do que parece, o primeiro passo seria eu encontrar uma forma de me conectar ao banco através do Java, me veio a mente que em libs do NodeJs geralmente você especifica os dados necessários em um formato de string, mais ou menos assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//usuario:senha@host:port/banco_de_dados&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Então logo pensei que deveria ter algo haver com uma conexão de sockets e na verdade o projeto ia virar mais relacionado a redes. Porém, com uma rápida pesquisada na documentação do próprio &lt;a href="https://www.postgresql.org/docs/17/index.html" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; vi que eu iria primeiro ter que escrever um client e para isso eu precisava da biblioteca deles: libpq.&lt;/p&gt;

&lt;p&gt;Lendo mais um pouco eu vi que só havia implementações em C e então o caminho estava mais claro do que nunca: eu só precisava de uma forma do Java conseguir chamar as funções de outra linguagem e resgatar os dados, isso tem um nome, se chama FFI (Foreign Function Interface) sendo algo muito utilizado devido as limitações das próprias linguagens. &lt;em&gt;Um exemplo disso é o Numpy do Python que usa algumas partes em Fortran devido ao desempenho&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Depois de mais uma pesquisada achei o JNI (Java Native Interface), que de acordo com a &lt;a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jni/" rel="noopener noreferrer"&gt;Oracle&lt;/a&gt;: JNI é uma interface que permite ao Java chamar código escrito em outras linguagens, como C ou C++. Basicamente o compilador do Java consegue gerar headers que podem ser depois implementados por essas linguagens usando o &lt;code&gt;&amp;lt;jni.h&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Claro que o meu objetivo desde o principio era somente conseguir fazer essa conexão e funções suficientes para &lt;strong&gt;um&lt;/strong&gt; mísero CRUD, porém, a criação da lib foi muito rápida e eu queria mais desafios.&lt;/p&gt;

&lt;h2&gt;
  
  
  20 milhões de linhas
&lt;/h2&gt;

&lt;p&gt;Saiu bem no inicio desse ano (2024) um desafio feito por Gunnar Morling em seu blog chamado de: &lt;a href="https://www.morling.dev/blog/one-billion-row-challenge/" rel="noopener noreferrer"&gt;One Billion Row Challenge&lt;/a&gt;, nesse desafio os participantes teriam que dar &lt;strong&gt;parse&lt;/strong&gt; em um arquivo csv com 1 bilhão de linhas, tudo isso feito em Java, essa competição ficou bem famosa e a solução mais rápida foi em &lt;strong&gt;1.5s&lt;/strong&gt;, isso me deixou muito curioso. Afinal, o arquivo devia ser muito pesado e eles usaram muitos (realmente muitos) conceitos técnicos de memória, processador, sistema operacional e performance. &lt;/p&gt;

&lt;p&gt;Um bilhão de linhas é muita coisa para mim ainda, mas talvez eu consiga trabalhar com um número um pouco menor, então após algumas sessões com a nossa LLM favorita criei um script em Python que conseguia criar dois arquivos csv com &lt;code&gt;nome;email;telefone&lt;/code&gt; pesando 10mb e 1GB, com 209712 e 20971521 de linhas respectivamente. Agora só bastava por minha framework a maior prova de fogo que eu consegui criar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Primeira implementação
&lt;/h2&gt;

&lt;p&gt;O primeiro passo é ler o arquivo. Isso pode soar fácil se você estiver na casa das 200 mil linhas, a memória heap da JVM onde geralmente se guarda o conteúdo lido provavelmente suporta essa quantidade de dados, mas você nunca vai conseguir guardar 1 milhão de itens lá dentro. Por isso a sua melhor opção vai ser ler e processar linha a linha do arquivo, assim, você não estoura a memória e linearmente insere todos os itens. Bom, vamos aos testes, todos eles serão feitos em um i5-11400 com 12 threads.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementações&lt;/th&gt;
&lt;th&gt;209.712 linhas&lt;/th&gt;
&lt;th&gt;20.971.521 linhas&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1°&lt;/td&gt;
&lt;td&gt;9 minutos&lt;/td&gt;
&lt;td&gt;Fim do universo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;9 minutos.&lt;br&gt;
Esse foi o melhor tempo que consegui com essa implementação e ainda nem chegamos na casa do milhão, o que deu errado? Não era pro Java ser rápido? Melhor reescrever tudo em React...&lt;/p&gt;
&lt;h2&gt;
  
  
  Segunda implementação
&lt;/h2&gt;

&lt;p&gt;A nossa máquina está acostumada a fazer bilhões de instruções por minuto e o primeiro algoritmo apena lê sequencialmente e insere cada linha uma a uma no banco, ou seja, o tempo aumenta quanto mais linhas existem no arquivo, fora que estamos jogando um tempo de leitura precioso demais aguardando as outras tarefas de dar parse na linha e as de inserção.&lt;/p&gt;

&lt;p&gt;Para reduzir esse problema podemos introduzir o multi-threading, fazendo com que usemos todos os nossos núcleos do processador e aumentando o número de "atores" para resolver o problema. Então nessa implementação adicionei uma queue, a thread principal lia o arquivo sequencialmente da forma mais rápida que podia e ia jogando em pedaços as linhas para que alguma outra thread pudesse puxar esse valor e fazer a inserção. Vamos aos testes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementações&lt;/th&gt;
&lt;th&gt;209.712 linhas&lt;/th&gt;
&lt;th&gt;20.971.521 linhas&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1°&lt;/td&gt;
&lt;td&gt;9 minutos&lt;/td&gt;
&lt;td&gt;Fim do universo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2°&lt;/td&gt;
&lt;td&gt;4 minutos&lt;/td&gt;
&lt;td&gt;Trava em 1.200.000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Opa, uma melhoria de 55,56%, já começou a ficar bem mais legal, até mesmo conseguimos processar o arquivo de 1Gb, porém, por algum motivo essa implementação fica presa nas 1.200.000 linhas.&lt;/p&gt;
&lt;h2&gt;
  
  
  Terceira implementação
&lt;/h2&gt;

&lt;p&gt;Ok, as threads ajudam muito, mas, meu conhecimento em Java não é dos maiores, então eu usei um método que eu conhecia em outras linguagens: Eu pegava a linha inteira, usava o &lt;code&gt;.split&lt;/code&gt; para separar por &lt;strong&gt;;&lt;/strong&gt; e então usava o &lt;code&gt;.format&lt;/code&gt; para criar uma query de inserção, ao pesquisar por soluções melhores achei em um blog que o &lt;code&gt;.format&lt;/code&gt; era o mais lento dentre todas as funções de string no Java e que isso era o que provavelmente estava causando essa enorme lentidão, então comecei a usar o &lt;code&gt;StringBuilder&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;StringBuilder&lt;/span&gt; &lt;span class="n"&gt;sb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringBuilder&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;sb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"INSERT INTO users VALUES "&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;split&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;";"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;sb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"('"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"','"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;"',"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;"),"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;sb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCharAt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;';'&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nos testes isso realmente se provou ser um grande gargalo do algoritmo: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementações&lt;/th&gt;
&lt;th&gt;209.712 linhas&lt;/th&gt;
&lt;th&gt;20.971.521 linhas&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1°&lt;/td&gt;
&lt;td&gt;9 minutos&lt;/td&gt;
&lt;td&gt;Fim do universo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2°&lt;/td&gt;
&lt;td&gt;4 minutos&lt;/td&gt;
&lt;td&gt;Trava em 1.200.000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3°&lt;/td&gt;
&lt;td&gt;0,4 segundos&lt;/td&gt;
&lt;td&gt;24 segundos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;😲 essa foi minha reação quando eu fiz o primeiro teste, uma melhora de 99,83%. Tão rápido que eu mesmo não estava acreditando que no que estava acontecendo. Claro que o &lt;code&gt;StringBuilder&lt;/code&gt; não foi a única solução adicionada, se você olhar com um pouco mais de atenção dá para perceber que junto todos os inserts das linhas e faço a query de uma vez só, assim reduzindo a quantidade de comandos realizados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Um último suspiro
&lt;/h2&gt;

&lt;p&gt;Eu ainda estava querendo mais, queria pelo menos algo em torno de 15 segundos (ia ficar bem no título, pensei comigo), então adicionei uma última carta na manga, as &lt;code&gt;threadpools&lt;/code&gt;, elas são um número de threads que são criadas em conjunto e conseguem receber tarefas igualmente, assim reduzo o tempo de criação e também melhoro a forma de distribuir as tarefas:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Implementações&lt;/th&gt;
&lt;th&gt;209.712 linhas&lt;/th&gt;
&lt;th&gt;20.971.521 linhas&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1°&lt;/td&gt;
&lt;td&gt;9 minutos&lt;/td&gt;
&lt;td&gt;Fim do universo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2°&lt;/td&gt;
&lt;td&gt;4 minutos&lt;/td&gt;
&lt;td&gt;Trava em 1.200.000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3°&lt;/td&gt;
&lt;td&gt;0,4 segundos&lt;/td&gt;
&lt;td&gt;24 segundos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4°&lt;/td&gt;
&lt;td&gt;0,2 segundos&lt;/td&gt;
&lt;td&gt;22-20 segundos&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Aqui, começo a identificar os gargalos nas minhas implementações. Nessa última tentativa, além da pool de threads, utilizei outros métodos que encontrei para extrair o máximo de desempenho possível. Porém não consegui passar dos 20 segundos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusões
&lt;/h2&gt;

&lt;p&gt;Esse projeto foi com certeza o mais técnico que fiz nos últimos tempos, apesar de não chegar no tempo que eu queria eu fiquei muito animado quando descobria cada nova forma de melhorar uma única linha (mesmo que eu provavelmente fosse ganhar no máximo 0.001 segundos).&lt;/p&gt;

&lt;p&gt;Ainda sim fiquei pensando o quanto eu conseguiria extrair dessa única framework de 3 funções, vale ressaltar que no desafio do bilhão de linhas eles somente tinham que processar o arquivo e escrever na tela, assim, não levavam em conta o tempo de espera das querys (embora eu acredite que isso não seria um impedimento para eles).&lt;/p&gt;

&lt;p&gt;Em conclusão, o meu pequeno desafio de ter mais impedimentos do que ajudas foi o pontapé para eu estudar e aprender mais sobre muita coisa que eu não conhecia, isso fora as que eu não quis entrar, como os métodos unsafe do java que iria me permitir mexer com ponteiros e endereços de memória.&lt;/p&gt;

&lt;p&gt;Caso você queira olhar o que eu fiz de certo, ou provavelmente de muito errado, por favor dê uma olhada no projeto pelo github: &lt;a href="https://github.com/WasixXD/Ant" rel="noopener noreferrer"&gt;Ant&lt;/a&gt;. Rumo aos 2 bilhões de linhas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;C is quirky, flawed, and an enormous success - Dennis Ritchie&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Refêrencias
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/technotes/guides/jni/" rel="noopener noreferrer"&gt;https://docs.oracle.com/javase/8/docs/technotes/guides/jni/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Foreign_function_interface" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Foreign_function_interface&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.postgresql.org/docs/17/libpq.html" rel="noopener noreferrer"&gt;https://www.postgresql.org/docs/17/libpq.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/java-read-lines-large-file" rel="noopener noreferrer"&gt;https://www.baeldung.com/java-read-lines-large-file&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gunnarmorling/1brc" rel="noopener noreferrer"&gt;https://github.com/gunnarmorling/1brc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=EFXxXFHpS0M&amp;amp;t=1836s" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=EFXxXFHpS0M&amp;amp;t=1836s&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>performance</category>
      <category>postgres</category>
      <category>c</category>
    </item>
    <item>
      <title>Do it Yourself: CPU</title>
      <dc:creator>Lucas Wasilewski</dc:creator>
      <pubDate>Mon, 29 Jul 2024 16:04:57 +0000</pubDate>
      <link>https://dev.to/wasix/do-it-yourself-cpu-37d6</link>
      <guid>https://dev.to/wasix/do-it-yourself-cpu-37d6</guid>
      <description>&lt;p&gt;Olá, meu nome é Lucas Wasilewski e no último mês me deparei com esse &lt;a href="https://www.youtube.com/watch?v=7w8IeXKstJY&amp;amp;list=WL&amp;amp;index=19&amp;amp;t=824s" rel="noopener noreferrer"&gt;vídeo&lt;/a&gt;, sinceramente fiquei tão empolgado com a ideia de poder criar uma "CPU" que coloquei esse projeto como prioridade na minha lista e algumas semanas depois aqui estamos. Esse artigo tem o objetivo de tentar te deixar muito animado ao ponto de você também desenvolver a sua própria CPU ou pelo menos um emulador dela.&lt;/p&gt;

&lt;h2&gt;
  
  
  CPUs
&lt;/h2&gt;

&lt;p&gt;Antes de começar a sair pensando em como sua CPU vai parecer ou o nome dela, vamos dar um passo para trás e entender qual é o papel de uma e um pouco de sua história.&lt;/p&gt;

&lt;p&gt;O ENIAC um dos primeiros computadores programáveis a serem construídos conseguia resolver uma grande quantidade de problemas, um deles sendo as distâncias que projéteis de artilharia podiam alcançar, sendo um grande benefício pro governo norte americano que tinha investido nisso na segunda guerra mundial.&lt;/p&gt;

&lt;p&gt;Por mais que isso fosse uma revolução pra época, o ENIAC tinha uma desvantagem, cada programa tinha que ser construído do zero, ou seja, os programadores tinham que levar semanas para pensar no programa e &lt;em&gt;plugar&lt;/em&gt; os cabos nos lugares certo (isso sem contar o tempo que levavam para corrigir &lt;em&gt;bugs&lt;/em&gt; e outras coisas).&lt;/p&gt;

&lt;p&gt;Para resolver esse problema de desenvolvimento foi criada a possibilidade de guardar o código na memória e da máquina ter instruções para interpretar esse programa, facilitando e permitindo uma melhor maneira de ser codificada.&lt;/p&gt;

&lt;p&gt;John von Neumann foi o consultor de ambos ENIAC e seu sucessor o EDVAC, foi responsável também por construir a arquitetura de von Neumann que é de onde vem o nome da Central Processing Unit(CPU) nela todas os chips de aritmética, lógica e controle de IO ficam armazenados juntos e através de instruções ela consegue controlar o funcionamento do programa.&lt;/p&gt;

&lt;p&gt;Atualmente, chamamos nossos processadores de CPU porque são projetados para realizar operações em velocidades absurdas. No entanto, se você, assim como eu, não tem uma mega corporação para minerar silício e criar placas com essa potência, a melhor alternativa será o nosso próximo tópico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Emuladores
&lt;/h2&gt;

&lt;p&gt;Emular uma CPU não é uma tarefa tão difícil quanto parece, apenas precisamos entender seu funcionamento básico e o resto é apenas programação.&lt;/p&gt;

&lt;p&gt;O ciclo básico se dá por quatro passos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primeiro&lt;/strong&gt;: Precisamos de um guia, ele vai quem  vai indicar onde estamos e para onde vamos, vamos chamá-lo de PC ou &lt;code&gt;program counter&lt;/code&gt; e então começamos a ler o programa&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Segundo&lt;/strong&gt;: Vamos buscar na memória a posição que o PC indica e carregá-la&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terceiro&lt;/strong&gt;: Decodificaremos a instrução que foi carregada para localizar os valores que vamos utilizar para nossa operação&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quarto&lt;/strong&gt;: Realizamos a instrução e incrementamos o PC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Siga com esses passos até não encontrar mais nenhuma instrução e seu programa foi realizado. &lt;/p&gt;

&lt;p&gt;Por mais que esse ciclo pareça bem simples, imagine que as CPUs modernas realizam essa operação a 3.5GHz, ou seja, a 3.5 &lt;strong&gt;bilhões&lt;/strong&gt; por segundo. Comparando ao ENIAC que fazia 5.000(5kHz) operações matemáticas por segundo, isso é um aumento de 69,800% na velocidade de processamento, um número tão absurdo que hoje em dia um computador simular a outro é algo relativamente fácil.&lt;/p&gt;

&lt;p&gt;Existem muitos artigos por aí ensinando como emular chips mais fracos como o: CHIP8 ou o muito respeitado 6502, que foi um dos microprocessadores que revolucionou áreas como a de desktop sendo a CPU principal do AppleII e do Comodore 64 ou a de Vídeo-Games integrando grandes consoles como o Nintendo Entertainment System(NES) e o Atari 2600.&lt;/p&gt;

&lt;p&gt;Emular é algo mais do que apenas conseguir rodar jogos antigos e nostalgia, é sobre história, preservação e teimosia. Muitas pessoas gastaram dias, semanas e meses fazendo &lt;em&gt;reverse engineering&lt;/em&gt; de instruções e mapeando cada componente daquele processador para que as pessoas pudessem entender como cada parte se comporta em determinada situações.&lt;/p&gt;

&lt;p&gt;Agora chega de história e vamos começar a pensar em como emular a sua CPU.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sua CPU
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O Trabalho dela
&lt;/h3&gt;

&lt;p&gt;Sua CPU vai ter vídeo? Essa é uma pergunta importante. &lt;/p&gt;

&lt;p&gt;Várias CPUs antigas incluíam suporte a exibição gráfica, por isso contavam com partes da memória dedicadas para ter funções que fariam o &lt;em&gt;display&lt;/em&gt; de vídeo mais fácil.&lt;/p&gt;

&lt;p&gt;O CHIP8 por exemplo, especifica que os &lt;em&gt;bitmaps&lt;/em&gt; das fontes ficassem nos primeiros 512 bytes da memória e tinha instruções próprias para desenhar pixels em uma tela de 64x32.&lt;/p&gt;

&lt;p&gt;Fora isso, comece a imaginar os problemas que você quer que ela resolva, funções matemáticas como multiplicação, divisão, exponenciação ou radiciação podem ser essenciais se você queria resolver funções ou gerar estatística, porém, podem ser péssimos se você apenas queira simular o &lt;a href="https://pt.wikipedia.org/wiki/Jogo_da_vida" rel="noopener noreferrer"&gt;game of life&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memória
&lt;/h3&gt;

&lt;p&gt;Sua CPU provavelmente vai querer guardar o programa dela na memória para evitar que os programadores passem semanas colocando os cabos nos lugares corretos como no ENIAC. Para isso pense na memória como um &lt;em&gt;array&lt;/em&gt; ou vetor na sua linguagem de programação preferida, armazenar algo nela pode ser algo tão simples quanto indicar que aquela posição terá aquele valor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registers
&lt;/h3&gt;

&lt;p&gt;Um &lt;em&gt;register&lt;/em&gt; é uma parte da memória de fácil acesso para a CPU, eles serão responsáveis por guardar valores que vão ser utilizados pelo seu programa ou por ela mesmo.&lt;/p&gt;

&lt;p&gt;Como estamos emulando, não precisamos necessariamente colocá-los dentro da memória, em C por exemplo, eles podem ser campos de uma &lt;em&gt;struct&lt;/em&gt;, isso irá facilitar em muito a sua vida &lt;/p&gt;

&lt;h3&gt;
  
  
  Suas instruções
&lt;/h3&gt;

&lt;p&gt;De todas as partes arquiteturais essa é com certeza a mais divertida.&lt;/p&gt;

&lt;h4&gt;
  
  
  Op Codes
&lt;/h4&gt;

&lt;p&gt;A CPU apenas entende binário. Isso é sua grande vantagem e desvantagem, por isso, iremos facilitar nosso entendimento criando mnemônicos que irão traduzir a linguagem humana para a linguagem de máquina. Então&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MOV a, 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resulta em:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0001 0101 0001 0000 0000 0000 0000 0001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sendo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Os 8 primeiros bits o código binários para o comando &lt;code&gt;MOV&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Os próximos 8 bits para os registradores, nesse caso apenas o &lt;code&gt;a&lt;/code&gt; foi usado, resultando no binário: &lt;code&gt;0001&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;E o últimos 16 bits sendo um valor decimal &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esse exemplo é da minha própria CPU e Assembler! Se você quiser ter um modelo de seguir ou ficou curioso, por favor cheque o projeto em &lt;a href="https://github.com/WasixXD/Wasilewski" rel="noopener noreferrer"&gt;https://github.com/WasixXD/Wasilewski&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O número de bits que você reservar para a instrução também define a quantidade de comando disponíveis, ou seja, se reservar apenas 4 bits para as instruções o máximo de comandos que poderá ter será de 2⁴ ou seja 16.&lt;/p&gt;

&lt;h2&gt;
  
  
  Desafios que irá encontrar
&lt;/h2&gt;

&lt;p&gt;Esse projeto não tem conceitos muito complicados, porém pode sair fora do controle muito rápido, então tome cuidados com os seguintes pontos:&lt;/p&gt;

&lt;h3&gt;
  
  
  Debuggar binário
&lt;/h3&gt;

&lt;p&gt;Escrever binário na mão é muito difícil, considere antes de escrever a sua CPU escrever um Assembler que consiga gerar os binários corretos, isso vai economizar muito do seu tempo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testes
&lt;/h3&gt;

&lt;p&gt;Testes são uma grande base para qualquer projeto, e nesse não é diferente, sempre cheque se sua CPU está realizando os comandos corretamente, e a vantagem é que você não precisa fazer os testes na mesma linguagem que você programou ela, eu por exemplo, fiz ambos CPU e Assembler em C, porém os testes unitários foram feitos em Python apenas pela facilidade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tipo de arquivo
&lt;/h3&gt;

&lt;p&gt;Para carregar os programas escolha bem o tipo de arquivo, se optar por colocar os programas em um arquivo de texto vai ter que ler linha por linha, o que pode geral comportamentos não muitos preditivos já que esses arquivos podem conter espaços ou quebras de linhas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memória
&lt;/h3&gt;

&lt;p&gt;De todas as operações as de memória são as mais difíceis, pois: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não há certeza do que foi escrito no inicio do programa foi sobrescrito&lt;/li&gt;
&lt;li&gt;O Endereço do que foi escrito pode ter sido perdido&lt;/li&gt;
&lt;li&gt;O valor que quer ser armazenado na memória pode ser muito grande ou é diferente do que ela aceita.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em dúvida consulte como as CPUs modernas lidam com esse problema.&lt;/p&gt;

&lt;h2&gt;
  
  
  E depois?
&lt;/h2&gt;

&lt;p&gt;Se você conseguiu superar todas essas adversidades e sucedeu em criar sua CPU, parabéns!. Agora desenvolva em cima dela, corrija os erros, adicione coisas únicas, afinal é a &lt;strong&gt;sua&lt;/strong&gt; CPU e nenhuma Intel ou AMD pode entrar no seu caminho para a supremacia.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Programming is the art of telling another human being what one wants the computer to do. Donald Knuth&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Refêrencias
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.hp.com/ca-en/shop/offer.aspx?p=computer-history-all-about-the-eniac" rel="noopener noreferrer"&gt;https://www.hp.com/ca-en/shop/offer.aspx?p=computer-history-all-about-the-eniac&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.columbia.edu/cu/computinghistory/eniac.html" rel="noopener noreferrer"&gt;https://www.columbia.edu/cu/computinghistory/eniac.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/ENIAC" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/ENIAC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://research.swtch.com/6502" rel="noopener noreferrer"&gt;https://research.swtch.com/6502&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=7w8IeXKstJY&amp;amp;list=WL&amp;amp;index=19&amp;amp;t=824s" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=7w8IeXKstJY&amp;amp;list=WL&amp;amp;index=19&amp;amp;t=824s&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Z5JC9Ve1sfI&amp;amp;t=338s" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=Z5JC9Ve1sfI&amp;amp;t=338s&lt;/a&gt;&lt;/p&gt;

</description>
      <category>c</category>
      <category>assembly</category>
      <category>emulator</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Bootloader 101</title>
      <dc:creator>Lucas Wasilewski</dc:creator>
      <pubDate>Fri, 15 Mar 2024 21:10:52 +0000</pubDate>
      <link>https://dev.to/wasix/bootloader-101-8j</link>
      <guid>https://dev.to/wasix/bootloader-101-8j</guid>
      <description>&lt;p&gt;Olá, meu nome é Lucas Wasilewski e nos últimos três meses eu fiquei obcecado com a matéria de Sistemas Operacionais. De como o computador liga até quando a área de trabalho do Windows aparece, eu queria saber tudo, vou dizer que "diversão" definitivamente não definiu esses meses mas o conhecimento que adquiri com certeza valeu a pena.&lt;/p&gt;

&lt;p&gt;Por mais que estejamos na era da tecnologia, onde:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Os dados são o novo petróleo &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Senti que tinha entrado em um mundo diferente, onde documentação é feita por gente que programa em papel e vivem em uma caverna, onde sua única fonte de luz é um terminal preto e branco. E os tutoriais? Poucos artigos na internet ensinando o básico de assembly e dizendo o quão ele é difícil. Meu objetivo nesse artigo é &lt;strong&gt;encorajar&lt;/strong&gt;, percebi que por mais que seja um assunto muito empolgante (pelo menos para mim) a maioria dos artigos e documentações desencorajam logo no inicio ou tem uma complexidade muito alta para algo que deveria ser fácil, pois, se fosse difícil ou, pior ainda, &lt;strong&gt;impossível&lt;/strong&gt;, não teríamos a quantidade de sistemas operacionais que temos por aí.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como o computador Boota
&lt;/h2&gt;

&lt;p&gt;Tudo começa quando você aperta o botão de ligar do seu computador, após o click é buscado algum programa que esteja na memória RAM, como não tem nenhum então é executado um firmware que já vem de fábrica, nós o conhecemos como: BIOS.&lt;/p&gt;

&lt;p&gt;A primeira função da BIOS é realizar um procedimento chamado POST (Power On Self Test), onde se é feito um teste nos componentes conectados para detectar algum possível problema. Vale ressaltar que esse teste não é algo exclusivo de máquinas pessoais, se é usado em praticamente todos os sistemas embarcados.&lt;/p&gt;

&lt;p&gt;Então a BIOS agora carrega na memória da máquina um executável que possa ser bootável, e para que isso ocorra é necessário ter dois fatores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ter 512 bytes&lt;/li&gt;
&lt;li&gt;Ter um assinatura de boot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Os 512 bytes são para que o bootloader tenha pelo menos um pouco de espaço para trabalhar, já a assinatura de boot são dois bytes com valores mágicos que apenas indicam que aquele é realmente o bootloader. &lt;/p&gt;

&lt;h2&gt;
  
  
  A função do bootloader
&lt;/h2&gt;

&lt;p&gt;O bootloader é nada mais que um programa que é executado pela BIOS, sua função é coletar e especificar algumas variáveis que vão ser usadas depois pelo kernel. Também podemos dizer que seu segundo objetivo é de trocar de Modo real para o Modo protegido ou até para o Modo Longo - Modo real (16 bits) é a forma no qual o seu computador liga, imagine que ele é apenas um estado que pode fazer poucas coisas, como fazer algumas chamadas para a BIOS e acesso a alguns periféricos, também pode usar pouca memória e tem pouca segurança, ou seja, queremos sair o mais rápido possível dele. Já o Modo protegido (32 bits) é o modo no qual já temos acesso a bem mais memória e podemos ter mais liberdade para desenvolver o que bem queremos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seu primeiro bootloader
&lt;/h2&gt;

&lt;p&gt;Certo, chega de teoria, vamos botar a mão na massa, para essa parte você vai precisar de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Um Assembler (NASM)&lt;/li&gt;
&lt;li&gt;Um emulador (QEMU)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verifique como instalá-los na sua distribuição Linux ou até mesmo no Windows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Uma rápida introdução a Assembly
&lt;/h3&gt;

&lt;p&gt;O assembly é uma linguagem de montagem de mais baixo nível que temos, ela é tão próxima do computador que se usa acrônimos para traduzir código hexadecimal/binário que geram os comandos, por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; eax = 1
mov eax, 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;resulta em:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;b8 01 00 00 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onde &lt;code&gt;b8&lt;/code&gt; é o opcode para &lt;code&gt;mov&lt;/code&gt;, e &lt;code&gt;01&lt;/code&gt; é o próprio 1.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PS: se alguém te perguntar essa é a sintaxe da Intel &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Hello World
&lt;/h3&gt;

&lt;p&gt;Agora que você já consegue entender um pouco de assembly, vamos criar um arquivo chamado &lt;code&gt;boot.asm&lt;/code&gt;, no qual vamos escrever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[org 0x7c00]
[bits 16]

jmp $ 

times 510 - ($ - $$) db 0
dw 0xaa55
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sim, parece bruxaria, mas vamos com calma ou melhor linha por linha.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[org 0x7c00]&lt;/code&gt;: Basicamente estamos querendo organizar a memória no qual estamos para começar a partir daquele endereço (&lt;code&gt;0x7c00&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[bits 16]&lt;/code&gt;: Estamos dizendo para o nosso assembler que esse código irá rodar em um ambiente 16 bits (Modo real)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jmp $&lt;/code&gt;: Quase como um loop infinito, damos um &lt;code&gt;jump&lt;/code&gt; para onde já estamos&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;times 510 - ($ - $$) db 0&lt;/code&gt;: Esse dá medo, mas a tradução seria, de onde estamos até o inicio do programa encha de 0s.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dw 0xaa55&lt;/code&gt;: &lt;code&gt;define word&lt;/code&gt; define que os últimos 2 bytes do nosso programa contenham o número mágico (um número que a BIOS sabe que o arquivo é bootável)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se você perceber nosso arquivo tem exatos 512 bytes de memória, ou seja estamos no limite. Para rodar basta compilar com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;nasm boot.asm &lt;span class="nt"&gt;-f&lt;/span&gt; bin &lt;span class="nt"&gt;-o&lt;/span&gt; boot.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e rodar usando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;qemu-system-x86_64 boot.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas, cadê o Hello World? Claro que esse programa apenas boota e faz com que a maquina fique em um estado "hibernado", não vai para frente nem para trás.&lt;br&gt;
Para realmente escrevermos algo é um pouco mais complicado já que teremos que utilizar um &lt;code&gt;interrupt&lt;/code&gt;, ou seja, vamos dizer a BIOS: "Quero escrever algo na tela" e a resposta dela é: "Ok, mas só se você já colocou tudo no lugar certo...".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[org 0x7c00]
[bits 16]


mov ah, 0x0e
mov al, 'H'
int 0x10
mov al, 'e'
int 0x10
mov al, 'l'
int 0x10
int 0x10
mov al, 'o'
int 0x10
mov al, 'W'
int 0x10
mov al, 'o'
int 0x10
mov al, 'r'
int 0x10
mov al, 'l'
int 0x10
mov al, 'd'

jmp $ 

times 510 - ($ - $$) db 0
dw 0xaa55
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que? você achou que teríamos algo chique como &lt;code&gt;print&lt;/code&gt;? Não caro leitor, estamos no mais baixo nível possível (quase escrevendo em binário), nosso único companheiro é a BIOS e eu não confiaria muito nela. De qualquer forma, é claro que esse código pode ser melhorado e ficar menor, mas para motivos de aprendizado, acredito que dessa forma fique de melhor compreensão.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vamos a explicação&lt;/strong&gt;:  Sempre que chamamos &lt;code&gt;int 0x10&lt;/code&gt;, estamos invocando a BIOS para executar uma determinada função. Você pode estar se perguntando: qual função? A resposta é que existem várias funções que ela pode executar e o valor de &lt;code&gt;ah&lt;/code&gt; é o que determina qual função queremos executar naquele momento, então, o valor &lt;code&gt;0x0e&lt;/code&gt; é o código para escrever o que está armazenado em &lt;code&gt;al&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Parabéns! se você chegou até aqui você escreveu seu primeiro Bootloader, claro que ele não é algo muito complexo e apenas escreve &lt;code&gt;HelloWorld&lt;/code&gt; na tela, mas esse é seu primeiro passo e ele é o mais importante que deve ser dado. &lt;/p&gt;

&lt;h2&gt;
  
  
  E depois?
&lt;/h2&gt;

&lt;p&gt;Bem para realmente escrever um bootloader que seja útil teríamos bem mais trabalho, teríamos que definir em que parte da memória nosso Kernel estaria, conseguir algumas informações do disco rígido, definir variáveis globais como a GDT (Global Descriptor Table) e outros. É um tópico definitivamente extenso mas que vale a pena ser estudado, é algo que pode ser alcançado e com certeza deveria ser mais difundido, acredito que na famosa "Era da tecnologia" deveríamos ter mais opções de sistemas operacionais e mais concorrência.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quem tem um bom porquê supera qualquer como.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Referências:&lt;br&gt;
&lt;a href="https://wiki.osdev.org/Expanded_Main_Page"&gt;https://wiki.osdev.org/Expanded_Main_Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.ghaiklor.com/2017/10/21/how-to-implement-your-own-hello-world-boot-loader/"&gt;https://blog.ghaiklor.com/2017/10/21/how-to-implement-your-own-hello-world-boot-loader/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ghaiklor/ghaiklor-os-gcc"&gt;https://github.com/ghaiklor/ghaiklor-os-gcc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/cs/computer-boot-process"&gt;https://www.baeldung.com/cs/computer-boot-process&lt;/a&gt;&lt;/p&gt;

</description>
      <category>assembly</category>
      <category>opensource</category>
      <category>softwaredevelopment</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
