<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Leandro Proença</title>
<link>https://leandronsp.com</link>
<description>low-level curiosity, high-level pragmatism</description>
<atom:link href="https://leandronsp.com/feed.xml" rel="self" type="application/rss+xml"/>
<item>
<title>Path to Vibe Engineering</title>
<link>https://leandronsp.com/articles/path-to-vibe-engineering.html</link>
<guid>https://leandronsp.com/articles/path-to-vibe-engineering.html</guid>
<description><![CDATA[<p>2026, what a year to be alive. AI, LLMs, agents, agentic coding. On one side, the hype train. On the other, narratives built to invalidate everything the hype touches.</p>
<p>In this article I'll dig into the limitations and benefits of using LLMs for coding and how to bring <strong>engineering</strong> back to the landscape, which I call <em>vibe engineering</em>. I aim to help readers on a path to vibe engineering, so this is for working engineers, not first-day coders.</p>
<p>In the end you'll realize that <strong>it's not about speed, it's about confidence</strong>.</p>
<p>Purely empirical, unpretentious, and potentially poetic. Reflections from someone who uses AI daily but doesn't sell courses or posts horror stories. Embrace pragmatism, avoid the radicals, grab a coffee and let's go.</p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p>First things first: my journey to agentic coding</p>
</li>
<li>
<p>Engineering, Agile &amp; AI</p>
</li>
<li>
<p>Vibe (Coding?) Engineering</p>
</li>
<li>
<p>My showcase in AI</p>
</li>
<li>
<p>Approaching the end, here are my takes</p>
</li>
<li>
<p>My 70/30 model: learning and sharpening fundamentals</p>
</li>
<li>
<p>Final words</p>
</li>
<li>
<p>Disclosure</p>
</li>
</ul>
<hr />
<h2 id="first-things-first-my-journey-to-agentic-coding">First things first: my journey to agentic coding</h2>
<p>Back in 2022, I was skeptical. ChatGPT 3.5 was peak hype, while most people were testing these new "chat" capabilities. Developers also started looking into it, and I was no different. However, something was off in my mind: asking a probabilistic model to reason about my code was not accurate. Nor right.</p>
<p>The upcoming years went nuts in terms of AI &amp; coding. I tried my best to get rid of AI from my programming routine. While other developers were struggling with ChatGPT to output a lot of spaghetti code, I was crafting Assembly on live streams. AI outputs were never satisfactory. "They" had no access to my codebase to understand and reason with more confidence.</p>
<p>Fast forward to 2025.</p>
<h3 id="claude-code">Claude Code</h3>
<p>In the middle of 2025, I was still coding manually, like an <em>artisan</em>. At every coding task I used to open my <a href="https://github.com/leandronsp/dotfiles">NeoVim</a> and get to work.</p>
<p>Then, I looked around and realized I was the only one not using AI. I attended a private talk at my current employer and I asked which AI models I could start using since I'm a NeoVim user and I was not keen on using Cursor or another IDE. The answer was: <em>Claude Code</em>.</p>
<p>It changed everything.</p>
<p>Within a week, I noticed a slight increase in speed, but not the <strong>speed boost</strong> people talk about. Something was still missing.</p>
<h3 id="its-not-about-speed-its-about-confidence">It's not about speed, it's about confidence</h3>
<p>Soon I realized that using AI, more specifically Claude Code (Sonnet 3.5, at the time), I could deliver with more <em>confidence</em>. Despite still being capable of writing and reading code, an LLM is orders of magnitude faster at retrieving and processing context from any codebase. For instance, my first steps involved <a href="http://code.claude.com/docs/en/best-practices#explore-first-then-plan-then-code">reading about best practices</a> of using Claude Code. Also, an LLM is way more capable of writing/dumping huge amounts of code - which of course, brings some tradeoffs.</p>
<p>On the other hand, even with flagship models, an LLM <em>does not reason</em> like humans. I think we have more reasoning capacity, understanding context and requirements more broadly than LLMs.</p>
<p>That said, this combination of leveraging an LLM to get context and provide information so we can reason about it, reflect and decide is indeed a <em>game changer</em>. Hence, I started delivering my tasks with <strong>way more</strong> confidence with AI assistance.</p>
<p>As a software engineer, I realized I can implement new features, fix bugs, refactor complex codebases and handle more complex tasks that would take me more time. By applying best <strong>software engineering and agile practices</strong>, I can go beyond, delivering with quality.</p>
<p>But what are those <em>software engineering and agile practices</em> we're talking about?</p>
<hr />
<h2 id="engineering-agile--ai">Engineering, Agile &amp; AI</h2>
<p>I'd like to introduce this topic by first talking about <strong>Software Engineering</strong>. It's not about <em>writing code</em>, it never was, and I'm pretty sure you're sick of hearing this statement many times on the social networks.</p>
<p>Software engineering is about <strong>managing complexity</strong> through practices that give you confidence in what you build. It involves testing, design, refactoring, code review and all that sort of practices many of us do on a daily basis. We should know when to scope something, when to break it down, when to ship and when to <em>say no</em>.</p>
<blockquote>
<p>Yes, sometimes just saying "no" is the right call, but respectful, of course</p>
</blockquote>
<p>As for <strong>agile</strong>, being agile is not about using a tool or some agile framework. Neither about hiring dozens of agile coaches. Truly agile embraces short cycles, working software, responding to change over following a plan. It's a <em>culture</em>.</p>
<p>Everything under an agile culture leans toward feedback loops. Pair programming and retrospectives provide feedback loops. Talking to designers, refining stories, writing spikes, promoting R&amp;D. The whole point is to <em>learn fast, fail fast, and correct course</em>.</p>
<h3 id="fundamentals-matter">Fundamentals matter</h3>
<p>Almost everyone in tech has already faced that moment where something breaks in production, and you realize the bug wasn't a lack of tooling, or a missing requirement. It was <strong>a gap in fundamentals</strong>. Hard to admit that, I know, but the sooner you realize that, the better you get at the software crafting.</p>
<p>When you know the fundamentals, you read code and introspect systems differently. You start having a broader and holistic vision of the whole system. You spot the shortcut before it becomes a regression, and you <strong>ask the right question</strong> before the wrong code ships.</p>
<p>Got it?</p>
<blockquote>
<p>You should <strong>ask the right question</strong> before the wrong solution lands in production</p>
</blockquote>
<p>That's why fundamentals are so important. Even more now, in the <em>AI agentic era</em>. That gut feeling, the one that comes from years of writing, reading, breaking, and fixing code, that's not something an AI model gives you. That's something you <em>earn</em>.</p>
<p>And here's where the irony kicks in: the more capable AI gets at generating code, the more you need fundamentals to work with it, not less. If you can't evaluate what the AI produces, if you can't tell whether the test it wrote actually covers the edge case, if you can't spot the subtle bug in a 3-line diff that looks perfectly clean, then you're not engineering, you're rubber-stamping.</p>
<p>Fundamentals are what turn an LLM's output <strong>from a suggestion into a deliberate decision</strong>.</p>
<h3 id="building-the-bridge">Building the bridge</h3>
<p>Now here's the thing. LLMs don't bring any of that, because they generate code at scale. They won't tell you if that code is right. Furthermore, they don't validate assumptions, don't catch regressions or question a misleading requirement.</p>
<p>All of that is still <em>on you</em>.</p>
<p>So the question isn't whether AI replaces engineering practices, because it won't. The question is how to use <strong>these engineering and agile practices to work with AI</strong>, hence increasing quality while delivering solutions to real problems.</p>
<h3 id="a-note-about-sdd-and-agent-orchestration">A note about SDD and agent orchestration</h3>
<blockquote>
<p>"Okay Leandro, so you mean we should do SDD and orchestrate dozens of agents?"</p>
</blockquote>
<p><em>Hell no</em>, definitely not. I'm not in this game to overcomplicate things. I think that SDD (or Spec-Driven Development) is fine, but the term is overly inflated and many people are taking SDD like <em>creating a lot of markdown files upfront then orchestrating with dozens of agents</em>.</p>
<p>What documentation enthusiasts are doing with SDD and plenty of agents is actually <em>waterfall</em>. I'm not very fond of waterfall for software development, because in the waterfall model we don't have feedback loops and I'm pretty sure that even with all that documentation upfront and multiple agents that dump code at the speed of light, <em>rework will be needed</em>. Requirements will be missed. Someone will forget important details and the AI won't catch those missing requirements as if it was something <em>magical</em>.</p>
<p>I think our industry evolved for decades to finally <strong>get shit done</strong> with agile practices and all of a sudden we're doing waterfall again? Please, no.</p>
<p>What I'm going to share here is a simple process with ancient engineering &amp; AI practices that I believe will work for most people in tech, working for startups or even enterprises. We'll dig further into these practices in the upcoming sections.</p>
<hr />
<h2 id="vibe-coding-engineering">Vibe (Coding?) Engineering</h2>
<p><em>Vibe coding</em> has been a hot topic lately. Karpathy coined the term, and suddenly a massive number of tech enthusiasts became <em>coders</em>. I'm not against it. I believe that vibe coding genuinely unlocks potential for people who want to build products, people who think in terms of what they want to create, not what syntax they need to type.</p>
<blockquote>
<p>I even consider myself a <strong>vibe coder</strong> despite years of experience writing software for a variety of companies using different programming languages. Not to mention I'm seasoned at different levels of architecture, yet I know I always have a lot of knowledge gaps to fill</p>
</blockquote>
<p>But let me bring a new term that I don't see many people talking about: <strong>vibe engineering</strong>. That's not a rejection of vibe coding, but an enhancement instead.</p>
<p>The practices I'm about to walk through aren't new though, and that's exactly the point. Refine, scope, test, pair, review, debug with <em>discipline</em>. These are the things <em>you should have been doing even before AI</em>, practices that kept software reliable before AI, and they're the stuff that keep AI-generated software reliable now.</p>
<p>The difference is that skipping them used to mean a bug in production. Skipping them with AI in the loop means <strong>a bug in production that you didn't even write</strong> and worse, <strong>you can't explain and reason about</strong>.</p>
<p>Let's get into the practices.</p>
<h3 id="engineering-practices-for-the-ai-era">Engineering practices for the AI era</h3>
<p>This is where most AI coding discussions fall apart. Either you're told to "just prompt harder" or you're told to "never trust the output". Both miss the point. The practices aren't new, and they don't change because agentic AI is here, they just become more important.</p>
<p><strong>Refine before you build</strong></p>
<p>This is non-negotiable. I don't necessarily mean to exaggerate on SDD (Spec driven development) - because I believe people are losing the point about SDD and I can talk about it in another post -, but before touching a keyboard, before opening an agent, <strong>you need to know what you're building and why</strong>.</p>
<p>I use a skill <a href="https://github.com/leandronsp/dotfiles/blob/main/claude/.claude/skills/po/SKILL.md">called "po"</a> (which acts like a <em>Product Owner</em>) that forces me to write a PRD - product requirements document -, before any code. Not because I love documentation, but because the agent will hallucinate scope if <em>I don't carve it myself</em>. A vague prompt gives you vague code, whereas a refined one gives you scoped and testable deliverables. Refine first, then build.</p>
<p><strong>Break work into small deliverables</strong></p>
<p>If your prompt asks for more than a few hundred lines of output, maybe better to step back and break down the requirements. I have a personal threshold: above 500 lines of diff and I start questioning whether the scope is right.</p>
<p>Small diffs are reviewable diffs, which make them easy to test and validate. The agent handles <strong>small scoped tasks far better</strong> than large ambiguous ones.</p>
<p>For instance, I usually write a prompt to break down in small pieces <em>before I start using the <code>/po</code> skill</em>:</p>
<pre><code class="sourceCode"><span class="text plain">I want to add RSS feed generation to the blog engine.
The feed should produce valid RSS 2.0 XML with:

- channel metadata (title, link, description, whatever else is needed for a RSS)

- items for each published post (title, link, published date, description)

Before writing any code, let&#39;s break this into small, independent deliverables.
Give me a roadmap with clear order, where each step produces something 
I can refine, test and validate on its own
</span></code></pre>
<p>The key word here is <strong>before</strong>. I'm not asking the agent to build anything yet - because coding agents <em>WILL try to build something</em> -, I'm asking it to plan.</p>
<p>Look, I'm not saying anything about the famous "plan mode", I'm not even using it anymore. The output is a mini roadmap, something like:</p>
<ol>
<li>Define the RSS data model (structs for channel and item)</li>
<li>Implement XML escaping for special characters</li>
<li>Build the feed header (channel metadata)</li>
<li>Build the feed items (post to RSS item mapping)</li>
<li>Wire it all together and validate against the RSS 2.0 spec</li>
</ol>
<p>Of course the <strong>first output is almost always not ready yet</strong>. I refine the ROADMAP. I leave comments before we decide the final version, and iterate over and over until <strong>my requirements are satisfied</strong>.</p>
<p>Then, once I'm comfortable with the roadmap, I refine one deliverable at a time. I take step 1, run <code>/po</code> to write a proper PRD just for that piece, then <code>/dev</code>, <a href="https://github.com/leandronsp/dotfiles/blob/main/claude/.claude/skills/dev/SKILL.md">my skill for coding</a>, to implement it.</p>
<p>Test, validate, deliver. What I learn from step 1 <em>might change now I approach step 2</em>, or even reshape the roadmap itself.</p>
<blockquote>
<p>Yes, that's the truly agile development. Not about SCRUM, not about KANBAN. That's all about <em>embracing changes</em>. If you are in this game and not keen to embrace changes during the whole cycle of software development, well...I have bad news for you</p>
</blockquote>
<p>I don't refine everything upfront, and that's why I'm not very fond of the "SDD" people are selling nowadays. All this <em>SDD thing</em> are a huge pile of requirements that <strong>will change</strong>, no matter how many agents I have working for me. Completely wasteful on my workflow.</p>
<p>I refine the first thing, ship it, learn, adjust if needed, move to the next one. This is agile applied to AI-assisted work, and it works precisely because the agent performs best on small, scoped tasks. Give it a destination, not a <strong>map of the entire country</strong>.</p>
<p><strong>Test first, always</strong></p>
<p>TDD is not a methodology debate for me, it's a survival tool. When an LLM writes code, you need a failing test that proves what you expect before the code even exists. Write the test, see it fail, let the agent make it pass, then verify.</p>
<p>This feedback loop, <code>RED -&gt; GREEN -&gt; REFACTOR</code> is nothing new, but it's the closest thing to determinism you'll get from a <em>probabilistic model</em>.</p>
<blockquote>
<p>I wrote an article this year about <a href="https://leandronsp.com/articles/taming-non-determinism-from-logic-gates-to-llms">Taming non-determinism: from logic gates to LLMs</a>, in case you want to have a deeper understanding of non-determinism</p>
</blockquote>
<p>My <a href="https://github.com/leandronsp/dotfiles/blob/main/claude/.claude/skills/dev/SKILL.md">skill "dev"</a> relies on TDD from the very start. I invite you to take a look into it.</p>
<p><strong>Pair with the agent</strong></p>
<p>I don't mean to sit back and watch it generate 800 lines. I mean <strong>treat the agent like a pair programming partner</strong>. You drive, the agent suggests and reviews. Or the agent drives, you suggest and review.</p>
<p>Again, my <code>/dev</code> skill covers different modes for development:</p>
<p>a) <code>agent-pair</code> - two subagents working adversarially, one writes, one gates</p>
<p>b) <code>solo</code> - the agent does the work but narrates every step</p>
<p>c) <code>pair-with-me</code> - me and the agent actually pairing, discussing before coding</p>
<p>At any mode, the skill is ready to work with TDD, no bullshit included. Pick the mode that matches the task, but always stay in the loop.</p>
<p><strong>Review the output</strong></p>
<p>Every. Single. Time. An LLM's output is a suggestion, not a decision. My <a href="https://github.com/leandronsp/dotfiles/blob/main/claude/.claude/skills/review/SKILL.md">"review" skill</a> spawns three parallel reviewer agents. One for security, one for performance, and one for quality. Then a <em>red-team auditor</em> that checks the reviewers themselves. It sounds excessive until you've shipped a bug that looked perfectly clean in a 400-line diff. If you're not reviewing, you're rubber-stamping.</p>
<p>Even so, you must review the auditor's final review. Don't take <em>any LLM output</em> as a source of truth. An LLM's output <strong>should never be the final destination</strong>, but using it with the correct tooling, it'll take you <em>some steps forward</em>.</p>
<p><strong>Debug with discipline</strong></p>
<p>When something breaks, don't just prompt the agent to "fix it". I know, it's tempting to drop a screenshot and ask the LLM to solve it. With a good LLM model and correct skills, this naive prompting will provide the right output very often, but sometimes it simply won't get out of the loop. Humans get stuck, so do AIs.</p>
<p><em>Tip:</em> reproduce the bug with a failing test first. Actually, that's a practice I've always tried to apply on my workflow way before agentic AI. If there's some skill I'd pick and say that every good engineer should sharpen, it's the <strong>ability to reproduce anything with a failing test</strong>. Many engineers, including the senior ones, fail at this important step while debugging.</p>
<blockquote>
<p>In a distributed system, debugging is very hard. Sometimes a failing test is not enough, but if you spend some time trying to write as many failing tests as possible, you'll eventually get there. The "test-driven" mindset is winner IMHO. "Follow the data and write a failing test for it" is the best engineering advice I've ever heard.</p>
</blockquote>
<p>Speaking of AI, I have a <a href="https://github.com/leandronsp/dotfiles/blob/main/claude/.claude/skills/bugfix/SKILL.md">"bugfix" skill</a> that enforces this: understand the bug, scout the codebase, write a failing test for the <em>right reason</em>, then fix. No test, no fix. Of course, agents usually write any poor test just to make it pass, but if you enforce it with a good skill, the agent will go to the right path guarded by good engineering practices <strong>you</strong> provided in the skill or prompt.</p>
<p>The agent will happily patch symptoms all day if you let it. A failing test forces both you and the agent to prove you actually <strong>fixed the root cause</strong>.</p>
<p>Now time to show what all this looks like in practice.</p>
<hr />
<h2 id="my-showcase-in-ai">My showcase in AI</h2>
<p>I want to highlight <em>three real use cases</em> where I applied those engineering practices and could be successful with it. Despite using AI for personal projects, I've been using agentic AI for <strong>delivering value to real customers in production</strong>, critical projects and demanding features. It's not a playground as many may argue: <em>it's serious work</em>.</p>
<h3 id="case-1-debugging-a-pdf-rendering-bug">Case 1: Debugging a PDF rendering bug</h3>
<p>I was working on a task where customers weren't able to download <em>some PDFs</em> generated by the platform, affecting critical workflows in production. Pay attention to the "some PDFs" part. Not all of them.</p>
<p>Logs pointed that some PDFs were failing to parse, leading the troubleshooting to go look at <em>broken PDFs</em>. In the "PDF world", everything is messy. Writer and reader tools don't always come to an agreement, despite the PDF itself having a public specification.</p>
<p>I got some broken PDFs and started looking into them, as they were opening normally in my PDF reader. The problem was somewhere in our <strong>merge PDF process</strong>, which is backed by <em>Ghostscript</em>, a well-known tool for printing and PDF manipulation.</p>
<p>With this information in place, instead of pasting the bug report into an agent and saying "fix it", I called my <code>/bugfix</code> skill. And you'll see how a good skill and a failing test win.</p>
<p>The skill started by understanding the bug: what's broken, when it happens, what's the expected behaviour. Then it scouted the codebase, reading the PDF parsing code, tracing data flow, checking git history for recent changes.</p>
<p>It came back with a hypothesis: the <em>outline builder</em> within the PDF content was pushing a parent reference into its own children, creating a cycle.</p>
<p>The critical step: write a test that fails. The skill produced a minimal test case that created a PDF outline with two levels, asserted that traversing the outline tree terminates, and the test failed, proving the bug existed.</p>
<blockquote>
<p>Once we can prove the bug exists with the <em>right failing test</em>, the dopamine levels skyrocket :P</p>
</blockquote>
<p><strong>The "senior" moment</strong></p>
<p>First, I let the AI go for a fix, but as soon as I noticed it got stuck in a loop after two or three failed approaches, I decided to enter the loop and become a <strong>real senior</strong>. My instinct was that something in the <em>Ghostscript</em> process was not recognizing the circular outlines. But Ghostscript is an external tool that I don't have control over. The only thing I could do was to try a variety of different <em>command line flags</em> in a "trial-and-error process". Not good.</p>
<p>The <em>senior</em> moment became when I asked the agent to analyze the <strong>Ghostscript process</strong> using some tooling in my macOS, which is an operating system based on BSD.</p>
<p>For freak's sake, the agent pulled out the utility <code>sample</code> against the <code>gs</code> process and then got the process's call stack.</p>
<p>And <em>boom</em>! My little boy got the exact part of the <em>Ghostscript stacktrace</em> where the circular reference was stuck in an infinite loop. The fix was just using the correct flag to "ignore" circular outlines. Easy peasy.</p>
<p>Could I hit the same destination without AI? Hell yes, but I would have spent too many hours on it, maybe days. The whole process took me <strong>only 20 minutes</strong>. More importantly, the bug is now captured in a test. If it ever regresses, I'll know immediately.</p>
<h3 id="case-2-building-a-feature-from-scratch-product-to-code">Case 2: Building a feature from scratch, product to code</h3>
<p><a href="https://github.com/leandronsp/chesswav">ChessWAV</a> is a Rust project that turns chess games into audio. It's not a simple CRUD. It's chess logic, graph manipulation, sine waves, mathematical stuff and all. The REPL had a working board display, but it was appending a new board after every move, scrolling the terminal endlessly. No move history, no file labels on both sides. I wanted to fix that.</p>
<p>Instead of jumping to code, I started with <code>/po in-place board rendering with move list sidebar</code>. The skill walked me through writing a proper PRD: what the rendering should look like, how ANSI cursor escapes work for in-place updates, how each display strategy (sprite, unicode, ascii) affects layout calculations. Edge cases like switching display modes mid-game and cursor-up calculations across different board heights.</p>
<blockquote>
<p>In case you don't believe me and think I could be making this up, please refer to my <a href="https://github.com/leandronsp/chesswav/issues/9">issue in Github</a>, the <a href="https://github.com/leandronsp/chesswav/pull/10">pull request</a>, all of it done <strong>during a live stream</strong> (pt-BR) in my <a href="https://www.youtube.com/watch?v=Da4BYe_gV0Y">Youtube channel</a></p>
</blockquote>
<p>The PRD took maybe ten minutes and saved me from <em>scope creep</em> on what could have been a bottomless rendering rabbit hole. Of course I had two or three iterations before I agreed on the PRD, but that's the true productivity power of using agentic AI IMHO.</p>
<p>After the issue was created, I handed it to <code>/dev</code>, no further prompting, just pasted the issue URL, then it scouted the codebase, asked clarifying questions about the existing display strategy pattern, proposed test cases, and only after did it start coding.</p>
<p>Every cycle was RED then GREEN. The whole feature shipped in three incremental diffs: cursor-up logic and layout height calculation first, then the move list sidebar, then the re-rendering flow that ties it together.</p>
<p>Before opening the PR, I ran the <code>/review</code> skill which gloriously gave me some hints on refactoring. I looked at the code afterwards, though it wasn't too bad, I suggested some refactoring to make the code cleaner. You can see the <a href="https://github.com/leandronsp/chesswav/pull/10">code yourself</a>, as the final PR was only 369 additions across 3 files. Not 2000 lines of "here's the whole thing". Small, reviewable, tested increments. Each one I could understand, validate and <em>ship with confidence</em>.</p>
<p>And before someone argues:</p>
<blockquote>
<p>But Leandro, you're doing engineering as usual. Why the need of using AI at all?</p>
</blockquote>
<p>Let's be honest here. I'm a seasoned software engineer and I'm <strong>pretty sure</strong> I couldn't deliver this kind of complexity in a matter of minutes or hours with confidence. That's not AI-slop, go check yourself. This use case is the difference between prompting "add in-place board rendering" and <strong>engineering your way to it</strong>.</p>
<p>I kindly invite you to truly experiment on this flow. Give engineering &amp; AI an honest chance.</p>
<blockquote>
<p>Unless you're a radical who's not keen to learn and evolve. If that's the case, well...you shouldn't be reading my blog at this point. Feel free to close this tab now. Radicals are not welcome here.</p>
</blockquote>
<h3 id="case-3-review-before-you-ship">Case 3: Review before you ship</h3>
<p>I had just finished a refactor of the markdown rendering pipeline for <a href="https://github.com/leandronsp/devtui">DevTUI</a>, the blog engine I created, using it to write this very blog post. The diff was around 300 lines, which is already pushing my comfort zone. I ran <code>/review</code> on the changes.</p>
<p>The skill pulled the diff, launched a scout to understand the surrounding code, then spawned three parallel reviewers. Security checked for injection risks in the HTML output. Performance looked for unnecessary allocations in the hot path. Quality examined whether the refactor actually improved the design or just moved code around.</p>
<p>Then the red-team auditor cross-checked all three reports, <strong>catching a false positive</strong> from the security reviewer and flagging a blind spot the others missed: the refactor had changed the order of markdown preprocessing steps, which would silently break nested blockquotes on certain inputs.</p>
<p>I would not have caught that by skimming the diff. <strong>The fix was two lines</strong>, but finding it required reading the diff against the full context of how the pipeline processes input.</p>
<p>That's what review gives you, not just "looks good" - which many developers already do -, but actual evidence that your change does what you think it does.</p>
<hr />
<h2 id="approaching-the-end-here-are-my-takes">Approaching the end, here are my takes</h2>
<p>Everything I described above, the skills, the TDD discipline, the review workflow, <strong>it's not magic</strong>. It's configuration and intentionality. Next are a few things from my setup that make this work. Also comes with a few takes, read it with discretion.</p>
<h3 id="write-your-own-claude.md-or-agents.md">Write your own CLAUDE.md (or AGENTS.md)</h3>
<p>This is the most impactful single thing you can do. My personal <code>~/.claude/CLAUDE.md</code> (check the correct configuration and conventions for your harness) is my <a href="https://github.com/leandronsp/dotfiles/blob/main/claude/.claude/CLAUDE.md">development philosophy distilled</a> into a file the agent reads on every session. It should be short. It says things like "deletion beats addition", "TDD for non-trivial work", "search the codebase first", "baby steps". Without it, the agent follows its own defaults, and those defaults are optimized for generating output, not for <em>engineering</em>.</p>
<p>Write yours, be opinionated. The more specific, the better.</p>
<h3 id="create-skills-for-your-recurring-workflows">Create skills for your recurring workflows</h3>
<p>My <code>/po</code>, <code>/dev</code>, <code>/bugfix</code> and <code>/review</code> skills encode processes I actually follow. Not theoretical best practices, but the way I work. A skill is just a markdown file that tells the agent what to do, step by step, with gates and waits. If you find yourself repeating the same process, write it down once and let the skill enforce it. That's how you get TDD from a model that defaults to dumping code.</p>
<p>And that's the main reason I avoid importing other's skills I don't fully understand or control. I avoid using repos with thousands of skills or "following some framework". I think we should pick up skills with caution. Always better to start from a reference and then craft a few of your own.</p>
<p>Feel free to <a href="https://github.com/leandronsp/dotfiles/tree/main/claude/.claude/skills">pick up my skills</a>, but use your agent to explain about them, refine and adapt to your own workflow.</p>
<h3 id="set-up-hooks-for-flow-state">Set up hooks for flow state</h3>
<p>I <a href="https://github.com/leandronsp/dotfiles/tree/main/claude/.claude/hooks">have a shell hook</a> that plays a sound and flashes my Tmux window when the agent finishes, so I don't sit staring at a terminal waiting. Another hook loads context from my Obsidian vault at session start, so the agent already knows my project history. Small things that compound.</p>
<h3 id="use-adversarial-agents">Use adversarial agents</h3>
<p>My <code>/dev</code> skill runs two subagents in pair mode: a driver that writes code and a navigator that gates every step. The navigator doesn't rubber-stamp. It pushes back on test scope, challenges minimum implementations, flags premature abstractions. This costs a bit more tokens, I know, but saves you from the model's tendency to over build.</p>
<p>One agent writing unchecked code is vibe coding. Two agents checking each other is closer to pair programming.</p>
<h3 id="its-not-just-claude">It's not just Claude</h3>
<p>I've been running GLM 5.1 and Kimi 2.6 for personal projects and I'm genuinely impressed. Both are strong models that hold their own for coding tasks. The important thing is that my skills, my CLAUDE.md, my memory, they're all model-agnostic configuration files. I can switch models and the process stays the same.</p>
<p>I've been using opencode and pi-agent alongside Claude Code, and both harnesses read from the same <code>~/.claude</code> configuration. Same skills, same rules, same workflows. Pi-agent works with extensions instead of Claude's hook system, so there are slight differences, but the core setup translates. They are <strong>way cheaper</strong> too.</p>
<p>The discipline is in the configuration, not in the model. Pick whatever works for your budget and preference, but bring your own process.</p>
<h3 id="ai-only-reflects-your-capability">AI only reflects your capability</h3>
<p>I'm going to be blunt here. The quality of AI-assisted work is <strong>directly proportional to the quality of the person guiding it</strong>. If you don't know how to write a test, the agent won't write a meaningful test. If you don't know how to review a diff, the agent's output passes your eyes without triggering a single alarm. If you don't understand your system's architecture - and here's the catch -, <em>you can't tell the agent where to look</em>, and it will simply <strong>guess</strong>. Sometimes right, often wrong, and you won't know which is which.</p>
<p>This is not a flaw in AI. It's a mirror. The agent amplifies what you bring. Bring fundamentals, and you get leverage. Bring ignorance, and you get confident ignorance at scale.</p>
<p>That's why I keep my craft projects. Assembly, Rust from scratch, neural networks without frameworks. Not because I'm nostalgic, but because that's where I build synaptic connections that make me deliver better with AI.</p>
<p>Skip it, and you're not vibe engineering. You're <em>vibe hoping</em>.</p>
<hr />
<h2 id="my-7030-model-learning-and-sharpening-fundamentals">My 70/30 model: learning and sharpening fundamentals</h2>
<p>Seventy percent AI-assisted work, shipping, delivering. Thirty percent manual coding, learning, building intuition. <strong>The 30% is what makes the 70% work</strong>. Without fundamentals, you become a prompt engineer who can't debug. With only fundamentals, you ship slower than the field. <em>Why not both?</em></p>
<p>Again, <strong>avoid the radicals</strong>.</p>
<blockquote>
<p>"But how to keep learning and sharpening the fundamentals?"</p>
</blockquote>
<p>How do I keep the 30% effective? How do I code, learn, and get intuition from the decisions? Ironically, the answer is in the <em>LLM itself</em>. Yes, we can leverage the LLM as a pair programming partner, remember the topic from earlier?</p>
<p>When I'm coding manually, I leave the agent open reading my code, doing TDD with me, where <strong>I'm the driver, the agent is the navigator</strong>. It watches my changes and provides feedback in real-time, which I can reason about, get intuition and iterate until I get a solution that I fully understand. Whenever I feel I'm good with the current development, the rest is only ceremony and boilerplate, then I switch to vibe coding and the agent finishes the boring work.</p>
<p>My skill <code>/dev</code> also covers this mode, which I call <code>pair-with-me</code>. Every time I want to code and learn something new, I'm using this mode. Otherwise, I'm doing engineering around agents as I already distilled throughout this whole article.</p>
<p>Here's <a href="https://www.youtube.com/watch?v=GWQ1OxnOKcQ">another live stream</a> where I'm studying using this technique (pt-BR), which I use daily too.</p>
<hr />
<h2 id="final-words">Final words</h2>
<p>I started this article saying I'd been procrastinating on writing it. Now I understand why. This isn't a hot take or a framework pitch. It's the distillation of months of trial and error, of shipping real features to real customers, of getting stuck in agent loops and finding my way out.</p>
<p>The message is simple: <em>vibe coding is real and it's powerful</em>. But vibe coding without engineering is just faster ways to produce code you can't explain, debug or maintain.</p>
<p><strong>Vibe engineering</strong> is what happens when you take that speed and pair it with discipline. Not the kind of discipline that slows you down, but the kind <strong>that makes speed sustainable</strong>.</p>
<blockquote>
<p>Yet I can't understand why so many "seniors" struggle to see this simple conclusion</p>
</blockquote>
<p>And for the love of whatever you believe in, <strong>don't skip the fundamentals</strong>. Any content about <strong>software architecture</strong> is always the best option. Look, I'm not saying anything about <em>SOLID or Design Patterns</em>, because IMHO those are just <em>coding design</em>, not <em>software architecture</em>. Safe to skim them.</p>
<p>I suggest you find your path to <strong>master how systems are created and how they communicate to each other</strong>. That's the <em>sweet spot</em> for software engineering, and that's an ongoing ability we're never done with.</p>
<h3 id="books-i-recommend">Books I recommend</h3>
<p>If there's one thing I learned about reading tech books, it's that most of them age like milk. Framework-specific books, language tutorials, "building X with Y", they're outdated before the ink dries. I always avoid those.</p>
<p>What I look for are books that are <strong>timeless</strong>. Books about principles, tradeoffs, and how systems think, not configuration tutorials or one random opinion from a guy from Arizona. You read timeless books once and they keep paying dividends years later because the problems they address haven't changed. We still distribute systems, communicate between services and deal with complexity and uncertainty.</p>
<p>Here are five that I keep coming back to:</p>
<ul>
<li>
<p>The Mythical Man-Month, Fred Brooks. This book is from 1975 (yup, that old) and it's still right. Adding people to a late project makes it later. Communication overhead grows quadratically. There's no silver bullet.</p>
</li>
<li>
<p>The Pragmatic Programmer, Hunt &amp; Thomas. This book taught me that programming is not about syntax, it's about thinking. DRY, tracing bullets, <strong>debugging by thinking</strong>. It's practical without being tied to a language or framework. Timeless.</p>
</li>
<li>
<p>Fundamentals of Software Architecture, Richards &amp; Ford. This goes straight to the sweet spot I mentioned. Architecture patterns, tradeoffs, modularity, how to make decisions when there's no right answer. The chapter on <em>tradeoff analysis</em> alone is worth the whole book. You read it and you'll never be the same developer.</p>
</li>
<li>
<p>Architecture the Hard Parts, Richards, Ford, Mishra &amp; Sadalage. The sequel in spirit. Where most architecture books show you the happy path, this one shows you the distributed transactions. This is the book that teaches you how systems communicate with each other and why that's where the real complexity lives.</p>
</li>
<li>
<p>Extreme Programming Explained: Embrace Change, Kent Beck. The book that gave agile its heart. Not the agile of frameworks and certifications, the agile of short cycles, continuous feedback, and actually embracing change instead of pretending you can plan it away. Everything I said about <em>feedback loops</em>, small deliverables, test-first, pair programming, Kent Beck was writing about it in 1999. <strong>Embrace change</strong>.</p>
</li>
</ul>
<p>These five books, together, cover exactly what I mean by the sweet spot. How systems are created, how they communicate, how to manage complexity, and how to make decisions under uncertainty. Read them in any order, but read them.</p>
<h3 id="and-for-the-best...">And for the best...</h3>
<p><em>Software engineering is dead. Long live software engineering.</em></p>
<hr />
<h2 id="disclosure">Disclosure</h2>
<p>This article was written using a TUI editor I built in Rust called <a href="https://github.com/leandronsp/devtui">DevTUI</a>, with the support of GLM 5.1 via pi-agent for drafting and context.</p>
<p>Every single paragraph came from my head. The LLM never wrote a sentence for me. It questioned, suggested, challenged, and I decided. Much like I use it <em>daily</em>.</p>
<p>The identity, opinions, takes and bad jokes in this article are 100% mine. The AI was a pair, not a ghostwriter.</p>
]]></description>
<pubDate>2026-05-02</pubDate>
</item>
<item>
<title>Palíndromo utilizando dois UNIX signals, uma fila e uma pilha</title>
<link>https://leandronsp.com/articles/resolvendo-palíndromo-com-apenas-dois-unix-signals-uma-fila-e-uma-pilha.html</link>
<guid>https://leandronsp.com/articles/resolvendo-palíndromo-com-apenas-dois-unix-signals-uma-fila-e-uma-pilha.html</guid>
<description><![CDATA[<p>Palíndromos, palíndromos. Você deve estar se perguntando como veio parar aqui, muito provavelmente já sem paciência pra este assunto por conta da recente trend do twitter no último fim de semana que, convenhamos, ultrapassou alguns limites:</p>
<p><img src="/images/untitled-2-screenshot-2026-04-27-at-17-48-31.png" alt="Print de trending topics do Twitter mostrando &#39;Palíndromo&#39; no topo da Bolha Dev" /></p>
<p>O assunto subiu para o trending topics global e os gringos ficavam se perguntando:</p>
<blockquote>
<p>Why is palindrome such a hot topic in Brazil now?</p>
</blockquote>
<p><em>Mal sabem eles que aqui no Brasil TUDO vira meme, até mesmo o "67" deles. Melhoramos o "67" e escalamos para um nível diferenciado. Google pesquisar.</em></p>
<p>Não vou entrar em detalhes, mas basicamente a "treta" foi criada porque alguém mencionou que não conseguia contratar desenvolvedores pois nenhum candidato passava no teste do palíndromo. O negócio escalou. Teve implementação de palíndromo de todos os tipos e também teve muito meme, que foi a melhor parte pra mim.</p>
<p>Mas vamos lá, quem acompanha meu blog sabe que não escrevo por escrever. Eu gosto de explorar um assunto técnico e ir fundo (lá ele), captando e compartilhando conhecimento no meio do caminho. É pra isso que estou aqui.</p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#first-things-first">First things first</a></p>
</li>
<li>
<p><a href="#palindromaniacs">Palindromaniacs</a></p>
<ul>
<li><a href="#mas-a-gente-%C3%A9-diferente-unix-signals--queue--stack">Mas a gente é diferente: UNIX signals + queue + stack</a></li>
</ul>
</li>
<li>
<p><a href="#unix-signals-como-forma-de-comunica%C3%A7%C3%A3o">UNIX signals como forma de comunicação</a></p>
<ul>
<li><a href="#enviando-bin%C3%A1rio-com-dois-unix-signals">Enviando binário com dois UNIX signals</a></li>
<li><a href="#montando-bytes-a-partir-dos-bits">Montando bytes a partir dos bits</a></li>
<li><a href="#enviando-strings-inteiras">Enviando strings inteiras</a></li>
</ul>
</li>
<li>
<p><a href="#marcando-o-fim-da-mensagem">Marcando o fim da mensagem</a></p>
</li>
<li>
<p><a href="#fila-e-pilha-o-teorema-central">Fila e pilha: o teorema central</a></p>
<ul>
<li><a href="#conectando-tudo">Conectando tudo</a></li>
</ul>
</li>
<li>
<p><a href="#bonus-points-handshake-ftw">Bonus points: Handshake FTW</a></p>
</li>
<li>
<p><a href="#conclus%C3%A3o-gloriosa">Conclusão gloriosa</a></p>
</li>
</ul>
<hr />
<h2 id="first-things-first">First things first</h2>
<p>E a pedido de muitos, incluindo o brabíssimo Navarro, vamos fazer uma implementação do <em>palíndromo</em> em Bash:</p>
<p><img src="/images/untitled-2-screenshot-2026-04-27-at-17-55-06-1.png" alt="Tweet do Rodrigo Navarro (@rdrnavarro) cobrando a versão canônica do palíndromo em Bash" /></p>
<blockquote>
<p>Por que Bash, Leandro?</p>
</blockquote>
<p>Porque entre todos os que submeteram soluções para a <a href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3">1ª Rinha de Backend</a> e as subsequentes, eu fui o <a href="https://github.com/leandronsp/rinha-backend-bash">primeiro da linhagem</a> com uma submissão funcional porém nada performática.</p>
<p>O que era pra ser um meme no Twitter, acabou virando o apelido "carinha do Bash". É sobre isso.</p>
<hr />
<h2 id="palindromaniacs">Palindromaniacs</h2>
<p>Uma das implementações mais comuns para <em>palindromania</em> chama-se <strong>two pointers</strong>, onde definimos dois ponteiros na string e vamos comparando o primeiro com o último, o segundo com o penúltimo e assim por diante, mexendo nos ponteiros até chegar na <em>metade da string</em>. Se todas as comparações derem certo, a palavra é palíndromo.</p>
<p>Em Bash dá pra implementar isso de forma mais legível usando <em>substrings</em>, que é prima do two pointers:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="meta function shell"><span class="entity name function shell">is_palindrome</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
<span class="meta function-call shell">    <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">input</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span><span class="punctuation definition string end shell">&quot;</span></span></span></span>
<span class="meta function-call shell">    <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">length</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="keyword operator arithmetic shell">#</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">input</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span></span></span>

    <span class="keyword control for shell">for</span><span class="meta group for shell"> <span class="meta group arithmetic shell"><span class="punctuation section arithmetic begin shell">((</span>i<span class="keyword operator assignment shell">=</span><span class="constant numeric integer decimal shell">0</span><span class="punctuation separator shell">;</span> i<span class="keyword operator logical shell">&lt;</span>length<span class="keyword operator arithmetic shell">/</span><span class="constant numeric integer decimal shell">2</span><span class="punctuation separator shell">;</span> i<span class="keyword operator arithmetic shell">++</span><span class="punctuation section arithmetic end shell">))</span></span> do</span>
<span class="meta function-call shell">        <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">leftmost</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">input</span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring begin shell">:</span></span><span class="meta group expansion parameter shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">i</span></span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring end shell">:</span></span><span class="meta group expansion parameter shell"><span class="constant numeric integer decimal shell">1</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span></span></span>
<span class="meta function-call shell">        <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">rightmost</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">input</span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring begin shell">:</span></span><span class="meta group expansion parameter shell"><span class="meta group expansion arithmetic shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">((</span>length<span class="keyword operator arithmetic shell">-</span><span class="constant numeric integer decimal shell">1</span><span class="keyword operator arithmetic shell">-</span>i<span class="punctuation section parens end shell">))</span></span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring end shell">:</span></span><span class="meta group expansion parameter shell"><span class="constant numeric integer decimal shell">1</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span></span></span>

        <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">leftmost</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="keyword operator logical shell">!=</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rightmost</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="support function test end shell">]</span></span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="keyword control return shell">return</span></span><span class="meta function-call arguments shell"> 1 <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Error status code, IS NOT a palindrome</span><span class="comment line number-sign shell">
</span></span>    <span class="keyword control done shell">done</span>

    <span class="meta function-call shell"><span class="keyword control return shell">return</span></span><span class="meta function-call arguments shell"> 0 <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Success status code, IS a palindrome</span><span class="comment line number-sign shell">
</span></span><span class="punctuation section braces end shell">}</span></span>
</span></code></pre>
<p>Sem entrar muito em detalhes, vou explicar pois Bash:</p>
<ul>
<li>
<p><code>local input="$1"</code>: joga o primeiro argumento da linha de comando na variável input</p>
</li>
<li>
<p><code>local length=${#input}</code>: pega o tamanho do input</p>
</li>
<li>
<p><code>for ((i=0; i&lt;length/2; i++))</code>: itera sobre cada caractere da string até a metade</p>
</li>
<li>
<p><code>local leftmost=${input:$i:1}</code>: pega 1 caractere a partir da posição <code>$i</code>, ou seja, o mais a esquerda possível</p>
</li>
<li>
<p><code>local rightmost=${input:$((length-1-i)):1}</code>: pega 1 caractere a partir da posição <code>length-1-i</code>, que vai andando do último pra dentro conforme <code>i</code> cresce, ou seja, o mais a direita possível</p>
</li>
<li>
<p><code>[ "$leftmost" != "$rightmost" ] &amp;&amp; return 1</code>: compara os dois, se forem diferentes, a palavra <strong>não é um</strong> palíndromo</p>
</li>
</ul>
<p>Caso não encontre nenhuma divergência nas comparações, então a palavra <strong>é um</strong> palíndromo, portanto <code>return 0</code> com sucesso.</p>
<p>Outras implementações que podemos encontrar:</p>
<ul>
<li>
<p>inverte a string e compara: essa é mais naive, geralmente <code>one-liner</code> e não requer muitos neurônios</p>
</li>
<li>
<p>recursão: mais idiomática em linguagens funcionais</p>
</li>
<li>
<p>stack: empilha a primeira metade, depois lê a segunda metade desempilhando e comparando a cada caractere</p>
</li>
<li>
<p><em>e mais</em>: deque (double-ended queue), programação dinâmica, etc tal e coisa</p>
</li>
</ul>
<h3 id="mas-a-gente-é-diferente-unix-signals--queue--stack">Mas a gente é diferente: UNIX signals + queue + stack</h3>
<p>Implementar palíndromo no modo tradicional faria Bash e este post serem mais do mesmo. Não tem graça, Bash precisa ser requintado. Então resolvi <del>ser o diferentão</del> inovar e resolver este problema utilizando apenas <strong>dois sinais UNIX, uma fila e uma pilha</strong>. A ideia, em três passos:</p>
<ul>
<li>
<p>um <code>sender</code> que manda a string bit a bit via signals</p>
</li>
<li>
<p>um <code>receiver</code> que monta cada caractere e empilha em duas estruturas (FIFO e LIFO)</p>
</li>
<li>
<p>no final, drena as duas estruturas. Se todo <code>pop</code> da pilha bater com todo <code>dequeue</code> da fila, é <strong>palíndromo</strong>.</p>
</li>
</ul>
<p><strong>FIFO</strong> significa <em>first-in, first-out</em>. É a nossa fila. E <strong>LIFO</strong> significa <em>last-in, first-out</em>, neste caso nossa pilha. Tudo nosso.</p>
<p><img src="/images/resolvendo-pal-ndromo-com-apenas-dois-unix-signals-uma-fila-e-uma-pilha-screenshot-2026-04-27-at-23-02-12.png" alt="Meme do Bugs Bunny soviético no espírito &#39;camarada, é tudo nosso&#39;" /></p>
<p>Basicamente, estamos explorando duas estruturas de dados primordiais da computação para verificar se uma palavra é palíndromo. E não só, estamos enviando a string <a href="https://leandronsp.com/articles/entendendo-unix-pipes-3k56">utilizando IPC</a> de uma forma bastante primitiva, com o <em>envio de sinais</em>.</p>
<p>Se quiser saber mais detalhes sobre UNIX signals e como os utilizei para construir um pequeno <em>broker de mensageria</em>, veja meu artigo <a href="https://leandronsp.com/articles/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals">You don't need Kafka: building a message queue with only two UNIX signals</a>. Lá eu explico o necessário sobre envio de sinais e também como implementei a modulação/demodulação de sinais para bits.</p>
<hr />
<h2 id="unix-signals-como-forma-de-comunicação">UNIX signals como forma de comunicação</h2>
<p>O intuito deste artigo não é aprofundar muito nos sinais UNIX, uma vez que já abordei com profundidade no polêmico artigo anterior. Mas a seguir temos um exemplo bastante simples para estarmos na mesma página:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">!/usr/bin/env bash</span><span class="comment line number-sign shell">
</span>
<span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>echo &quot;Received signal SIGUSR1&quot;<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR1</span>

<span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>PID: <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">$</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
<span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Rodar em outra sessão shell: kill -SIGUSR1 <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">$</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>

<span class="keyword control while shell">while</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
    <span class="meta function-call shell"><span class="variable function shell">sleep</span></span><span class="meta function-call arguments shell"> 0.5</span> <span class="keyword operator logical or shell">||</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span>
<span class="keyword control done shell">done</span>
</span></code></pre><pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash receiver.sh</span>
<span class="meta function-call shell"><span class="variable function shell">PID:</span></span><span class="meta function-call arguments shell"> 54112</span>
<span class="meta function-call shell"><span class="variable function shell">Rodar</span></span><span class="meta function-call arguments shell"> em outra sessão shell: kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 54112</span>
</span></code></pre>
<p>Em outra sessão:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 54112</span>
</span></code></pre>
<p>Com isto, <em>receiver</em> imprime <code>Received signal SIGUSR1</code> pra cada vez que enviarmos o sinal!</p>
<p>O que é um sinal, afinal? Pra quem nunca ouviu falar, signals são a forma mais primitiva de IPC no UNIX. Você pode mandar <code>kill -SIGTERM</code> num processo pra encerrá-lo, <code>kill -SIGINT</code> pro mesmo efeito de <code>Ctrl+C</code>, e por aí vai. A graça é que o processo que recebe pode <em>interceptar</em> esses signals e <em>fazer o que quiser</em>. Esta é a famosa técnica de <strong>signal trap</strong>.</p>
<blockquote>
<p>Nossa, Leandro, mas o <code>kill</code> não "mata" o processo?</p>
</blockquote>
<p>Não, ele serve para envio de sinais, incluindo os clássicos <code>SIGTERM</code> e <code>SIGKILL</code>. Reforço: veja <a href="https://leandronsp.com/articles/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals">meu artigo de UNIX signals</a> para entender as nuances.</p>
<h3 id="enviando-binário-com-dois-unix-signals">Enviando binário com dois UNIX signals</h3>
<p>Quando falamos de IPC primitivo tal como UNIX signals, não conseguimos enviar uma "mensagem" no formato que estamos acostumados (string). Nem bytes. Receber <strong>um</strong> signal é como receber um boolean: ligou ou não ligou. É a representação de apenas <em>dois estados possíveis</em>.</p>
<p>O que UNIX nos entrega são dois sinais <em>user-defined</em>, <strong>SIGUSR1</strong> e <strong>SIGUSR2</strong>, livres para usarmos como quisermos. Não conseguimos enviar bytes, mas temos a primitiva necessária para representar um byte: <em>bits</em>.</p>
<ul>
<li>
<p><code>SIGUSR1</code> = <strong>bit 0</strong></p>
</li>
<li>
<p><code>SIGUSR2</code> = <strong>bit 1</strong></p>
</li>
</ul>
<p>Pronto, acabamos de inventar uma linguagem binária. O <code>receiver</code> agora fica assim:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">!/usr/bin/env bash</span><span class="comment line number-sign shell">
</span>
  <span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>echo -n &quot;0&quot;<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR1</span>
  <span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>echo -n &quot;1&quot;<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR2</span>

  <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>PID: <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">$</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
  <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Rodar: kill -SIGUSR1 <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">$</span></span> (bit 0) ou kill -SIGUSR2 <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">$</span></span> (bit 1)<span class="punctuation definition string end shell">&quot;</span></span></span>

  <span class="keyword control while shell">while</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
      <span class="meta function-call shell"><span class="variable function shell">sleep</span></span><span class="meta function-call arguments shell"> 0.5</span> <span class="keyword operator logical or shell">||</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span>
  <span class="keyword control done shell">done</span>
</span></code></pre><pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash ./receiver.sh</span>
<span class="meta function-call shell"><span class="variable function shell">PID:</span></span><span class="meta function-call arguments shell"> 73251</span>
<span class="meta function-call shell"><span class="variable function shell">Rodar:</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 73251 (bit 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="meta function-call shell"><span class="variable function shell">ou</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR2</span> 73251 (bit 1</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Em outra sessão:</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 73251</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 73251</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 73251</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR2</span> 73251</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR2</span> 73251</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR2</span> 73251</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 73251</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 73251</span>
</span></code></pre>
<p>O que imprime <code>0001 1100</code>, seja lá o que isso significa :)</p>
<p>Agora a gente fala binário. Cada <code>kill</code> é um bit chegando no fio. Mas só bit solto não vira muita coisa. <strong>8 bits formam um byte</strong>, e cada byte representa um caractere <a href="https://www.matematica.pt/util/resumos/tabela-ascii.php">ASCII</a>. Por exemplo, a letra <code>A</code> tem código ASCII <strong>65</strong>, que em binário é <code>0100 0001</code>.</p>
<p>Se conseguirmos receber esses 8 bits e transformar isso em caractere, conseguimos transmitir <em>uma string inteira</em>, um caractere por vez.</p>
<h3 id="montando-bytes-a-partir-dos-bits">Montando bytes a partir dos bits</h3>
<p>Já sabemos que <strong>8 bits formam 1 byte</strong>. E que cada byte representa 1 caractere ASCII. Pra transformar a chuva de SIGUSR1 e SIGUSR2 em texto, o <code>receiver</code> precisa <strong>acumular</strong> os bits e, a cada 8, converter em caractere.</p>
<p>Vamos usar uma convenção onde o primeiro bit que chega é o de menor peso (bit 0), o segundo é o bit 1, o terceiro é o bit 2, e assim por diante até o bit 7. Ou seja, vamos utilizar LSB, ou <em>least significant bit</em>, que traduzido é "bit menos significativo".</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">!/usr/bin/env bash</span><span class="comment line number-sign shell">
</span>
  <span class="variable other readwrite assignment shell">POSITION</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
  <span class="variable other readwrite assignment shell">ACCUMULATOR</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>

<span class="meta function shell">  <span class="entity name function shell">decode_bit</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
<span class="meta function-call shell">      <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">bit</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span></span></span>
      <span class="variable other readwrite assignment shell">ACCUMULATOR</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion arithmetic shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">((</span> ACCUMULATOR <span class="keyword operator arithmetic shell">+</span> <span class="meta group parens shell"><span class="punctuation section parens begin shell">(</span>bit <span class="keyword operator logical shell">&lt;&lt;</span> POSITION<span class="punctuation section parens end shell">)</span></span> <span class="punctuation section parens end shell">))</span></span></span>
      <span class="variable other readwrite assignment shell">POSITION</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion arithmetic shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">((</span> POSITION <span class="keyword operator arithmetic shell">+</span> <span class="constant numeric integer decimal shell">1</span> <span class="punctuation section parens end shell">))</span></span></span>

      <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">POSITION</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>eq</span> 8 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
<span class="meta function-call shell">          <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">char</span></span>
          <span class="variable other readwrite assignment shell">char</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="support function printf shell">printf</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="constant character escape shell">\\</span><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="support function printf shell">printf</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>%03o<span class="punctuation definition string end shell">&#39;</span></span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">ACCUMULATOR</span></span><span class="punctuation definition string end shell">&quot;</span></span></span><span class="punctuation section parens end shell">)</span></span><span class="punctuation definition string end shell">&quot;</span></span></span><span class="punctuation section parens end shell">)</span></span></span>
          <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>byte: <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">ACCUMULATOR</span></span> | char: <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">char</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
          <span class="variable other readwrite assignment shell">POSITION</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
          <span class="variable other readwrite assignment shell">ACCUMULATOR</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
      <span class="keyword control if end shell">fi</span>
  <span class="punctuation section braces end shell">}</span></span>

  <span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>decode_bit 0<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR1</span>
  <span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>decode_bit 1<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR2</span>

  <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>PID: <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">$</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>

  <span class="keyword control while shell">while</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
      <span class="meta function-call shell"><span class="variable function shell">sleep</span></span><span class="meta function-call arguments shell"> 0.5</span> <span class="keyword operator logical or shell">||</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span>
  <span class="keyword control done shell">done</span>
</span></code></pre>
<p>Explicando as partes que mais importam:</p>
<ul>
<li>
<p><code>(bit &lt;&lt; POSITION)</code>: <em>shift</em> à esquerda. O bit é empurrado pra posição certa dentro do byte. Se POSITION é 6 e o bit é 1, isso vira <code>64</code> (porque <code>1 &lt;&lt; 6 = 64</code>). Se o bit é 0, fica sempre 0.</p>
</li>
<li>
<p>quando POSITION chega em 8, fechamos o byte. Convertemos pro caractere com <code>printf</code>, imprimimos e zeramos tudo pro próximo byte</p>
</li>
</ul>
<p>Vamos ver isto funcionando na prática: A letra <code>A</code> tem código ASCII 65 como já vimos, que em binário é <code>0100 0001</code>. Mandando LSB primeiro, a sequência de bits vira <code>1 0 0 0 0 0 1 0</code>:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash receiver.sh</span>
<span class="meta function-call shell"><span class="variable function shell">PID:</span></span><span class="meta function-call arguments shell"> 80381</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Em outra sessão:</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR2</span> 80381   <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 1</span><span class="comment line number-sign shell">
</span></span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 80381   <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0</span><span class="comment line number-sign shell">
</span></span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 80381   <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0</span><span class="comment line number-sign shell">
</span></span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 80381   <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0</span><span class="comment line number-sign shell">
</span></span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 80381   <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0</span><span class="comment line number-sign shell">
</span></span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 80381   <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0</span><span class="comment line number-sign shell">
</span></span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR2</span> 80381   <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 1</span><span class="comment line number-sign shell">
</span></span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGUSR1</span> 80381   <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0</span><span class="comment line number-sign shell">
</span></span></span></code></pre>
<p>O receiver imprime: <code>byte: 65 | char: A</code>. <em>What a wonderful day, uh?</em></p>
<p>Signals viraram bits. Bits viraram byte. Byte virou caractere. Agora dá pra mandar palavras inteiras, onde cada caractere é <strong>apenas uma sequência de 8 bits</strong>, e o <code>receiver</code> decodifica um por um conforme chegam.</p>
<blockquote>
<p>Manda mais bytes para ver outras letras: B = 66 = <code>0100 0010</code> e assim por diante. Não esquecendo de inverter a ordem dos bits, do LSB pro MSB.</p>
</blockquote>
<p><em>Nota: poderíamos utilizar o formato MSB (most-significant bit), para não precisarmos inverter os bits no envio, mas pra deixar o código do <code>receiver</code> mais simples e seguindo a maioria das convenções, decidi utilizar LSB mesmo</em></p>
<h3 id="enviando-strings-inteiras">Enviando strings inteiras</h3>
<p>No momento só conseguimos mandar bits "na mão", utilizando <code>kill -SIGUSR1</code> ou <code>kill -SIGUSR2</code>, um por um. Porém isso não escala. Precisamos do outro lado da história, um <code>sender</code> que recebe uma string e cuida de mandar os bits certos.</p>
<p>A lógica é o "espelho" do <code>receiver</code> basicamente:</p>
<ul>
<li>
<p>pra cada caractere da string, pega o código ASCII</p>
</li>
<li>
<p>codifica para bits (8 bits), seguindo convenção LSB</p>
</li>
<li>
<p>manda cada bit como SIGUSR1 (0) ou SIGUSR2 (1)</p>
</li>
</ul>
<p><code>sender.sh</code></p>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">!/usr/bin/env bash</span><span class="comment line number-sign shell">
</span>
  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> usage: ./sender.sh &lt;pid&gt; &lt;string&gt;</span><span class="comment line number-sign shell">
</span>  <span class="variable other readwrite assignment shell">PID</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span></span>
  <span class="variable other readwrite assignment shell">INPUT</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">2</span></span></span>

<span class="meta function shell">  <span class="entity name function shell">send_bit</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
      <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>eq</span> 0 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
          <span class="meta function-call shell"><span class="support function kill shell">kill</span></span><span class="meta function-call arguments shell"> -SIGUSR1 <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">PID</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="keyword control if else shell">else</span>
          <span class="meta function-call shell"><span class="support function kill shell">kill</span></span><span class="meta function-call arguments shell"> -SIGUSR2 <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">PID</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="keyword control if end shell">fi</span>
      <span class="meta function-call shell"><span class="variable function shell">sleep</span></span><span class="meta function-call arguments shell"> 0.5</span>
  <span class="punctuation section braces end shell">}</span></span>

<span class="meta function shell">  <span class="entity name function shell">send_byte</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
<span class="meta function-call shell">      <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">byte</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span></span></span>
<span class="meta function-call shell">      <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">k</span></span>
      <span class="keyword control for shell">for</span><span class="meta group for shell"> <span class="meta group arithmetic shell"><span class="punctuation section arithmetic begin shell">((</span>k<span class="keyword operator assignment shell">=</span><span class="constant numeric integer decimal shell">0</span><span class="punctuation separator shell">;</span> k<span class="keyword operator logical shell">&lt;</span><span class="constant numeric integer decimal shell">8</span><span class="punctuation separator shell">;</span> k<span class="keyword operator arithmetic shell">++</span><span class="punctuation section arithmetic end shell">))</span></span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
          <span class="meta function-call shell"><span class="variable function shell">send_bit</span></span><span class="meta function-call arguments shell"> <span class="meta group expansion arithmetic shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">((</span> <span class="meta group parens shell"><span class="punctuation section parens begin shell">(</span>byte <span class="keyword operator logical shell">&gt;&gt;</span> k<span class="punctuation section parens end shell">)</span></span> <span class="keyword operator bitwise shell">&amp;</span> <span class="constant numeric integer decimal shell">1</span> <span class="punctuation section parens end shell">))</span></span></span>
      <span class="keyword control done shell">done</span>
  <span class="punctuation section braces end shell">}</span></span>

  <span class="keyword control for shell">for</span><span class="meta group for shell"> <span class="meta group arithmetic shell"><span class="punctuation section arithmetic begin shell">((</span>i<span class="keyword operator assignment shell">=</span><span class="constant numeric integer decimal shell">0</span><span class="punctuation separator shell">;</span> i<span class="keyword operator logical shell">&lt;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="keyword operator arithmetic shell">#</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">INPUT</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation separator shell">;</span> i<span class="keyword operator arithmetic shell">++</span><span class="punctuation section arithmetic end shell">))</span></span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
      <span class="variable other readwrite assignment shell">char</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">INPUT</span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring begin shell">:</span></span><span class="meta group expansion parameter shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">i</span></span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring end shell">:</span></span><span class="meta group expansion parameter shell"><span class="constant numeric integer decimal shell">1</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="variable other readwrite assignment shell">code</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="support function printf shell">printf</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>%d<span class="punctuation definition string end shell">&#39;</span></span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>&#39;<span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">char</span></span><span class="punctuation definition string end shell">&quot;</span></span></span><span class="punctuation section parens end shell">)</span></span></span>
      <span class="meta function-call shell"><span class="variable function shell">send_byte</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">code</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
  <span class="keyword control done shell">done</span>
</span></code></pre>
<p>O core está em <code>send_byte</code>:</p>
<ul>
<li>
<p><code>(byte &gt;&gt; k) &amp; 1</code>: pega o k-ésimo bit do byte. Faz shift à direita por <code>k</code> posições e aplica <code>&amp; 1</code> (máscara) para isolar o bit. Em <code>k=0</code>, pega o LSB, em <code>k=7</code>, pega o MSB.</p>
</li>
<li>
<p><code>sleep 0.5</code> entre bits: signals podem ser perdidos se chegarem rápido demais (o sistema operacional colapsa sinais idênticos pendentes, como forma de "debounce"). Esse delay dá tempo do receiver processar cada um antes do próximo chegar</p>
</li>
</ul>
<p>Conseguimos mandar uma string inteira via signals. Cada caractere viajou como 8 bits via IPC, foi remontado byte a byte, e o receiver imprimiu conforme decodificava. Vamos provar isso na próxima seção, onde também resolvemos o fim de mensagem.</p>
<blockquote>
<p>Nossa, isso é mágica?</p>
</blockquote>
<p>Não, é apenas <strong>trap + bit shift + acumulador</strong>.</p>
<p>Entretanto, temos um problema. O receiver não sabe quando a mensagem <em>acabou</em>. Ele fica esperando o próximo bit pra sempre, sem poder fazer nada com a string completa.</p>
<h2 id="marcando-o-fim-da-mensagem">Marcando o fim da mensagem</h2>
<p>O receiver fica eternamente esperando bits. A gente precisa avisar quando a string acabou. Uma convenção clássica em comunicação binária é o famoso <strong>byte zero</strong> (<code>0x00</code>, conhecido como NUL). Isto marca o fim da mensagem. Strings em C usam essa ideia há décadas, então vamos roubar.</p>
<p>No <code>sender</code>, basta mandar 8 bits "zeros" logo depois do último caractere:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> ...todo o loop de envio dos caracteres...</span><span class="comment line number-sign shell">
</span>
  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> fim da mensagem</span><span class="comment line number-sign shell">
</span>  <span class="meta function-call shell"><span class="variable function shell">send_byte</span></span><span class="meta function-call arguments shell"> 0</span>
</span></code></pre>
<p>E no <code>receiver</code>, quando o byte completo for <code>0</code>, em vez de decodificar como caractere, marcamos o fim:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">POSITION</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>eq</span> 8 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
      <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">ACCUMULATOR</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>eq</span> 0 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
          <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="punctuation definition string end shell">&quot;</span></span></span>
          <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>[end of message]<span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="keyword control if else shell">else</span>
<span class="meta function-call shell">          <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">char</span></span>
          <span class="variable other readwrite assignment shell">char</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="support function printf shell">printf</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="constant character escape shell">\\</span><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="support function printf shell">printf</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>%03o<span class="punctuation definition string end shell">&#39;</span></span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">ACCUMULATOR</span></span><span class="punctuation definition string end shell">&quot;</span></span></span><span class="punctuation section parens end shell">)</span></span><span class="punctuation definition string end shell">&quot;</span></span></span><span class="punctuation section parens end shell">)</span></span></span>
          <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>n</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">char</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="keyword control if end shell">fi</span>
      <span class="variable other readwrite assignment shell">POSITION</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
      <span class="variable other readwrite assignment shell">ACCUMULATOR</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
  <span class="keyword control if end shell">fi</span>
</span></code></pre>
<p>Vamos rodar tudo:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Receiver</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash receiver.sh</span>
<span class="meta function-call shell"><span class="variable function shell">PID:</span></span><span class="meta function-call arguments shell"> 15300</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Sender</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash sender.sh 15300 ana</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Receiver</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">ana</span></span>
<span class="meta function-call shell"><span class="variable function shell">[end</span></span><span class="meta function-call arguments shell"> of message]</span>
</span></code></pre>
<p><em>Cool, uh?</em> Agora temos a base completa de transporte. Bits viram bytes, que viram caracteres, e o NUL fecha a mensagem. Tudo isso com apenas <strong>dois sinais e um trap</strong>.</p>
<p>Contudo, falta a peça principal do post: <em>a lógica do palíndromo</em>, implementada via <strong>fila e pilha</strong> conforme prometemos.</p>
<hr />
<h2 id="fila-e-pilha-o-teorema-central">Fila e pilha: o teorema central</h2>
<p>Vamos esquecer signals por um momento. Esquece também <strong>substrings, índices, two pointers</strong>. Imagina que os caracteres da string chegam um a um, e que precisamos decidir se formam um palíndromo, <em>sem precisar remontar a string em memória</em>. É aqui que está o sumo deste artigo! Os signals foram apenas uma "armadilha" que montei pra você, caro leitor.</p>
<blockquote>
<p>Tô brincando, eu quis fazer um trocadilho com "trap". Espero que a piada tenha servido de alguma coisa</p>
</blockquote>
<p>Como todo engenheiro de software, temos que fazer a pergunta certa: <strong>que estruturas de dados, sozinhas, decidem palíndromo por construção?</strong> Resposta: uma fila (FIFO) e uma pilha (LIFO).</p>
<blockquote>
<p>Uai, por quê?</p>
</blockquote>
<p>Pensa no que cada uma faz:</p>
<ul>
<li>
<p><strong>FIFO</strong>: preserva a ordem. Enfileirei <code>R, A, D, A, R</code>, desenfileiro <code>R, A, D, A, R</code>. Mesma ordem.</p>
</li>
<li>
<p><strong>LIFO</strong>: inverte a ordem. Empilhei <code>R, A, D, A, R</code>, desempilho <code>R, A, D, A, R</code>. Ordem reversa.</p>
</li>
</ul>
<p>E palíndromo é, por definição, uma string que lida na ordem normal <strong>e</strong> na ordem reversa dá a mesma sequência. Que é exatamente o que acontece se a saída da fila bater com a saída da pilha.</p>
<p><em>Supa hot fireeee</em></p>
<p><img src="/images/resolvendo-pal-ndromo-com-apenas-dois-unix-signals-uma-fila-e-uma-pilha-screenshot-2026-04-28-at-01-22-39.png" alt="Meme do Supa Hot Fire reagindo com cara de incrédulo, marcando o clímax da explicação" /></p>
<p>Em outras palavras, uma string é palíndromo <strong>se e somente se</strong>, ao empilhar e enfileirar cada caractere em paralelo, todo <code>pop</code> da pilha for igual ao <code>dequeue</code> da fila. Sem comparação posicional, nem <code>length / 2</code>, nem indexação adicional. As duas estruturas <em>decidem por construção</em>. Puro suco da computação ao nosso favor.</p>
<p><code>palindromer.sh</code></p>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">!/usr/bin/env bash</span><span class="comment line number-sign shell">
</span>
  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> usage: ./palindromer.sh &lt;string&gt;</span><span class="comment line number-sign shell">
</span>  <span class="variable other readwrite assignment shell">INPUT</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span></span>

  <span class="variable other readwrite assignment shell">stack</span><span class="keyword operator assignment shell">=</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span>
  <span class="variable other readwrite assignment shell">queue</span><span class="keyword operator assignment shell">=</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span>

  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> push and enqueue each char</span><span class="comment line number-sign shell">
</span>  <span class="keyword control for shell">for</span><span class="meta group for shell"> <span class="meta group arithmetic shell"><span class="punctuation section arithmetic begin shell">((</span>i<span class="keyword operator assignment shell">=</span><span class="constant numeric integer decimal shell">0</span><span class="punctuation separator shell">;</span> i<span class="keyword operator logical shell">&lt;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="keyword operator arithmetic shell">#</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">INPUT</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation separator shell">;</span> i<span class="keyword operator arithmetic shell">++</span><span class="punctuation section arithmetic end shell">))</span></span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
      <span class="variable other readwrite assignment shell">char</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">INPUT</span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring begin shell">:</span></span><span class="meta group expansion parameter shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">i</span></span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring end shell">:</span></span><span class="meta group expansion parameter shell"><span class="constant numeric integer decimal shell">1</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="variable other readwrite assignment shell">stack</span><span class="keyword operator assignment shell">+=</span><span class="punctuation section parens begin shell">(</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">char</span></span><span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation section parens end shell">)</span>
      <span class="variable other readwrite assignment shell">queue</span><span class="keyword operator assignment shell">+=</span><span class="punctuation section parens begin shell">(</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">char</span></span><span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation section parens end shell">)</span>
  <span class="keyword control done shell">done</span>

  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> flush both and compare</span><span class="comment line number-sign shell">
</span>  <span class="keyword control while shell">while</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="keyword operator arithmetic shell">#</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">stack<span class="punctuation section braces begin shell">[</span><span class="variable language array shell">@</span><span class="punctuation section braces end shell">]</span></span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>gt</span> 0 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
      <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">stack<span class="punctuation section braces begin shell">[</span><span class="keyword operator arithmetic shell">-</span><span class="constant numeric integer decimal shell">1</span><span class="punctuation section braces end shell">]</span></span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="keyword operator logical shell">!=</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">queue<span class="punctuation section braces begin shell">[</span><span class="constant numeric integer decimal shell">0</span><span class="punctuation section braces end shell">]</span></span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
          <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>false<span class="punctuation definition string end shell">&quot;</span></span></span>
          <span class="meta function-call shell"><span class="support function exit shell">exit</span></span><span class="meta function-call arguments shell"> 0</span>
      <span class="keyword control if end shell">fi</span>
      <span class="meta function-call shell"><span class="support function unset shell">unset</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>stack[-1]<span class="punctuation definition string end shell">&#39;</span></span></span>
      <span class="variable other readwrite assignment shell">queue</span><span class="keyword operator assignment shell">=</span><span class="punctuation section parens begin shell">(</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">queue<span class="punctuation section braces begin shell">[</span><span class="variable language array shell">@</span><span class="punctuation section braces end shell">]</span></span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring begin shell">:</span></span><span class="meta group expansion parameter shell"><span class="constant numeric integer decimal shell">1</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation section parens end shell">)</span>
  <span class="keyword control done shell">done</span>

  <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>true<span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<ul>
<li>
<p><code>stack+=("$char")</code>: append em array é o <code>push</code> da pilha</p>
</li>
<li>
<p><code>queue+=("$char")</code>: o mesmo append serve como <code>enqueue</code> da fila</p>
</li>
<li>
<p><code>${stack[-1]}</code>: pega o <strong>topo</strong> da pilha (último elemento, <em>last-in</em>)</p>
</li>
<li>
<p><code>${queue[0]}</code>: pega a <strong>frente</strong> da fila (primeiro elemento, <em>first-in</em>)</p>
</li>
<li>
<p><code>unset 'stack[-1]'</code>: remove o topo (<code>pop</code>)</p>
</li>
<li>
<p><code>queue=("${queue[@]:1}")</code>: reatribui a fila a partir do segundo elemento (<code>dequeue</code>)</p>
</li>
</ul>
<p>Rodando tudo:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash palindromer.sh ANA</span>
<span class="meta function-call shell"><span class="variable function shell">true</span></span>

<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash palindromer.sh ABC</span>
<span class="meta function-call shell"><span class="variable function shell">false</span></span>

<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash palindromer.sh RADAR</span>
<span class="meta function-call shell"><span class="variable function shell">true</span></span>
</span></code></pre>
<p>Temos então palíndromo com uma fila, uma pilha, e a propriedade matemática que cada uma representa. Agora nos resta plugar tudo isso no <code>receiver</code>. Cada caractere que chegar via signals vai direto pras duas estruturas, e quando o NUL chegar, drenamos e respondemos.</p>
<h3 id="conectando-tudo">Conectando tudo</h3>
<p>A função do <code>palindromer.sh</code> recebia uma string como argumento. Aqui, a string não existe inteira em lugar nenhum. Os caracteres chegam, um a cada 8 bits, conforme o sender vai mandando. Mas a lógica é exatamente a mesma.</p>
<p>Em vez de iterar sobre uma string já pronta, a gente empilha e enfileira <strong>conforme cada caractere chega</strong>. Incrível, não? Desta forma o <code>receiver</code> muda um pouco de lógica:</p>
<ul>
<li>
<p>cada vez que um byte completo é decodificado e <strong>não é</strong> o NUL, a gente empilha e enfileira o caractere</p>
</li>
<li>
<p>quando o NUL chega, fazemos a drenagem das duas estruturas e respondemos com <code>true</code> ou <code>false</code></p>
</li>
</ul>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">!/usr/bin/env bash</span><span class="comment line number-sign shell">
</span>
  <span class="variable other readwrite assignment shell">POSITION</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
  <span class="variable other readwrite assignment shell">ACCUMULATOR</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
  <span class="variable other readwrite assignment shell">stack</span><span class="keyword operator assignment shell">=</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span>
  <span class="variable other readwrite assignment shell">queue</span><span class="keyword operator assignment shell">=</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span>

<span class="meta function shell">  <span class="entity name function shell">drain_and_decide</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
      <span class="keyword control while shell">while</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="keyword operator arithmetic shell">#</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">stack<span class="punctuation section braces begin shell">[</span><span class="variable language array shell">@</span><span class="punctuation section braces end shell">]</span></span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>gt</span> 0 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
          <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">stack<span class="punctuation section braces begin shell">[</span><span class="keyword operator arithmetic shell">-</span><span class="constant numeric integer decimal shell">1</span><span class="punctuation section braces end shell">]</span></span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="keyword operator logical shell">!=</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">queue<span class="punctuation section braces begin shell">[</span><span class="constant numeric integer decimal shell">0</span><span class="punctuation section braces end shell">]</span></span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
              <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>false<span class="punctuation definition string end shell">&quot;</span></span></span>
              <span class="variable other readwrite assignment shell">stack</span><span class="keyword operator assignment shell">=</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span>
              <span class="variable other readwrite assignment shell">queue</span><span class="keyword operator assignment shell">=</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span>
              <span class="meta function-call shell"><span class="keyword control return shell">return</span></span>
          <span class="keyword control if end shell">fi</span>
          <span class="meta function-call shell"><span class="support function unset shell">unset</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>stack[-1]<span class="punctuation definition string end shell">&#39;</span></span></span>
          <span class="variable other readwrite assignment shell">queue</span><span class="keyword operator assignment shell">=</span><span class="punctuation section parens begin shell">(</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">queue<span class="punctuation section braces begin shell">[</span><span class="variable language array shell">@</span><span class="punctuation section braces end shell">]</span></span></span><span class="meta group expansion parameter shell"><span class="keyword operator substring begin shell">:</span></span><span class="meta group expansion parameter shell"><span class="constant numeric integer decimal shell">1</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span><span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation section parens end shell">)</span>
      <span class="keyword control done shell">done</span>
      <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>true<span class="punctuation definition string end shell">&quot;</span></span></span>
  <span class="punctuation section braces end shell">}</span></span>

<span class="meta function shell">  <span class="entity name function shell">decode_bit</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
<span class="meta function-call shell">      <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">bit</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span></span></span>
      <span class="variable other readwrite assignment shell">ACCUMULATOR</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion arithmetic shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">((</span> ACCUMULATOR <span class="keyword operator arithmetic shell">+</span> <span class="meta group parens shell"><span class="punctuation section parens begin shell">(</span>bit <span class="keyword operator logical shell">&lt;&lt;</span> POSITION<span class="punctuation section parens end shell">)</span></span> <span class="punctuation section parens end shell">))</span></span></span>
      <span class="variable other readwrite assignment shell">POSITION</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion arithmetic shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">((</span> POSITION <span class="keyword operator arithmetic shell">+</span> <span class="constant numeric integer decimal shell">1</span> <span class="punctuation section parens end shell">))</span></span></span>

      <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">POSITION</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>eq</span> 8 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
          <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">ACCUMULATOR</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>eq</span> 0 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
              <span class="meta function-call shell"><span class="variable function shell">drain_and_decide</span></span>
          <span class="keyword control if else shell">else</span>
<span class="meta function-call shell">              <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">char</span></span>
              <span class="variable other readwrite assignment shell">char</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="support function printf shell">printf</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="constant character escape shell">\\</span><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="support function printf shell">printf</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>%03o<span class="punctuation definition string end shell">&#39;</span></span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">ACCUMULATOR</span></span><span class="punctuation definition string end shell">&quot;</span></span></span><span class="punctuation section parens end shell">)</span></span><span class="punctuation definition string end shell">&quot;</span></span></span><span class="punctuation section parens end shell">)</span></span></span>
              <span class="variable other readwrite assignment shell">stack</span><span class="keyword operator assignment shell">+=</span><span class="punctuation section parens begin shell">(</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">char</span></span><span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation section parens end shell">)</span>
              <span class="variable other readwrite assignment shell">queue</span><span class="keyword operator assignment shell">+=</span><span class="punctuation section parens begin shell">(</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">char</span></span><span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation section parens end shell">)</span>
          <span class="keyword control if end shell">fi</span>
          <span class="variable other readwrite assignment shell">POSITION</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
          <span class="variable other readwrite assignment shell">ACCUMULATOR</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell">0</span>
      <span class="keyword control if end shell">fi</span>
  <span class="punctuation section braces end shell">}</span></span>

  <span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>decode_bit 0<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR1</span>
  <span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>decode_bit 1<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR2</span>

  <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>PID: <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">$</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>

  <span class="keyword control while shell">while</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
      <span class="meta function-call shell"><span class="variable function shell">sleep</span></span><span class="meta function-call arguments shell"> 0.5</span> <span class="keyword operator logical or shell">||</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span>
  <span class="keyword control done shell">done</span>
</span></code></pre>
<p>Diferença pro receiver da versão anterior:</p>
<ul>
<li>
<p>duas variáveis globais novas: <code>stack=()</code> e <code>queue=()</code></p>
</li>
<li>
<p>quando o byte completa, em vez de só imprimir o caractere, a gente manda pra stack e queue</p>
</li>
<li>
<p>quando o byte é NUL, em vez de só sinalizar o fim, disparamos o <code>drain_and_decide</code> que devolve o veredito</p>
</li>
</ul>
<p>Momento da verdade:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Receiver</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash receiver.sh</span>
<span class="meta function-call shell"><span class="variable function shell">PID:</span></span><span class="meta function-call arguments shell"> 33485</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Sender</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash sender.sh 33485 ANA</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash sender.sh 33485 ABC</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash sender.sh 33485 RADAR</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> bash sender.sh 33485 SOCORRAMMESUBINOONIBUSEMMARROCOS</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Receiver</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">true</span></span>
<span class="meta function-call shell"><span class="variable function shell">false</span></span>
<span class="meta function-call shell"><span class="variable function shell">true</span></span>
<span class="meta function-call shell"><span class="variable function shell">true</span></span>
</span></code></pre>
<p><em>OMFG!</em> Cada string é codificada via signals, e depois a lógica do palíndromo é feita <strong>sem remontar</strong> a string novamente!</p>
<hr />
<h2 id="bonus-points-handshake-ftw">Bonus points: Handshake FTW</h2>
<p>Até aqui o receiver imprime <code>true/false</code> no terminal dele. O sender não fica sabendo de nada. Vamos fechar este ciclo com o receiver devolvendo um signal para o sender imprimir localmente.</p>
<p>Convenção: <strong>SIGUSR2 = palíndromo (true), SIGUSR1 = não é palíndromo (false)</strong>.</p>
<p>O receiver precisa saber quem é o sender. Sender escreve o próprio PID em <code>/tmp/sender.pid</code> antes de mandar a string, e configura um trap para receber o veredito:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> sender.sh</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">$</span></span> <span class="keyword operator assignment redirection shell">&gt;</span> /tmp/sender.pid</span>

<span class="variable other readwrite assignment shell">RESPONSE</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="punctuation definition string end shell">&quot;</span></span></span>
<span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>RESPONSE=0<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR1</span>
<span class="meta function-call shell"><span class="support function trap shell">trap</span></span><span class="meta function-call arguments shell"> <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>RESPONSE=1<span class="punctuation definition string end shell">&#39;</span></span> SIGUSR2</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> ... send the string ...</span><span class="comment line number-sign shell">
</span>
<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> after EOF, RESPONSE was set from verdict</span><span class="comment line number-sign shell">
</span><span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">RESPONSE</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="keyword operator logical shell">=</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>1<span class="punctuation definition string end shell">&quot;</span></span> <span class="support function test end shell">]</span></span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>true<span class="punctuation definition string end shell">&quot;</span></span></span> <span class="keyword operator logical or shell">||</span> <span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>false<span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<p>Do lado do receiver, o <code>drain_and_decide</code> agora termina enviando o signal de volta:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="meta function shell">  <span class="entity name function shell">verdict</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
<span class="meta function-call shell">      <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">result</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span></span></span>
<span class="meta function-call shell">      <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">pid</span></span>
      <span class="variable other readwrite assignment shell">pid</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">cat</span></span><span class="meta function-call arguments shell"> /tmp/sender.pid <span class="constant numeric integer decimal file-descriptor shell">2</span><span class="keyword operator assignment redirection shell">&gt;</span>/dev/null</span><span class="punctuation section parens end shell">)</span></span></span>

      <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">result</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="keyword operator logical shell">=</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>true<span class="punctuation definition string end shell">&quot;</span></span> <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
          <span class="meta function-call shell"><span class="support function kill shell">kill</span></span><span class="meta function-call arguments shell"> -SIGUSR2 <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">pid</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="constant numeric integer decimal file-descriptor shell">2</span><span class="keyword operator assignment redirection shell">&gt;</span>/dev/null</span>
      <span class="keyword control if else shell">else</span>
          <span class="meta function-call shell"><span class="support function kill shell">kill</span></span><span class="meta function-call arguments shell"> -SIGUSR1 <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">pid</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="constant numeric integer decimal file-descriptor shell">2</span><span class="keyword operator assignment redirection shell">&gt;</span>/dev/null</span>
      <span class="keyword control if end shell">fi</span>
  <span class="punctuation section braces end shell">}</span></span>
</span></code></pre>
<p>Com isso, sender chama, recebe o veredito via signal, e imprime. Ciclo fechado.</p>
<blockquote>
<p>Mas isso tá lento demais, o <code>sleep 0.5</code> por bit dá uns 16 segundos só pra ANA. No caso do "SOCORRAMMESUBINOONIBUSEMMARROCOS", demorou bons minutos...inaceitável</p>
</blockquote>
<p>Uma forma de contornar o delay é através de um mecanismo de <strong>handshake</strong>. O receiver responde com um <strong>ACK</strong> depois de cada bit, e o sender só manda o próximo quando recebeu. Como o sender só avança após o ACK, nunca há dois sinais enfileirados, portanto a coalescência é eliminada por construção. Sem fila de sinais pendentes, e sem <code>sleep</code> arbitrário.</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> receiver.sh</span><span class="comment line number-sign shell">
</span>
<span class="meta function shell">  <span class="entity name function shell">ack</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
<span class="meta function-call shell">      <span class="storage modifier shell">local</span> <span class="variable other readwrite assignment shell">pid</span></span>
      <span class="variable other readwrite assignment shell">pid</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion command parens shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section parens begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">cat</span></span><span class="meta function-call arguments shell"> /tmp/sender.pid <span class="constant numeric integer decimal file-descriptor shell">2</span><span class="keyword operator assignment redirection shell">&gt;</span>/dev/null</span><span class="punctuation section parens end shell">)</span></span></span>
      <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>n</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">pid</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="support function test end shell">]</span></span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="support function kill shell">kill</span></span><span class="meta function-call arguments shell"> -SIGUSR1 <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">pid</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="constant numeric integer decimal file-descriptor shell">2</span><span class="keyword operator assignment redirection shell">&gt;</span>/dev/null</span>
  <span class="punctuation section braces end shell">}</span></span>

</span></code></pre>
<p>E o sender:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> sender.sh — espera o ACK no lugar do sleep</span><span class="comment line number-sign shell">
</span><span class="meta function shell">  <span class="entity name function shell">send_bit</span><span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> <span class="punctuation section braces begin shell">{</span>
      <span class="variable other readwrite assignment shell">RESPONSE</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="keyword control if begin shell">if</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">1</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>eq</span> 0 <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control if then shell">then</span>
          <span class="meta function-call shell"><span class="support function kill shell">kill</span></span><span class="meta function-call arguments shell"> -SIGUSR1 <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">RECEIVER_PID</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="keyword control if else shell">else</span>
          <span class="meta function-call shell"><span class="support function kill shell">kill</span></span><span class="meta function-call arguments shell"> -SIGUSR2 <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">RECEIVER_PID</span></span><span class="punctuation definition string end shell">&quot;</span></span></span>
      <span class="keyword control if end shell">fi</span>
      <span class="keyword control while shell">while</span> <span class="support function test begin shell">[</span><span class="meta function-call arguments shell"> <span class="variable parameter option shell"><span class="punctuation definition parameter shell">-</span>z</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">RESPONSE</span></span><span class="punctuation definition string end shell">&quot;</span></span> <span class="support function test end shell">]</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
          <span class="meta function-call shell"><span class="variable function shell">sleep</span></span><span class="meta function-call arguments shell"> 0.001</span> <span class="keyword operator logical or shell">||</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span>
      <span class="keyword control done shell">done</span>
  <span class="punctuation section braces end shell">}</span></span>
</span></code></pre>
<p>O <strong>detalhe que muda tudo</strong>: o loop ocioso do receiver também precisa ser tight. Trocamos <code>sleep 0.5</code> por <code>sleep 0.001</code> no <code>while true</code> principal. Sem isso, cada round-trip pagava parte do meio segundo.</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash">  <span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> receiver.sh</span><span class="comment line number-sign shell">
</span>  <span class="keyword control while shell">while</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span><span class="keyword operator logical continue shell">;</span> <span class="keyword control do shell">do</span>
      <span class="meta function-call shell"><span class="variable function shell">sleep</span></span><span class="meta function-call arguments shell"> 0.001</span> <span class="keyword operator logical or shell">||</span> <span class="meta function-call shell"><span class="variable function shell">true</span></span>
  <span class="keyword control done shell">done</span>
</span></code></pre>
<p>Rodando agora:</p>
<pre><code class="sourceCode language-sh"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> time bash sender.sh 19204 ANA</span>
<span class="meta function-call shell"><span class="variable function shell">true</span></span>
<span class="meta function-call shell"><span class="variable function shell">real</span></span><span class="meta function-call arguments shell">    0m0.164s</span>
</span></code></pre>
<p>De <em>16 segundos para 160 milissegundos</em>. <strong>100x mais rápido!!!!11</strong>. How amazing is that?</p>
<hr />
<h2 id="conclusão-gloriosa">Conclusão gloriosa</h2>
<p>A treta do palíndromo virou desculpa pra brincar com duas coisas que eu gosto: <strong>UNIX signals</strong> e <strong>estruturas de dados clássicas</strong>. O resultado é isso que acabamos de ver, dois processos conversando por sinais primitivos, e duas estruturas primitivas decidindo palíndromo por construção. Lembrando:</p>
<blockquote>
<p>Uma string é palíndromo <strong>se e somente se</strong> LIFO == FIFO</p>
</blockquote>
<p>Esse é o teorema, o resto é adorno. Eu sei que Bash não foi feito pra isso, mas Bash também não foi feito pra rodar a <a href="https://github.com/leandronsp/rinha-backend-bash/">Rinha de Backend</a> e aqui a gente está, de novo.</p>
<p>Se gostou dessa aventura, recomendo ler <a href="https://leandronsp.com/articles/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals">o pai dela</a>, "You don't need Kafka".</p>
<p>Stay tuned, e bebam água.</p>
<hr />
<h2 id="disclosure">Disclosure</h2>
<p>Este artigo foi escrito usando uma ferramenta TUI que criei em Rust chamada <a href="https://github.com/leandronsp/devtui">leandronsp/devTUI</a>, com o apoio do Claude Opus 4.7 no refinamento, correção ortográfica e contexto.</p>
<p><em>Toda a identidade do artigo é 100% minha, eu não coloco IA pra escrever por mim. LLM serve apenas como um par que navega e dá feedback em tempo real, feature também incluída no DevTUI</em>.</p>
<p><img src="/images/resolvendo-pal-ndromo-com-apenas-dois-unix-signals-uma-fila-e-uma-pilha-screenshot-2026-04-28-at-02-57-58.png" alt="Print do DevTUI no Tmux com o Claude Code ao lado" /></p>
]]></description>
<pubDate>2026-04-27</pubDate>
</item>
<item>
<title>Taming non-determinism: from logic gates to LLMs</title>
<link>https://leandronsp.com/articles/taming-non-determinism-from-logic-gates-to-llms.html</link>
<guid>https://leandronsp.com/articles/taming-non-determinism-from-logic-gates-to-llms.html</guid>
<description><![CDATA[<p>Or: <em>how engineering keeps turning chaos into reliable computation. And why agentic AI still hasn't solved this.</em></p>
<p>There's a pattern that repeats across the entire history of computing: we take something fundamentally <strong>non-deterministic</strong> and engineer enough layers on top of it until it behaves deterministically. Logic gates did it. Artificial neural networks (ANNs) replicated it at some level. LLMs are the next frontier, and the hardest one yet.</p>
<p>In this article, we'll explore how engineering is crucial to addressing non-determinism, and analyze the current state of the art for LLMs.</p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#part-i---the-lie-inside-a-logic-gate">Part I - The lie inside a logic gate</a></p>
<ul>
<li><a href="#noise-margins">Noise margins</a></li>
<li><a href="#the-cpu-clock">The CPU clock</a></li>
</ul>
</li>
<li>
<p><a href="#part-ii---aspirina-teaching-non-determinism-to-behave">Part II - Aspirina: teaching non-determinism to behave</a></p>
<ul>
<li><a href="#where-the-chaos-lives---unleash-the-madness">Where the chaos lives</a></li>
<li><a href="#composition-does-the-rest">Composition does the rest</a></li>
<li><a href="#the-cost-compared">The cost compared</a></li>
</ul>
</li>
<li>
<p><a href="#part-iii---llms-and-the-unresolved-problem">Part III - LLMs and the "Unresolved Problem"</a></p>
<ul>
<li><a href="#tests-as-noise-margins">Tests as noise margins</a></li>
<li><a href="#the-agentic-loop-as-clock">The agentic loop as clock</a></li>
<li><a href="#the-type-system-and-compiler-as-low-level-validators">The type system and compiler</a></li>
<li><a href="#whats-missing-the-equivalent-of-timing-analysis">What's missing: timing analysis</a></li>
<li><a href="#how-to-mitigate-that">How to mitigate that?</a></li>
</ul>
</li>
<li>
<p><a href="#conclusion">Conclusion</a></p>
</li>
</ul>
<hr />
<h2 id="part-i---the-lie-inside-a-logic-gate">Part I - The lie inside a logic gate</h2>
<p>A <a href="https://en.wikipedia.org/wiki/Logic_gate">logic gate</a> is taught in school as a simple binary machine. You give it 0s and 1s, you get 0s and 1s back.</p>
<p>AND, OR and XOR are example of logic gates. They are clean, mathematical, deterministic. And that's a useful <em>fiction</em>.</p>
<p>At the physical level, a gate is a transistor (or a few of them) through which electrons flow. Electrons don't care about your <strong>Boolean algebra</strong>. The voltage on a wire is a continuous, analog value that fluctuates due to thermal noise, manufacturing variance, electromagnetic interference, and even cosmic radiation flipping bits in memory.</p>
<blockquote>
<p>Fun fact: in May 2003, in Belgium, an electronic voting machine gave a candidate <a href="https://en.wikipedia.org/wiki/Electronic_voting_in_Belgium">exactly 4096 extra votes</a>. More than she could possibly have received. After investigation, the error was attributed to the <strong>spontaneous creation of a 13th bit in the memory of the computer</strong>. The leading explanation: a cosmic ray flipped a single bit, turning a 0 into a 1 at position 2^12, adding exactly 4096 to the candidate count.</p>
</blockquote>
<p>Ok, but how does the industry get determinism out of this mess?</p>
<h3 id="noise-margins">Noise margins</h3>
<p>Engineers define voltage thresholds: anything below 0.8V is a <code>0</code>, anything above 2.0V is a <code>1</code>. The zone between those values is declared "forbidden". The circuit is designed to never operate stably there. This isn't physics; it's an engineering contract. (<a href="https://en.wikipedia.org/wiki/Noise_margin">More on noise margins</a>)</p>
<h3 id="the-cpu-clock">The CPU clock</h3>
<p>A CPU clock isn't just a metronome. It's also a <em>sampling strategy</em>. You let the signal propagate through the gate (which takes time, called <strong>propagation delay</strong>), and only read the value at a specific moment: the <em>clock edge</em>. By then, the signal has had time to cross the threshold and stabilise. Timing is calculated to guarantee this.</p>
<p><strong>But when timing fails, things may get weird</strong>. If a signal is sampled while it's still in the forbidden zone, a flip-flop can enter <a href="https://en.wikipedia.org/wiki/Metastability_(electronics)">metastability</a>, which is an unstable equilibrium where the output isn't quite <code>0</code> or <code>1</code> and can oscillate for an indeterminate time. This may cause real crashes in real systems.</p>
<blockquote>
<p>Think of metastability as what happens when two clocks on a wall are unsynchronized. Each showing a slightly different time. "What time is it right now?", one may ask. The answer depends on which clock you look at, but you can't decide which one is right.</p>
</blockquote>
<p>Inside the CPU, when facing a forbidden zone, the flip-flop faces the same dilemma. It can't decide if it's a <code>0</code> or a <code>1</code>, which can corrupt the system state. Engineers mitigate this with synchronizer chains, but never eliminate it entirely.</p>
<p><em>It's the non-determinism of physics leaking through the engineering abstraction</em>!</p>
<p><strong>The key insight</strong>: the determinism of digital computing is not a property of nature. It's an <em>engineering achievement</em>. It's paid with noise margins, timing analysis and careful design.</p>
<p>Yes, it's all about <strong>engineering</strong>.</p>
<hr />
<h2 id="part-ii---aspirina-teaching-non-determinism-to-behave">Part II - Aspirina: teaching non-determinism to behave</h2>
<p><a href="https://github.com/leandronsp/aspirina">Aspirina</a> is my personal project that builds a complete CPU entirely from artificial neural networks (ANNs) trained to behave as logic gates, written in Rust.</p>
<blockquote>
<p>Actually I created the <a href="https://github.com/leandronsp/morphine">very first version</a> almost 10 years ago in Elixir, when I was learning about ANNs and Elixir. Recently I decided to write a Rust version while I was learning Rust.</p>
</blockquote>
<p>The inversion from Part I brings the beauty: instead of physical electrons that need to be tamed into bits, here we have ANNs - <em>systems whose weights are initialised randomly and whose outputs are continuous floating-point numbers</em> - that need to be tamed into <code>0</code> and <code>1</code> too.</p>
<p>The non-determinism here is introduced deliberately, and then engineered away. Bear with me.</p>
<h3 id="where-the-chaos-lives---unleash-the-madness">Where the chaos lives - unleash the madness</h3>
<p>A neural network starts with random weights. Its output for any input is whatever the math happens to produce. Not <code>0</code>, not <code>1</code>, but something like <code>0.6312</code>. In case you missed, I already have an article in my blog about <a href="https://leandronsp.com/articles/ai-ruby-an-introduction-to-neural-networks-23f3">neural networks</a>.</p>
<p><strong>Backpropagation is the engineering response</strong>. It's the algorithm that adjusts the weights iteratively, measuring how wrong the output is (the <em>loss</em>) and leading weights in the direction that reduces the error. Run this for 10,000 epochs - 10,000 passes over the training data - and the network converges to weights that produce <code>0.002</code> for inputs that should be <code>0</code>, and <code>0.997</code> for inputs that should be <code>1</code>.</p>
<p>The <a href="https://en.wikipedia.org/wiki/Sigmoid_function">sigmoid function</a> (a.k.a the <em>logistic curve</em>) does in Aspirina what noise margins do in hardware: it squashes any continuous value into the range <code>0..1</code>. It doesn't give you exact binary outputs, but it pushes values toward the extremes.</p>
<blockquote>
<p>And that's exactly what we need</p>
</blockquote>
<p>Combined with a threshold decision - below <code>0.5</code> we could consider <code>0</code>, above <code>0.5</code> we consider <code>1</code> -, we get in Aspirina the same effect: a circuit that <em>behaves deterministically</em> even though its internals are continuous and learned.</p>
<h3 id="composition-does-the-rest">Composition does the rest</h3>
<p>Once gates are trained, they're composed to:</p>
<pre><code class="sourceCode"><span class="text plain">XOR + AND =&gt; Half Adder =&gt; Full Adder =&gt; 4-bit ALU =&gt; Memory =&gt; Registers =&gt; CPU =&gt; Assembler =&gt; Interpreter
</span></code></pre>
<p>Each layer treats the layer below as if it were perfectly deterministic, which is <strong>exactly the abstraction hierarchy</strong> of real hardware.</p>
<p>The non-determinism was contained at the lowest level (training), and every layer above it benefits from the illusion of determinism.</p>
<p>Yes, <strong>determinism is an illusion</strong>. Deal with it.</p>
<h3 id="the-cost-compared">The cost compared</h3>
<p>Compute time during training. Just as chip fabrication invests energy upfront to create reliable silicon, Aspirina invests 10,000 epochs upfront to create reliable logic. After that, inference is cheap and stable.</p>
<p>Now, <em>enter LLMs</em>.</p>
<hr />
<h2 id="part-iii---llms-and-the-unresolved-problem">Part III - LLMs and the "Unresolved Problem"</h2>
<p>A <a href="https://en.wikipedia.org/wiki/Large_language_model">large language model</a> (LLM) is non-deterministic in a deeper and more stubborn way than either of the above.</p>
<p>Its weights are the result of a stochastic training process over vast data. Its output is sampled probabilistically (even with <code>temperature=0</code>), and there's pseudo-randomness baked in. And crucially, unlike a neural network trained on a clean truth table, an LLM's "correct output" for most inputs is <em>fundamentally ambiguous</em>.</p>
<p>Yet we're building agentic systems (Claude Code, Codex, Cursor etc) that use LLMs to write, run and iterate on code autonomously. <strong>How do we tame this?</strong></p>
<p>The pattern repeats, but the engineering is particularly <em>messier</em> on LLM's.</p>
<h3 id="tests-as-noise-margins">Tests as noise margins</h3>
<p>A test suite could behave as a binary verdict on the LLM's  output: <em>green or red</em>. It doesn't matter if the model generated three different valid implementations in three runs: if all tests pass, they're equivalent from the system's perspective. The non-determinism of the model is <em>contained</em> below the threshold of "passes tests". This works, but only as well as the tests themselves. And unlike voltage thresholds, test coverage is always incomplete.</p>
<h3 id="the-agentic-loop-as-clock">The agentic loop as clock</h3>
<p>An agentic system like Claude Code doesn't generate once and deliver. It reads state (files, compiler output, test results), acts, observes the new state, and repeats. This feedback loop is structurally similar to the <em>fetch-decode-execute</em> cycle of a CPU or the iterative of Aspirina. Each iteration constrains the space of valid next actions. Errors are observable, and the agent can correct.</p>
<h3 id="the-type-system-and-compiler-as-low-level-validators">The type system and compiler as low-level validators</h3>
<p>In a Rust project like Aspirina, the borrow checker <em>rejects invalid outputs before tests even run</em>. <em>The LLM can generate wrong code and hallucinate, the compiler then refuses it, the agent observes the error message, and iterates.</em></p>
<p><strong>This is a lower-level noise margin</strong>: just a formal filter beneath the test layer and type system.</p>
<blockquote>
<p>And that's why I think that languages with strict compilers like Rust will thrive in the agentic era. Let's see.</p>
</blockquote>
<h3 id="whats-missing-the-equivalent-of-timing-analysis">What's missing: the equivalent of timing analysis</h3>
<p>In hardware, engineers can <em>prove</em> that a circuit will work at a given clock frequency. They run static timing analysis and guarantee that every signal stabilises before every clock edge. There's no equivalent for agentic LLM systems.</p>
<p>We don't know how many iterations an agent will need. We can't bound the convergence time. We can't guarantee termination. An agent can loop indefinitely, or enter what I'd call "agentic metastability": making and undoing the same change repeatedly, unable to reach a stable state.</p>
<p>Anyone who has used Claude Code or Codex for long enough has seen this - the model oscillates between two approaches, each creating a problem that motivates reverting to the other.</p>
<blockquote>
<p>Despite we can retry, add guardrails, skills, and set token budgets, in the end, we can't prove termination the way a hardware engineer proves timing closure on metastability</p>
</blockquote>
<h3 id="how-to-mitigate-that">How to mitigate that?</h3>
<p>In hardware, the fix for metastability is <strong>design</strong>. In agentic systems, the analog fix is <strong>clearer context, more granular tests, explicit checkpoints and tighter feedback loops</strong>; which can be described with the following practical list of skills I created and have been using on a daily basis for every project in production:</p>
<ul>
<li>
<p><strong>PO (product owner)</strong>: agent receives a prompt and outputs a well-scoped task based on initial requirements and prior knowledge on the codebase. Clearer context.</p>
</li>
<li>
<p><strong>TDD (test-driven development)</strong>: the developer agent outputs the code, guided by TDD - red, green, refactor. Granular tests as noise margins.</p>
</li>
<li>
<p><strong>Review</strong>: agent and human checks before merging. Explicit checkpoint.</p>
</li>
<li>
<p><strong>Small PRs</strong>: small PR's enable development and testing with reviewable increments. Tighter feedback loops.</p>
</li>
</ul>
<p>Yes, that's <strong>software engineering practices</strong> all the way down (and they are not new). Yet we don't have the formal tools <em>to prove</em> these fixes work. It's totally empirical.</p>
<hr />
<h2 id="conclusion">Conclusion</h2>
<p>At least for me, what's interesting is that each level's "solved" status depends on <em>bounded, well-defined tasks</em>. Logic gates are deterministic for Boolean logic. Aspirina's networks converge reliably because truth tables are finite and exact. LLMs work well on narrow, testable tasks with earlier and good feedback.</p>
<p>The frontier is: <strong>what does it take to engineer reliable agentic behaviour on open-ended, ambiguous, long-horizon tasks?</strong> The answer probably looks like what came before: more layers of verification, better sampling strategies (the clock), formal specifications (the truth table), and tools that can analyse convergence before execution. <em>We just don't have those yet</em>.</p>
<p>Non-determinism doesn't go away. It never has. We just keep finding better ways to push it where it can't hurt us. From voltage thresholds to synchronizer chains to temperature tuning. Every generation of computing has faced the same enemy and responded with the same weapon: <strong>engineering</strong>. Besides hype, LLMs are no different. We're just earlier in the cycle.</p>
<hr />
<h2 id="references">References</h2>
<p>https://en.wikipedia.org/wiki/Logic_gate
https://en.wikipedia.org/wiki/Electronic_voting_in_Belgium
https://en.wikipedia.org/wiki/Noise_margin
https://en.wikipedia.org/wiki/Metastability_(electronics)
https://en.wikipedia.org/wiki/Sigmoid_function
https://en.wikipedia.org/wiki/Large_language_model
https://en.wikipedia.org/wiki/Backpropagation
https://en.wikipedia.org/wiki/Static_timing_analysis
https://github.com/leandronsp/aspirina
https://github.com/leandronsp/morphine
https://leandronsp.com/articles/ai-ruby-an-introduction-to-neural-networks-23f3</p>
]]></description>
<pubDate>2026-02-19</pubDate>
</item>
<item>
<title>Understanding Recursion Fundamentals</title>
<link>https://leandronsp.com/articles/understanding-recursion-fundamentals.html</link>
<guid>https://leandronsp.com/articles/understanding-recursion-fundamentals.html</guid>
<description><![CDATA[<p>If for you:</p>
<ul>
<li>
<p><strong>Recursion</strong> is an obscure topic or you want to understand it a bit better;</p>
</li>
<li>
<p><strong>Tail call and TCO</strong> are alien communication methods and;</p>
</li>
<li>
<p><strong>Trampoline</strong> is a medicine name</p>
</li>
</ul>
<p><em>Then this article is for you.</em></p>
<p>Here, I'll explain what these terms are in a didactic way and the problems they solve, with examples in <strong>Ruby</strong>. But don't worry because the examples are quite simple to understand, especially since the concepts shown here are <em>language-agnostic</em>.</p>
<p>So, come with me on this <strong>endless</strong> journey.</p>
<blockquote>
<p>✋ To continue, go back to the beginning</p>
</blockquote>
<p><em>Note: This is an English translation of the original article in Portuguese: <a href="https://leandronsp.com/articles/entendendo-fundamentos-de-recursao-2ap4">Entendendo fundamentos de recursão</a></em></p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#what-is-recursion">What is recursion</a></p>
</li>
<li>
<p><a href="#meet-fibo">Meet Fibo</a></p>
</li>
<li>
<p><a href="#tail-call">Tail call</a></p>
</li>
<li>
<p><a href="#stack-and-stack-overflow">Stack and stack overflow</a></p>
</li>
<li>
<p><a href="#tail-call-optimization">Tail call optimization</a></p>
</li>
<li>
<p><a href="#trampoline">Trampoline</a></p>
</li>
<li>
<p><a href="#conclusion">Conclusion</a></p>
</li>
<li>
<p><a href="#references">References</a></p>
</li>
</ul>
<hr />
<h2 id="what-is-recursion">What is recursion</h2>
<p>In computer programs, we're used to <strong>breaking large problems into smaller problems</strong> through the use of functions or methods.</p>
<p><strong>Recursion</strong> is, in an extremely simplified way, a technique in computing where these problems are broken down so that a <em>certain function is executed recursively</em>.</p>
<p>With this, the function "calls itself" to solve some computation and continue its execution.</p>
<hr />
<h2 id="meet-fibo">Meet Fibo</h2>
<p>A very classic example of recursion is discovering, given the <strong>Fibonacci sequence</strong>, or Fibo, which number is found at a certain position.</p>
<pre><code class="sourceCode"><span class="text plain">0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55.........
</span></code></pre>
<p>With this in place, the <strong>fib</strong> function would return results like:</p>
<pre><code class="sourceCode"><span class="text plain">fib(0) = 0
fib(1) = 1
fib(2) = 1
...
fib(7) = 13
fib(10) = 55
</span></code></pre>
<p>We then have a possible recursive implementation in Ruby:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">fib</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">position</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="keyword control pseudo-method ruby">return</span> position <span class="keyword control ruby">if</span> position <span class="keyword operator comparison ruby">&lt;</span> <span class="constant numeric ruby">2</span>

  fib<span class="punctuation definition group begin ruby">(</span>position <span class="keyword operator arithmetic ruby">-</span> <span class="constant numeric ruby">1</span><span class="punctuation definition group end ruby">)</span> <span class="keyword operator arithmetic ruby">+</span> fib<span class="punctuation definition group begin ruby">(</span>position <span class="keyword operator arithmetic ruby">-</span> <span class="constant numeric ruby">2</span><span class="punctuation definition group end ruby">)</span>
<span class="keyword control ruby">end</span>
</span></code></pre>
<p>This code, however, is not performant. When trying to find the number at position <code>10_000</code> (ten thousand) in the sequence, the program becomes very slow because it makes numerous <strong>redundant recursive calls</strong>.</p>
<pre><code class="sourceCode"><span class="text plain">                 fib(10)
             /                \
     fib(9)                 fib(8)
        /          \          /   \
fib(8)     fib(7)     fib(7)    fib(6)
  /      \       /       \       /   \
fib(7) fib(6) fib(6) fib(5) fib(6) fib(5)
   /    \     /     \     /     \     /    \
fib(6) fib(5) fib(5) fib(4) fib(5) fib(4) fib(5) fib(4)
  /   \   /   \   /   \   /   \   /   \   /   \   /   \
...
</span></code></pre>
<p>Consequently, the larger the function input, the execution time of this code tends to grow exponentially, which in <strong>Big-O</strong> notation would be <code>O(2^n)</code>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9udpxmgl34093mpmqvc.png" alt="big O exponential" /></p>
<p>Is it possible to reduce this complexity?</p>
<p>What if we try to apply a technique where the last function call, instead of being the sum of two recursive calls, becomes just <strong>one recursive call</strong>, without performing additional computations?</p>
<p>This technique exists and is called <strong>tail call</strong>, or <em>tail recursion</em>.</p>
<hr />
<h2 id="tail-call">Tail call</h2>
<p><strong>Tail call</strong>, or <strong>TC</strong>, consists of a recursive function where the last recursive call is the function itself without additional computation.</p>
<p>With this in place, we reduce the complexity from exponential to linear, as if it were a <em>simple loop iterating over a list of inputs</em>.</p>
<p>In Big-O notation this becomes <code>O(n)</code>, meaning the complexity grows linearly following the growth of the input.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z8uj2fzw9090971awu89.png" alt="big O linear" /></p>
<p>Example in Ruby:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">fib</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">position</span><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">_current</span> </span><span class="meta function parameters default-value ruby"><span class="keyword operator assignment ruby">=</span></span><span class="meta function parameters default-value ruby"> <span class="constant numeric ruby">0</span></span><span class="meta function parameters ruby"><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">_next</span> </span><span class="meta function parameters default-value ruby"><span class="keyword operator assignment ruby">=</span></span><span class="meta function parameters default-value ruby"> <span class="constant numeric ruby">1</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="keyword control pseudo-method ruby">return</span> _current <span class="keyword control ruby">if</span> position <span class="keyword operator comparison ruby">&lt;</span> <span class="constant numeric ruby">1</span>

  fib<span class="punctuation definition group begin ruby">(</span>position <span class="keyword operator arithmetic ruby">-</span> <span class="constant numeric ruby">1</span><span class="punctuation separator ruby">,</span> _next<span class="punctuation separator ruby">,</span> _current <span class="keyword operator arithmetic ruby">+</span> _next<span class="punctuation definition group end ruby">)</span>
<span class="keyword control ruby">end</span>
</span></code></pre>
<p>Therefore, the number of recursive calls is drastically reduced to something like:</p>
<pre><code class="sourceCode"><span class="text plain">fib(10, 0, 1)
fib(9, 1, 1)
fib(8, 1, 2)
fib(7, 2, 3)
fib(6, 3, 5)
fib(5, 5, 8)
fib(4, 8, 13)
fib(3, 13, 21)
fib(2, 21, 34)
fib(1, 34, 55)
fib(0, 55, 89)
</span></code></pre>
<p>Notice how the number of recursive calls decreased, meaning the code is following a more <strong>linear</strong> path with this approach.</p>
<p>Thus, when running the <strong>fib with TC</strong> program, the execution time is exponentially less than running without TC, being <em>tens of thousands of times faster</em>.</p>
<blockquote>
<p>✋
Clearly a program that takes exponential time is terribly poor performance-wise, right?</p>
</blockquote>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Without TC
</span>fib<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">30</span><span class="punctuation definition group end ruby">)</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> 0.75 seconds
</span>
<span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> With TC
</span>fib<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">30</span><span class="punctuation definition group end ruby">)</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> 0.000075 seconds
</span></span></code></pre>
<p>Going back to the example of <code>fib(10000)</code>, when running with TC, we see that execution is much faster, however:</p>
<pre><code class="sourceCode"><span class="text plain">recursion/fib.rb:10:in `fib_tc&#39;: stack level too deep (SystemStackError)
        from recursion/fib.rb:10:in `fib_tc&#39;
        from recursion/fib.rb:10:in `fib_tc&#39;
        from recursion/fib.rb:10:in `fib_tc&#39;
        from recursion/fib.rb:10:in `fib_tc&#39;
        from recursion/fib.rb:10:in `fib_tc&#39;
        from recursion/fib.rb:10:in `fib_tc&#39;
        from recursion/fib.rb:10:in `fib_tc&#39;
        from recursion/fib.rb:10:in `fib_tc&#39;
</span></code></pre>
<p><em>Uh oh</em>, a <strong>stack overflow!</strong></p>
<p>To understand what's happening, let's first understand what the heck is a <strong>stack</strong> and <strong>stack overflow</strong>.</p>
<hr />
<h2 id="stack-and-stack-overflow">Stack and stack overflow</h2>
<p>When a program is executed, a data structure in the form of a <em>stack</em>, called <strong>Stack</strong> (duh), is allocated in memory and is used to store the data being used in a running function.</p>
<blockquote>
<p>✋
There's also another structure in the program's memory called <strong>Heap</strong>, which is not a stack and has other traits that are beyond the scope of this article. To understand recursion, we focus only on the stack</p>
</blockquote>
<p>When the program enters a function or method, each piece of data is <em>pushed onto the stack</em>. When the function finishes, the <em>removal (pop) of each piece of data</em> is done.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rstqf6yz2yph2d7byeuq.png" alt="stack" /></p>
<p>With each function call, a new <em>stack frame</em> is assigned. Since a recursive call never ends, the runtime doesn't know it needs to "pop" the data and finish the frame, so at every call, a new stack frame is created and <strong>more elements are added</strong> to the stack.</p>
<p>Guess what happens when we add too much data to the stack to the point of <strong>exceeding its limit</strong> in the computer's memory?</p>
<p>Yes, the infamous <strong>Stack overflow</strong> happens 💥🪲, and this explains that error in Ruby when running fib of 10000 with tail call.</p>
<blockquote>
<p>✋
So does that mean calculating fib of 10000 is an impossible problem to solve with recursion?</p>
</blockquote>
<p>Hold on, some languages employ an optimization technique that consists of using the tail call with <em>just one stack frame</em>, hence ensuring that each recursive call is treated as if it were <strong>an iteration in a primitive loop.</strong></p>
<p>With this, the function's arguments and data are manipulated in a single stack frame, exactly as if we had written a primitive loop. And consequently, new tail recursive calls won't cause stack overflow.</p>
<p>We call this technique <strong>Tail call optimization</strong>, or <em>TCO</em>.</p>
<hr />
<h2 id="tail-call-optimization">Tail call optimization</h2>
<p>Due to its imperative nature, and like several other general-purpose languages, <em>Ruby doesn't have native TCO support</em>.</p>
<p>Usually this optimization is more commonly found in languages with a strong inclination toward the functional paradigm, rather than the imperative one.</p>
<p>But in Ruby it's possible to <em>enable TCO mode</em> with a simple configuration in the Ruby runtime instruction (YARV), and thus we can execute fib of 10000 without pain.</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="support class ruby">RubyVM</span><span class="punctuation accessor ruby">::</span><span class="support class ruby">InstructionSequence</span><span class="punctuation accessor ruby">.</span>compile_option <span class="keyword operator assignment ruby">=</span> <span class="punctuation section scope ruby">{</span>
  <span class="constant other symbol ruby">tailcall_optimization<span class="punctuation definition constant ruby">:</span></span> <span class="constant language ruby">true</span><span class="punctuation separator ruby">,</span>
  <span class="constant other symbol ruby">trace_instruction<span class="punctuation definition constant ruby">:</span></span> <span class="constant language ruby">false</span>
<span class="punctuation section scope ruby">}</span>

<span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">fib</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">position</span><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">_current</span> </span><span class="meta function parameters default-value ruby"><span class="keyword operator assignment ruby">=</span></span><span class="meta function parameters default-value ruby"> <span class="constant numeric ruby">0</span></span><span class="meta function parameters ruby"><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">_next</span> </span><span class="meta function parameters default-value ruby"><span class="keyword operator assignment ruby">=</span></span><span class="meta function parameters default-value ruby"> <span class="constant numeric ruby">1</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="keyword control pseudo-method ruby">return</span> _current <span class="keyword control ruby">if</span> position <span class="keyword operator comparison ruby">&lt;</span> <span class="constant numeric ruby">1</span>

  fib<span class="punctuation definition group begin ruby">(</span>position <span class="keyword operator arithmetic ruby">-</span> <span class="constant numeric ruby">1</span><span class="punctuation separator ruby">,</span> _next<span class="punctuation separator ruby">,</span> _current <span class="keyword operator arithmetic ruby">+</span> _next<span class="punctuation definition group end ruby">)</span>
<span class="keyword control ruby">end</span>

<span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> TC with TCO
</span>fib<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">10000</span><span class="punctuation definition group end ruby">)</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> 0.02 seconds
</span></span></code></pre>
<p><strong>Superb</strong>! With TCO enabled, a fib 10000 with tail call is executed in <em>0.02 seconds</em>!</p>
<p><em>It's worth remembering that TCO is a technique used not only in recursion but also in instruction generation optimization in compilers, but this is beyond the scope of this article.</em></p>
<blockquote>
<p>✋
Okay, but what if it's not possible to enable TCO for tail recursion or I'm programming in a language that doesn't have TCO support?</p>
</blockquote>
<p><strong>Trampoline</strong> to the rescue.</p>
<hr />
<h2 id="trampoline">Trampoline</h2>
<p>To understand <em>trampoline</em>, let's think about the problem and a possible solution.</p>
<p>If we think smart, we can initially conclude that recursion should be avoided, and this is <em>premise number one</em>.</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">fib</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">position</span><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">_current</span> </span><span class="meta function parameters default-value ruby"><span class="keyword operator assignment ruby">=</span></span><span class="meta function parameters default-value ruby"> <span class="constant numeric ruby">0</span></span><span class="meta function parameters ruby"><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">_next</span> </span><span class="meta function parameters default-value ruby"><span class="keyword operator assignment ruby">=</span></span><span class="meta function parameters default-value ruby"> <span class="constant numeric ruby">1</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="keyword control pseudo-method ruby">return</span> _current <span class="keyword control ruby">if</span> position <span class="keyword operator comparison ruby">&lt;</span> <span class="constant numeric ruby">1</span>

  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>##################################
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>### We must avoid this!!!!!! ####
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>##################################
</span>  fib<span class="punctuation definition group begin ruby">(</span>position <span class="keyword operator arithmetic ruby">-</span> <span class="constant numeric ruby">1</span><span class="punctuation separator ruby">,</span> _next<span class="punctuation separator ruby">,</span> _current <span class="keyword operator arithmetic ruby">+</span> _next<span class="punctuation definition group end ruby">)</span>
<span class="keyword control ruby">end</span>
</span></code></pre>
<p>Premise two, instead of returning a recursive call directly, what if we return it <strong>encapsulated in an anonymous function structure that stores context</strong> to be executed in another context?</p>
<blockquote>
<p>Yes, like a closure or lambda for the more attentive readers</p>
</blockquote>
<p>In Ruby, we can use the concept of <strong>lambdas</strong>.</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">fib</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">position</span><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">_current</span> </span><span class="meta function parameters default-value ruby"><span class="keyword operator assignment ruby">=</span></span><span class="meta function parameters default-value ruby"> <span class="constant numeric ruby">0</span></span><span class="meta function parameters ruby"><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">_next</span> </span><span class="meta function parameters default-value ruby"><span class="keyword operator assignment ruby">=</span></span><span class="meta function parameters default-value ruby"> <span class="constant numeric ruby">1</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="keyword control pseudo-method ruby">return</span> _current <span class="keyword control ruby">if</span> position <span class="keyword operator comparison ruby">&lt;</span> <span class="constant numeric ruby">1</span>

  <span class="support function builtin ruby">lambda</span> <span class="keyword control start-block ruby">do</span>
    fib<span class="punctuation definition group begin ruby">(</span>position <span class="keyword operator arithmetic ruby">-</span> <span class="constant numeric ruby">1</span><span class="punctuation separator ruby">,</span> _next<span class="punctuation separator ruby">,</span> _current <span class="keyword operator arithmetic ruby">+</span> _next<span class="punctuation definition group end ruby">)</span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>
</span></code></pre>
<p>If we call <code>result = fib(0)</code>, because of the first line's short-circuit (<code>position &lt; 1</code>), the method's return is <code>0</code>.</p>
<p>But if we call <code>result = fib(10)</code>, the return won't be a recursive call, but rather the <strong>return will be an anonymous function</strong> (lambda).</p>
<p>By doing this, the method is then finished and the <em>stack is cleared</em>, meaning the <strong>pop of data</strong> is done from within the method.</p>
<p>Since lambdas store context, if we call <code>result.call</code>, the lambda is executed with the previous context, which can return the final number (if it enters the short-circuit) or another lambda with the new context.</p>
<p>And so, <strong>we loop until we have the final value</strong>, while the current return continues to be a lambda. Did you understand what we can do?</p>
<p>Yes, a <em>loop!</em></p>
<pre><code class="sourceCode language-ruby"><span class="source ruby">result <span class="keyword operator assignment ruby">=</span> fib<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">10000</span><span class="punctuation definition group end ruby">)</span>

<span class="keyword control ruby">while</span> result<span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">is_a?</span><span class="punctuation definition group begin ruby">(</span><span class="variable other constant ruby">Proc</span><span class="punctuation definition group end ruby">)</span>
  result <span class="keyword operator assignment ruby">=</span> result<span class="punctuation accessor ruby">.</span>call
<span class="keyword control ruby">end</span>

<span class="support function builtin ruby">puts</span> result
</span></code></pre>
<p>Output (a really very large number):</p>
<pre><code class="sourceCode"><span class="text plain">33644764876431783266621612005107543310302148460680063906564769974680081442166662368155595513633734025582065332680836159373734790483865268263040892463056431887354544369559827491606602099884183933864652731300088830269235673613135117579297437854413752130520504347701602264758318906527890855154366159582987279682987510631200575428783453215515103870818298969791613127856265033195487140214287532698187962046936097879900350962302291026368131493195275630227837628441540360584402572114334961180023091208287046088923962328835461505776583271252546093591128203925285393434620904245248929403901706233888991085841065183173360437470737908552631764325733993712871937587746897479926305837065742830161637408969178426378624212835258112820516370298089332099905707920064367426202389783111470054074998459250360633560933883831923386783056136435351892133279732908133732642652633989763922723407882928177953580570993691049175470808931841056146322338217465637321248226383092103297701648054726243842374862411453093812206564914032751086643394517512161526545361333111314042436854805106765843493523836959653428071768775328348234345557366719731392746273629108210679280784718035329131176778924659089938635459327894523777674406192240337638674004021330343297496902028328145933418826817683893072003634795623117103101291953169794607632737589253530772552375943788434504067715555779056450443016640119462580972216729758615026968443146952034614932291105970676243268515992834709891284706740862008587135016260312071903172086094081298321581077282076353186624611278245537208532365305775956430072517744315051539600905168603220349163222640885248852433158051534849622434848299380905070483482449327453732624567755879089187190803662058009594743150052402532709746995318770724376825907419939632265984147498193609285223945039707165443156421328157688908058783183404917434556270520223564846495196112460268313970975069382648706613264507665074611512677522748621598642530711298441182622661057163515069260029861704945425047491378115154139941550671256271197133252763631939606902895650288268608362241082050562430701794976171121233066073310059947366875
</span></code></pre>
<p>🔑 <strong>Key point</strong>
And with this, friends, we have the <strong>trampoline</strong> technique: a non-recursive primitive <strong>loop</strong> that keeps calling another function <em>written recursively</em> but that returns a lambda with context, <strong>until reaching the final value</strong>.</p>
<p>This code, <strong>without TCO</strong>, for <strong>fib of 10000</strong>, takes 0.04 seconds, a result very close to TCO and without causing stack overflow.</p>
<p><em>Incredible, right?</em> Now there are no excuses for not writing a function recursively in languages that don't have TCO support 😛</p>
<hr />
<h2 id="conclusion">Conclusion</h2>
<p>In this article, the intent was to bring some concepts and fundamentals around the <strong>recursion</strong> topic. These concepts overlap with very academic topics that sometimes make it difficult for people who are starting in the field or who don't have a very academic background to understand.</p>
<p>I hope I've clarified the recursion subject in a didactic way. If you can, leave any corrections or relevant information in the comments.</p>
<hr />
<h2 id="references">References</h2>
<p>https://en.wikipedia.org/wiki/Fibonacci_sequence
https://en.wikipedia.org/wiki/Recursion
https://www.geeksforgeeks.org/stack-data-structure/
https://en.wikipedia.org/wiki/Tail_call
https://en.wikipedia.org/wiki/Trampoline_(computing)
https://nithinbekal.com/posts/ruby-tco/
https://www.bigocheatsheet.com/
https://ruby-doc.org/core-3.1.0/RubyVM/InstructionSequence.html#method-c-compile_option</p>
]]></description>
<pubDate>2025-11-14</pubDate>
</item>
<item>
<title>Arrays in x86 Assembly</title>
<link>https://leandronsp.com/articles/arrays-in-x86-assembly.html</link>
<guid>https://leandronsp.com/articles/arrays-in-x86-assembly.html</guid>
<description><![CDATA[<p><em>Originally posted in <a href="https://leandronsp.com/articles/arrays-em-assembly-x86-55hb">Portuguese</a></em></p>
<p>Recently I wrote <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-i-introducao-14p5">a 6-article series</a> about x86 Assembly (written in Portuguese, but I'm planning to translate the guide to English soon), covering fundamental concepts of computer architecture and low-level programming while building a minimalist multi-threaded web server.</p>
<p>During the process, I left some important concepts aside for later articles, because if I had tackled them during the series, it would have been even longer than it already was. However, these are concepts that can be addressed separately, like the queues implemented in the thread pool.</p>
<p>And when we talk about queues, <strong>it's inevitable to address arrays</strong> and how they're organized in computer memory.</p>
<p>In this article, we'll cover fundamental concepts like memory manipulation, registers, and heap memory while implementing arrays.</p>
<blockquote>
<p>I'm assuming you're already familiar with x86 Assembly and the GDB tool. If not, I strongly recommend reading my series.</p>
</blockquote>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#arrays-dont-exist">Arrays don't exist</a></p>
</li>
<li>
<p><a href="#strings-dont-exist-either">Strings don't exist either</a></p>
</li>
<li>
<p><a href="#the-simplest-array-in-the-universe">The simplest array in the universe</a></p>
</li>
<li>
<p><a href="#using-an-array-with-uninitialized-data">Using an array with uninitialized data</a></p>
<ul>
<li><a href="#index-to-the-rescue">Index to the rescue</a></li>
<li><a href="#hitting-the-array-limit">Hitting the array limit</a></li>
</ul>
</li>
<li>
<p><a href="#heap-heap-hooray">Heap, heap, hooray!</a></p>
<ul>
<li><a href="#dynamic-memory-allocation-with-brk">Dynamic memory allocation with brk</a></li>
<li><a href="#pointers-pointers-everywhere">Pointers, pointers everywhere</a></li>
<li><a href="#resize-with-brk">Resize with brk</a></li>
</ul>
</li>
<li>
<p><a href="#the-final-program">The final program</a></p>
</li>
<li>
<p><a href="#conclusion">Conclusion</a></p>
</li>
<li>
<p><a href="#references">References</a></p>
</li>
</ul>
<hr />
<h2 id="arrays-dont-exist">Arrays don't exist</h2>
<p><em>Arrays don't exist.</em> Simple as that.</p>
<p>As we saw <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iv-um-assembly-modesto-oif">in part IV</a> of the series, memory is organized contiguously, where information is allocated one after another.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u90q0z4ka96nccs1syef.png" alt="contiguous memory" /></p>
<p>Suppose we want to declare the following sequence of information:</p>
<pre><code class="sourceCode"><span class="text plain">1, 2, &#39;H&#39;, 0
</span></code></pre>
<blockquote>
<p>I know, I know, the types are mixed, but that doesn't matter right now. They all fit in 1 byte</p>
</blockquote>
<p>In x86 assembly (let's call it asm for the rest of the article), we can declare this information in the data section like this:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
stuff<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0x1</span>, <span class="constant numeric actionscript 2">0x2</span>, <span class="constant numeric actionscript 2">0x48</span>, <span class="constant numeric actionscript 2">0x0</span>
</span></code></pre>
<blockquote>
<p>Remember that the character 'H' in the ASCII table represents 0x48 in hexadecimal</p>
</blockquote>
<p>Using <code>gdb</code> for debugging, we can confirm that this hexadecimal sequence at the <code>stuff</code> label is stored as follows:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Reading the first hexbyte in stuff</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/1xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">stuff</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>stuff<span class="keyword operator assignment redirection shell">&gt;</span>:       0x01</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Reading the second hexbyte in stuff</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/1xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">stuff+1</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402001:</span></span><span class="meta function-call arguments shell">       0x02</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Reading the third hexbyte in stuff</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/1xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">stuff+2</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002:</span></span><span class="meta function-call arguments shell">       0x48</span>
</span></code></pre>
<p>We can also represent the hexadecimal <code>0x48</code> in string format using <code>x/s</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/s (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">stuff+2</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002:</span></span><span class="meta function-call arguments shell">       <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>H<span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<p><em>It's all hexadecimal!</em></p>
<p>With this, if we want to represent the string "Hello", according to the ASCII table, it could look like this:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0x48</span>, <span class="constant numeric actionscript 2">0x65</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6F</span>, <span class="constant numeric actionscript 2">0x0</span>
</span></code></pre>
<p>In gdb, let's check the string representation of the <code>msg</code> label:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/s</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">msg</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>msg<span class="keyword operator assignment redirection shell">&gt;</span>: <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Hello<span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<p>In asm, it's possible to declare the string with direct ASCII table representation:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0x0</span>

; same as
; msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0x48</span>, <span class="constant numeric actionscript 2">0x65</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6F</span>, <span class="constant numeric actionscript 2">0x0</span>
</span></code></pre>
<hr />
<h2 id="strings-dont-exist-either">Strings don't exist either</h2>
<p>In other words, it's all hexadecimal in memory. An array, like a string, is simply a contiguous sequence of data <strong>with the same size</strong> in memory.</p>
<p>The difference is that a string is a "special array" that has data representing ASCII table characters (note that both need to delimit a "final" byte to represent the end of the string or array):</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dw5cjo8fvoh7rvp8t2l3.png" alt="string and array" /></p>
<h2 id="the-simplest-array-possible">The simplest array possible</h2>
<p>Below we have the implementation of a very simple array in asm, which we'll explore step by step in subsequent sections:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">data</span>
array<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">1</span>, <span class="constant numeric actionscript 2">2</span>, <span class="constant numeric actionscript 2">3</span>, <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov al, [array]        ; array[<span class="constant numeric actionscript 2">0</span>]
	mov bl, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>]    ; array[<span class="constant numeric actionscript 2">1</span>]
	mov cl, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">2</span>]    ; array[<span class="constant numeric actionscript 2">2</span>]
	mov sil, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">3</span>]   ; array[<span class="constant numeric actionscript 2">3</span>]
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
</span></code></pre>
<p>In the initialized data section <code>.data</code>, we declare an array with 3 elements of 1 byte each (integers from 1 to 3), using the number 0 as the array terminator:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
array<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">1</span>, <span class="constant numeric actionscript 2">2</span>, <span class="constant numeric actionscript 2">3</span>, <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<p>Next, in the <code>.text</code> section, which is where the program's source code goes, we can access array elements using pointer arithmetic, storing the result in registers:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
mov al, [array]        ; array[<span class="constant numeric actionscript 2">0</span>]
</span></code></pre>
<p>In the code above, we're accessing the value contained at memory address <code>0x402000</code> and storing the result in a register (AL) that has a size of 1 byte, meaning only the first byte of the array will be stored in the register.</p>
<p>Let's check with gdb:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> The array is stored at address 0x402000</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> and contains the hex value 0x00 0x03 0x02 0x01,</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> remembering that this architecture uses little-endian format</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00030201</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 13</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> In register AL we have the first element of the array</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r al</span>
<span class="meta function-call shell"><span class="variable function shell">al</span></span><span class="meta function-call arguments shell">             0x1                 1</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> It&#39;s the same as accessing the first hexbyte contained at address</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x402000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/1xb 0x402000</span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x01</span>

</span></code></pre>
<blockquote>
<p>Remember that the AL register represents the lower 8-bits within the spectrum of the RAX register which encompasses a total of 64-bits in the x86_64 architecture</p>
</blockquote>
<p>To access the other array elements, just do pointer arithmetic and store in other 1-byte registers:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov al, [array]        ; array[<span class="constant numeric actionscript 2">0</span>] <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">1</span>
mov bl, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>]    ; array[<span class="constant numeric actionscript 2">1</span>] <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">2</span>
mov cl, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">2</span>]    ; array[<span class="constant numeric actionscript 2">2</span>] <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">3</span>
mov sil, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">3</span>]   ; array[<span class="constant numeric actionscript 2">3</span>] <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">0</span> (array ends here)
</span></code></pre>
<hr />
<h2 id="using-an-array-with-uninitialized-data">Using an array with uninitialized data</h2>
<p>So far, we're declaring the array in the <code>.data</code> section where data is initialized. But we can make the program more "dynamic" by declaring the array in the section of <strong>uninitialized</strong> data, which is <code>.bss</code>.</p>
<p>Keeping compatibility with the previous example, let's declare a 4-byte array using the <code>resb</code> directive which means "reserve byte", where the first 3 bytes are reserved to store array elements and the last byte representing 0x0 which is the array terminator.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">4</span> ; <span class="constant numeric actionscript 2">3</span> bytes <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span> terminator byte
</span></code></pre>
<p>In gdb, we can see that the array is initialized with all values at zero, indicating that the array is empty but has 4 bytes reserved:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000000</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/4xb</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00    0x00    0x00    0x00</span>
</span></code></pre>
<p>To add elements to the array, we also need to use pointer arithmetic, just like we did in the previous example to access an array with pre-initialized data.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; Move <span class="support function actionscript 2">value</span> <span class="constant numeric actionscript 2">1</span> to the <span class="support function actionscript 2">first</span> byte of the memory address at array
mov byte [array], <span class="constant numeric actionscript 2">1</span>  ; array[<span class="constant numeric actionscript 2">0</span>] <span class="keyword operator symbolic actionscript 2">=</span> <span class="constant numeric actionscript 2">1</span>
</span></code></pre>
<p>With gdb we confirm that at address 0x402000 where the array is, byte 1 was added:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000001</span>
</span></code></pre>
<p>And if we want to add value 2 to the next byte of the array?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>], <span class="constant numeric actionscript 2">2</span>
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000201</span>
</span></code></pre>
<p>Notice that what changes is the array "index". At the initial position of the array, it's like the index is zero, and at the subsequent position, we use index 1, which can be incremented until the array terminator.</p>
<p>It would be very complicated to keep manipulating a hard-coded index. We need a <em>pointer</em> to represent this index.</p>
<h3 id="index-to-the-rescue">Index to the rescue</h3>
<p>Assuming the array pointer starts with <em>zero</em>, which is the memory address where the array is, we can declare it in the initialized data section <code>.data</code>:</p>
<pre><code class="sourceCode"><span class="text plain">section .bss
array: resb 4 ; 3 bytes + 1 terminator byte

section .data
pointer: db 0
</span></code></pre>
<p>So, we could add the first element like this, right?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> pointer], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<p>When running the program, we get this error:</p>
<pre><code class="sourceCode"><span class="text plain">src/live.asm:14: error: invalid effective address: multiple base segments
</span></code></pre>
<p><strong>This error indicates that we're trying to do pointer manipulation from multiple memory segments</strong>, in this case array and pointer.</p>
<p>To solve this, we need to do pointer manipulation with immediate values (which was the previous case with hard-coded numbers) or with registers:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; append(<span class="constant numeric actionscript 2">1</span>)
mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<ul>
<li>
<p>the first instruction moves the first byte contained at the <code>pointer</code> address and stores it in register AL</p>
</li>
<li>
<p>the second instruction moves immediate value 1 (array element) to the array's memory address. Since RAX (64-bit version of AL) has value <code>0x0</code> representing the pointer, we're inserting at the first byte of the array</p>
</li>
</ul>
<p>And to store the second element in the array?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; append(<span class="constant numeric actionscript 2">2</span>)
mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">2</span>
</span></code></pre>
<p>In gdb, let's check what's happening:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000002</span>
</span></code></pre>
<p><em>Uh, oh...</em> This way we're overwriting the previous value. We actually want the pointer to "move", that is, it needs to be incremented by one byte so that <code>append(2)</code> results in 2 elements in the array.</p>
<p>With the <code>INC</code> instruction we can solve this problem:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov al, byte [pointer]      ; pointer <span class="keyword operator symbolic actionscript 2">-</span>&gt; <span class="constant numeric actionscript 2">0</span>
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
inc byte [pointer]          ; pointer <span class="keyword operator symbolic actionscript 2">-</span>&gt; <span class="constant numeric actionscript 2">1</span>

mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">2</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000201</span>
</span></code></pre>
<p><em>Yay!</em> What a wonderful day!</p>
<h3 id="hitting-the-array-limit">Hitting the array limit</h3>
<p>And if we keep incrementing the pointer until we hit the array limit?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
inc byte [pointer]

mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">2</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>
inc byte [pointer]

mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">3</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">2</span>
inc byte [pointer]
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Reading the first 4 hexabytes of the array, we have the representation</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> of the full array with all spaces occupied, remembering that</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> the last byte is the array terminator</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /4xb</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x01    0x02    0x03    0x00</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> The pointer is at the end of the array</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x03</span>
</span></code></pre>
<p>Wonderful, and if we add one more element, should our program allow it?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">4</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">3</span>
inc byte [pointer]
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> We shouldn&#39;t allow another element to be added,</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> since our array was already full</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /4xb</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x01    0x02    0x03    0x04</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> The pointer is beyond the array capacity (not good...)</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x04</span>
</span></code></pre>
<p>Let's use a conditional jump (I explain more about this in the <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iv-um-assembly-modesto-oif">series</a>) to not allow the element to be added. With this, before appending to the array, we should check if the pointer is already at the end of the array:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
je .exit                ; jump to .exit routine <span class="keyword control actionscript 2">if</span> flag is raised
</span></code></pre>
<p>Here's the complete program:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>

section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">4</span> ; <span class="constant numeric actionscript 2">3</span> bytes <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span> terminator byte

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .exit

	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
	inc byte [pointer]

	cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .exit

	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">2</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>
	inc byte [pointer]

	cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .exit

	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">3</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">2</span>
	inc byte [pointer]

	cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .exit

	; shouldn<span class="string quoted single actionscript 2"><span class="punctuation definition string begin actionscript 2">&#39;</span>t allow adding the fourth element,
	; since the array supports up to 3 elements. this way,
	; we<span class="punctuation definition string end actionscript 2">&#39;</span></span>d be writing to the memory address of other
	; program <span class="support function actionscript 2">data</span>
	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">4</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">3</span>
	inc byte [pointer]
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x00000003</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00030201</span>
</span></code></pre>
<p>Perfect, let's now do a small refactoring in the code separating the append logic into a subroutine:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb CAPACITY <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">1</span>
	<span class="support function actionscript 2">call</span> .append

	mov rdi, <span class="constant numeric actionscript 2">2</span>
	<span class="support function actionscript 2">call</span> .append

	mov rdi, <span class="constant numeric actionscript 2">3</span>
	<span class="support function actionscript 2">call</span> .append

	mov rdi, <span class="constant numeric actionscript 2">4</span>
	<span class="support function actionscript 2">call</span> .append
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .done

	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], dil
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
</span></code></pre>
<blockquote>
<p>If you want to understand more about conditional jump, routines, call, ret and flags, I suggest reading my series which has been referenced several times in this article</p>
</blockquote>
<p>Running with gdb and...</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00030201</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x00000003</span>
</span></code></pre>
<p>A big <em>Yay!</em></p>
<p>However, there may be situations where we want our array to be <em>resized</em> to support more elements, that is, the array size would be dynamic.</p>
<p>How do we add more elements beyond the <em>initial capacity</em> without writing to other memory areas that don't belong to the array?</p>
<hr />
<h2 id="heap-heap-hooray">Heap, heap, hooray!</h2>
<p>Before talking about the heap, let's remember how the memory layout of a computer program works:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s81vxvgfylw0wfcf6if7.png" alt="memory layout" /></p>
<ul>
<li>
<p>the layout is represented as an area in computer memory where we have the program's lowest memory addresses toward the highest addresses at the top</p>
</li>
<li>
<p>at the lowest memory addresses, we have the <code>.text</code> section, where we've already seen that it refers to the program itself</p>
</li>
<li>
<p>then we have the <strong>data section</strong> which encompasses initialized data <code>.data</code> and the following section representing uninitialized data <code>.bss</code></p>
</li>
<li>
<p>at the highest addresses, we have the program's <em>stack</em>, which stores metadata such as the program name, its arguments and any program information that has a fixed size fitting within the stack, as well as function calls and their respective arguments</p>
</li>
<li>
<p>the stack has a <em>stack</em> format and "grows downward", that is, as we add elements to the stack, it grows toward lower addresses in memory</p>
</li>
</ul>
<p>In the "middle" of the layout, between the data section and the stack, we have a large area in memory that many end up associating as <em>heap</em>. In the heap, we can allocate data dynamically, unlike the static way we do in the data section.</p>
<p>To accommodate a dynamic-sized array that supports resizing, we have to allocate memory in this area.</p>
<blockquote>
<p>In this article, we'll call this region in the middle of memory between the data section and the stack <strong>heap</strong></p>
</blockquote>
<h3 id="dynamic-memory-allocation-with-brk">Dynamic memory allocation with brk</h3>
<p>One way to manipulate this memory area is through the <a href="https://man7.org/linux/man-pages/man2/brk.2.html">brk syscall</a>, which changes the <em>program break</em>, which is <strong>where the data section ends</strong>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c703vs0c7bl1eosh5i8.png" alt="program break" /></p>
<p>With <code>brk</code>, we can modify this <em>program break</em> to higher addresses, that is, allowing manipulation of memory areas that go beyond the program and data section.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jh2x79f2nb1m1v4dcaxe.png" alt="program break visualized" /></p>
<p>The first thing we need to do is map the syscall and make the call that brings the current break address:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
....

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
; syscall to access the program <span class="keyword control actionscript 2">break</span> (<span class="constant numeric actionscript 2">0x403000</span>), which is where
; the <span class="support function actionscript 2">data</span> section ends <span class="support function actionscript 2">and</span> the heap begins
mov rdi, <span class="constant numeric actionscript 2">0</span>
mov rax, SYS_brk
syscall
....
</span></code></pre>
<p>With gdb, let's analyze the program state:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint at brk syscall line</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 18</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> The program start is in the .text section and begins at</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x401000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x _start</span>
<span class="meta function-call shell"><span class="variable function shell">0x401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>:      0x000000bf</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> The pointer is in the .data section a bit higher and starts at</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x402000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x00000000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> The array is in the .bss section a bit higher and starts at</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x402004</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Execute the brk syscall</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> The brk syscall stores in RAX the program break memory address,</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> in this case a bit higher at 0x403000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rax</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x403000            4206592</span>
</span></code></pre>
<ul>
<li>
<p><code>0x401000</code>: <code>.text</code> section which is where the program begins</p>
</li>
<li>
<p><code>0x402000</code>: <code>.data</code> section where initialized data is</p>
</li>
<li>
<p><code>0x402004</code>: <code>.bss</code> section where uninitialized data is</p>
</li>
<li>
<p><code>0x403000</code>: program break, which is where the data section ends and our "heap" begins</p>
</li>
</ul>
<p>With this, from address <code>0x403000</code> onwards is where we'll put our array elements, so the array address can use just one byte, which points to the address where the first element begins in the heap.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkuui4ot8ta2ohpf05bx.png" alt="array in heap" /></p>
<p>In the syscall we made, if the argument in RDI is zero, it means brk will return the current program break, in this case <code>0x403000</code>. But we can make more brk syscalls with a different RDI argument (incremented), signaling that we're changing the program break.</p>
<p>From now on, in the <code>.bss</code> data section, we no longer need to reserve 4 bytes for the array, so only 1 byte is needed which will represent the array's memory address in the heap:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

; initially starts <span class="support function actionscript 2">with</span> <span class="constant numeric actionscript 2">0x000000</span>, but will later contain
; address <span class="constant numeric actionscript 2">0x403000</span>
section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

...
...
</span></code></pre>
<p>Analyzing with gdb:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint at first syscall</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 18</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Execute the syscall line</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> In RAX the syscall stores the program break address, in this case</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x403000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rax</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x403000            4206592</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       Cannot access memory at address 0x403000</span>
</span></code></pre>
<p>At this moment, this address is not yet accessible because we haven't reserved new bytes in the heap. Let's move forward with the next syscall:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Before executing the syscall, we verify that argument RDI will</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> contain the desired address for the new program break, in this case with</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 3 bytes added, 0x403003</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdi</span>
<span class="meta function-call shell"><span class="variable function shell">rdi</span></span><span class="meta function-call arguments shell">            0x403003            4206595</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Execute the syscall...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> After executing the second syscall, we see that in RAX, the program break was changed to 0x403003</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rax</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x403003            4206595</span>
</span></code></pre>
<p>Now, we can access memory addresses between <code>0x403000</code> and <code>0x403003</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       0x00000000</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403001</span>
<span class="meta function-call shell"><span class="variable function shell">0x403001:</span></span><span class="meta function-call arguments shell">       0x00000000</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403002</span>
<span class="meta function-call shell"><span class="variable function shell">0x403002:</span></span><span class="meta function-call arguments shell">       0x00000000</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403003</span>
<span class="meta function-call shell"><span class="variable function shell">0x403003:</span></span><span class="meta function-call arguments shell">       0x00000000</span>
</span></code></pre>
<p><em>Wow!</em> Now we have in the heap a reserved area especially for our dear array, how cool is that!</p>
<p>How are we going to manipulate the array in this memory region?</p>
<h3 id="pointers-pointers-everywhere">Pointers, pointers everywhere</h3>
<p>After the first syscall, we should take the memory address <code>0x403000</code> which represents the first program break and store it in the array pointer that's in <code>.bss</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">...
mov rdi, <span class="constant numeric actionscript 2">0</span>
mov rax, SYS_brk
syscall
mov [array], rax      ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> breakpoint here

mov rdi, rax
<span class="support function actionscript 2">add</span> rdi, CAPACITY
mov rax, SYS_brk
syscall
...
</span></code></pre>
<p>Let's check with gdb the breakpoint at the line that changes the array pointer:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 19</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Execute the line that changes the pointer</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Now the pointer points to address 0x403000,</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> this is what we want</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00403000</span>
</span></code></pre>
<p><em>Important to note</em> that <strong>array</strong> is at address <code>0x402004</code>, in the <code>.bss</code> section, so its value represents another memory address <code>0x403000</code> which is where the first array element should start in the heap.</p>
<p>Now, when we make the next syscall to allocate 3 bytes in the heap, the program break will be modified and we'll be able to manipulate the array since the pointer already points to the correct address.</p>
<p>After the second syscall, we can no longer manipulate <code>array</code> by its value, because now the array value is no longer an actual element, but rather an address to another place in memory.</p>
<p>Here's the program in its current version:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">1</span>   ; <span class="constant numeric actionscript 2">0x403000</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall
	mov [array], rax

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

	mov rbx, [array]

	mov r8, <span class="constant numeric actionscript 2">1</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">2</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">3</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">4</span>
	<span class="support function actionscript 2">call</span> .append
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .done

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
</span></code></pre>
<p>Explaining each block:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov rdi, <span class="constant numeric actionscript 2">0</span>
mov rax, SYS_brk
syscall
mov [array], rax
</span></code></pre>
<ul>
<li>fetches the current program break and stores the address in the <code>array</code> pointer</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov rdi, rax
<span class="support function actionscript 2">add</span> rdi, CAPACITY
mov rax, SYS_brk
syscall
</span></code></pre>
<ul>
<li>modifies the current program break, incrementing 3 bytes which is the initial array capacity in the heap</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; assign to the register the memory address that the
; <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>array<span class="punctuation definition string end actionscript 2">&quot;</span></span> pointer is pointing to
mov rbx, [array]
</span></code></pre>
<ul>
<li>stores the pointer's memory address in register RBX. This is necessary because we don't want to do arithmetic directly on the pointer in the <code>.bss</code> section, but rather through a register that allows it</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov r8, <span class="constant numeric actionscript 2">1</span>
<span class="support function actionscript 2">call</span> .append
</span></code></pre>
<ul>
<li>since now RDI was used as argument in the brk syscall, it's not convenient to use this register anymore to represent the element to be added to the array, so we switch to register R8</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .done

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b    ; indirect<span class="keyword operator symbolic actionscript 2">-</span><span class="support function actionscript 2">mode</span> addressing
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
</span></code></pre>
<p>Now the <code>.append</code> routine has been modified so that heap array manipulation is through register RBX. We also can't use register RAX anymore to represent the pointer because the brk syscall also used it as return for the program break; in this case we switch to RSI (which has SIL as its lower 8-bit representation).</p>
<p>Running with gdb, we can verify that elements are being added at address <code>0x403000</code> which is in the heap, through the pointer that was stored in register RBX:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Array points to address 0x403000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00403000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> At that address, we have the added elements. Yay!</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       0x00030201</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> And the &quot;index&quot; pointer correctly representing the end of the array in the heap</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x00000003</span>
</span></code></pre>
<p>At this point, the program has the same behavior as the previous example with static array in <code>.bss</code>, not allowing adding more elements when the array reaches its limit.</p>
<p>Let's change this by resizing the array and allowing new elements to be added.</p>
<h3 id="resize-with-brk">Resize with brk</h3>
<p>Next, we start the steps so that array resizing is done when <strong>it reaches capacity limit</strong>. We start by changing the <code>.append</code> routine:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .<span class="support function actionscript 2">resize</span>

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
.<span class="support function actionscript 2">resize</span><span class="keyword operator symbolic actionscript 2">:</span>
	...
</span></code></pre>
<p>Instead of jumping to <code>.done</code> when the array is full, we jump to another subroutine called <code>.resize</code>, which should make the brk syscall again, thus modifying the <strong>program break</strong> in a new memory area, obeying the initial array capacity:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .<span class="support function actionscript 2">resize</span>

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
.<span class="support function actionscript 2">resize</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall

	mov rdi, rax            ; RDI now represents the current <span class="keyword control actionscript 2">break</span>
	<span class="support function actionscript 2">add</span> rdi, CAPACITY       ; <span class="support function actionscript 2">add</span> <span class="constant numeric actionscript 2">3</span> bytes, becoming <span class="constant numeric actionscript 2">0x403006</span>
	mov rax, SYS_brk
	syscall
	jmp .append
</span></code></pre>
<ul>
<li>
<p>the first resize syscall brings the current break, in this case we already know it's <code>0x403003</code>, which was allocated at the beginning of the program for the array</p>
</li>
<li>
<p>the second resize syscall modifies the current break, thus allocating 3 more bytes in the heap</p>
</li>
<li>
<p>at the end of resize, instead of returning the function, we'll go back to the beginning of <code>.append</code> and execute the necessary logic to add the element to the array</p>
</li>
</ul>
<p>This way, we can manipulate this new memory area to add more elements to the array, thus dynamically modifying its capacity.</p>
<p>If we run the program exactly like this, we'll face a problem, because:</p>
<ul>
<li>
<p>every time resize is done, it jumps to the beginning of the routine</p>
</li>
<li>
<p>the array size (pointer) is checked against the initial capacity, which in this case is 3. Since the pointer reached value 3, it will enter resize again characterizing an infinite loop with infinite resize until memory runs out</p>
</li>
</ul>
<p>To solve this, we need to compare the pointer with the current capacity (modified), and therefore we'll add a value in the <code>.data</code> section representing the current capacity:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>
currentCapacity<span class="keyword operator symbolic actionscript 2">:</span> db CAPACITY ; starts <span class="support function actionscript 2">with</span> <span class="constant numeric actionscript 2">3</span>
</span></code></pre>
<p>In the <code>.append</code> routine, we'll make the comparison with <code>currentCapacity</code>, which will be modified with each resize, instead of with <code>CAPACITY</code>, which will remain fixed with the initial value throughout the program.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.append<span class="keyword operator symbolic actionscript 2">:</span>
	mov r9, [currentCapacity]
	cmp byte [pointer], r9b     ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .<span class="support function actionscript 2">resize</span>
...
</span></code></pre>
<p>And, after resizing before going back to <code>.append</code>, we'll increment the initial capacity to the current capacity:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">resize</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

	mov r10, currentCapacity
	<span class="support function actionscript 2">add</span> byte [r10], CAPACITY
	jmp .append
</span></code></pre>
<p>Running the program, we can see that element 4 was successfully added to the array after resizing:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       0x04030201</span>
</span></code></pre>
<p>And if we add more and more elements?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">...
	mov r8, <span class="constant numeric actionscript 2">4</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">5</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">6</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">7</span>
	<span class="support function actionscript 2">call</span> .append
...
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> We can see that currentCapacity is 9, meaning there were</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 2 resizes. Our array can now accommodate up to 9 elements,</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> so when adding the tenth element, one more resize would be done.</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">currentCapacity</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402001</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>currentCapacity<span class="keyword operator assignment redirection shell">&gt;</span>:     0x09</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Fetching the first 9 hexabytes at the array address in the heap</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/9xb  0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       0x01    0x02    0x03    0x04    0x05    0x06    0x07    0x00</span>
<span class="meta function-call shell"><span class="variable function shell">0x403008:</span></span><span class="meta function-call arguments shell">       0x00</span>
</span></code></pre>
<p><em>How cool is that?</em></p>
<hr />
<h2 id="the-final-program">The final program</h2>
<p>Here's the final program, with an array of initial capacity of 3 elements in the heap that can be resized using the <code>brk</code> syscall, as more elements are added to the array:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>
currentCapacity<span class="keyword operator symbolic actionscript 2">:</span> db CAPACITY ; initial capacity is <span class="constant numeric actionscript 2">3</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall
	mov [array], rax

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

	mov rbx, [array]

	mov r8, <span class="constant numeric actionscript 2">1</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">2</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">3</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">4</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">5</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">6</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">7</span>
	<span class="support function actionscript 2">call</span> .append
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
.append<span class="keyword operator symbolic actionscript 2">:</span>
	mov r9, [currentCapacity]
	cmp byte [pointer], r9b ; <span class="support function actionscript 2">check</span> <span class="keyword control actionscript 2">if</span> array is full
	je .<span class="support function actionscript 2">resize</span>

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
.<span class="support function actionscript 2">resize</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

	mov r10, currentCapacity
	<span class="support function actionscript 2">add</span> byte [r10], CAPACITY
	jmp .append
</span></code></pre>
<hr />
<h2 id="conclusion">Conclusion</h2>
<p>In this article, we showed the implementation of an array in x86 Assembly, covering important concepts like memory layout, register manipulation, and dynamic memory allocation with <code>brk</code>.</p>
<p>This article is the foundation for future articles about data structures, where I intend to write about implementing queues and later other data structures.</p>
<hr />
<h2 id="references">References</h2>
<ul>
<li>
<p><a href="https://man7.org/linux/man-pages/man2/brk.2.html">brk syscall</a></p>
</li>
<li>
<p><a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-i-introducao-14p5">x86 Assembly series</a></p>
</li>
</ul>
]]></description>
<pubDate>2025-10-22</pubDate>
</item>
<item>
<title>You don't need Kafka: Building a message queue with only two UNIX signals</title>
<link>https://leandronsp.com/articles/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals.html</link>
<guid>https://leandronsp.com/articles/you-dont-need-kafka-building-a-message-queue-with-only-two-unix-signals.html</guid>
<description><![CDATA[<p>Have you ever asked yourself what if we could replace any message broker with a very simple one using only two UNIX signals? Well, I'm not surprised if you didn't. But I did. And I want to share my journey of how I achieved it.</p>
<p>If you want to learn about UNIX signals, binary operations the easy way, how a message broker works under the hood, and a bit of Ruby, this post is for you.</p>
<p>And if you came here just because of the clickbait title, I apologize and invite you to keep reading. It'll be fun, I promise.</p>
<p><img src="/uploads/3491.png" alt="image" /></p>
<h2 id="its-all-about-unix">It's all about UNIX</h2>
<p>A few days ago, I saw some discussion on the internet about how we could send messages between processes. Many people think of sockets, which are the most common way to send messages, even allowing communication across different machines and networks. Some don't even realize that pipes are another way to send messages between processes:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> echo <span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>hello<span class="punctuation definition string end shell">&#39;</span></span></span> <span class="keyword operator logical pipe shell">|</span> <span class="meta function-call shell"><span class="variable function shell">base64</span></span>
<span class="meta function-call shell"><span class="variable function shell">aGVsbG8K</span></span>
</span></code></pre>
<p>Here's what's happening:</p>
<ul>
<li>
<p>The process <code>echo</code> is started with the content "hello"</p>
</li>
<li>
<p><code>echo</code> is a program that prints the message to <em>STDOUT</em></p>
</li>
<li>
<p>Through the pipe, the content in <em>STDOUT</em> is <strong>sent</strong> directly to the <em>STDIN</em> of the <code>base64</code> process</p>
</li>
<li>
<p>The <code>base64</code> process encodes its input to Base64 and then puts the result in <em>STDOUT</em></p>
</li>
</ul>
<p>Note the word "send". Yes, anonymous pipes are a form of <strong>IPC (Inter-process communication).</strong> Other forms of IPC in UNIX include:</p>
<ul>
<li>
<p>named pipes (mkfifo)</p>
</li>
<li>
<p>sockets</p>
</li>
<li>
<p>regular files</p>
</li>
<li>
<p>or even a simple <strong>signal</strong></p>
</li>
</ul>
<h2 id="unix-signals">UNIX signals</h2>
<p>According to <a href="url">Wikipedia</a>:</p>
<blockquote>
<p>A UNIX signal is a standardized message sent to a program to trigger specific behaviour, such as quitting or error handling</p>
</blockquote>
<p>There are many signals we can send to a process, including:</p>
<ul>
<li>
<p>SIGTERM - sends a notification to the process to terminate. It can be "trapped," which means the process can do some cleanup work before termination, like releasing OS resources and closing file descriptors</p>
</li>
<li>
<p>SIGKILL - sends a termination signal that cannot be trapped or ignored, forcing immediate termination</p>
</li>
<li>
<p>SIGINT - the interrupt signal, typically sent when you press <code>Ctrl+C</code> in the terminal. It can be trapped, allowing the process to perform cleanup before exiting gracefully</p>
</li>
<li>
<p>SIGHUP - the hangup signal, originally sent when a terminal connection was lost. Modern applications often use it to reload configuration files without restarting the process</p>
</li>
<li>
<p>SIGQUIT - similar to SIGINT but also generates a core dump for debugging</p>
</li>
<li>
<p>SIGSTOP - pauses (suspends) a process. Cannot be trapped or ignored</p>
</li>
<li>
<p>SIGCONT - resumes a process that was paused by <em>SIGSTOP</em></p>
</li>
<li>
<p>SIGCHLD - sent to a parent process when a child process terminates or stops</p>
</li>
<li>
<p><strong>SIGUSR1</strong> and <strong>SIGUSR2</strong> - user-defined signals that applications can use for custom purposes</p>
</li>
</ul>
<h2 id="sending-messages-using--signals">Sending messages using  signals</h2>
<p>Okay, we know that signals are a primitive form of IPC. UNIX-like systems provide a syscall called <code>kill</code> that sends signals to processes. Historically, this syscall was created solely to terminate processes. But over time, they needed to accommodate other types of signals, so they reused the same syscall for different purposes.</p>
<p>For instance, let's create a simple Ruby script <code>sleeper.rb</code> which sleeps for 60 seconds, nothing more:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Process ID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
<span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Sleeping for 60 seconds...<span class="punctuation definition string end ruby">&quot;</span></span>
<span class="support function builtin ruby">sleep</span> <span class="constant numeric ruby">60</span>
</span></code></pre>
<p>After running we see:</p>
<pre><code class="sourceCode language-text"><span class="text plain">Process ID: 55402
Sleeping for 60 seconds...
</span></code></pre>
<p>In another window, we can <strong>send</strong> the <code>SIGTERM</code> signal to the process <code>55402</code> via syscall <code>kill</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> kill<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>SIGTERM</span> 55402</span>
</span></code></pre>
<p>And then, in the script session:</p>
<pre><code class="sourceCode language-text"><span class="text plain">[1]    55402 terminated  ruby sleeper.rb
</span></code></pre><h3 id="signal-traps">Signal traps</h3>
<p>In Ruby, we can also <em>trap</em> a signal using the <code>trap</code> method in Ruby:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Process ID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
<span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Sleeping for 60 seconds...<span class="punctuation definition string end ruby">&quot;</span></span>

<span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGTERM<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="keyword control start-block ruby">do</span> 
  <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Received SIGTERM, exiting gracefully...<span class="punctuation definition string end ruby">&quot;</span></span>
  <span class="support function builtin ruby">exit</span>
<span class="keyword control ruby">end</span>

<span class="support function builtin ruby">sleep</span> <span class="constant numeric ruby">60</span>
</span></code></pre>
<p>Which in turn, after sending the signal, will gracefully:</p>
<pre><code class="sourceCode language-text"><span class="text plain">Process ID: 55536
Sleeping for 60 seconds...
Received SIGTERM, exiting gracefully...
</span></code></pre>
<p>After all, we <em>cannot send messages using signals</em>. They are a primitive way of sending <em>standardized messages</em> which will trigger specific behaviours. At most, we can trap some signals, but nothing more.</p>
<blockquote>
<p>Okay Leandro, but what's the purpose of this article then?</p>
</blockquote>
<p><em>Hold on</em>. That's exactly why I'm here. To prove points by doing useless stuff, like when I <a href="https://leandronsp.com/articles/simulating-oop-in-bash-3mop">simulated OOP in Bash</a> a couple of years ago (it was fun though).</p>
<p>To understand how we can "hack" UNIX signals and send messages between processes, let's first talk a bit about <strong>binary operations</strong>. Yes, those "zeros" and "ones" you were scared of when you saw them for the first time. But they don't bite (🥁 LOL), I promise.</p>
<h2 id="what-is-a-message">What is a message?</h2>
<p>If we model a message as a sequence of characters, we could say that at a high-level, messages are simply <em>strings</em>. But in memory, they are stored as <strong>bytes</strong>.</p>
<p>We know that bytes are made of bits. In computer terms, what's a bit? It's simply an abstraction representing <strong>only two states</strong>:</p>
<ul>
<li>
<p>zero</p>
</li>
<li>
<p>one</p>
</li>
</ul>
<p>That's it. For instance, using <a href="url">ASCII</a>, we know that the letter "h" has the following codes:</p>
<ul>
<li>
<p>104 in decimal</p>
</li>
<li>
<p><code>0x68</code> in hexadecimal</p>
</li>
<li>
<p><code>01101000</code> in binary</p>
</li>
</ul>
<p>Binary-wise, what if we represented each "0" with a specific signal and each "1" with another? We know that some signals such as SIGTERM, SIGINT, and SIGCONT can be trapped, but intercepting them would harm their original purpose.</p>
<p>But thankfully, UNIX provides two user-defined signals that are perfect for our hacking experiment.</p>
<h2 id="sending-sigusr1-and-sigusr2">Sending SIGUSR1 and SIGUSR2</h2>
<p>First things first, let's trap those signals in the code:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Process ID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
<span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Sleeping forever. Send signals to this process to see how it responds.<span class="punctuation definition string end ruby">&quot;</span></span>

<span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="keyword control start-block ruby">do</span> 
  <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Received SIGUSR1 signal<span class="punctuation definition string end ruby">&quot;</span></span>
<span class="keyword control ruby">end</span>

<span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR2<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="keyword control start-block ruby">do</span>
  <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Received SIGUSR2 signal<span class="punctuation definition string end ruby">&quot;</span></span>
<span class="keyword control ruby">end</span>

<span class="support function builtin ruby">sleep</span>
</span></code></pre><pre><code class="sourceCode language-text"><span class="text plain">Process ID: 56172
Sleeping forever. Send signals to this process to see how it responds.
</span></code></pre>
<p>After sending some <code>kill -SIGUSR1 56172</code> and <code>kill -SIGUSR2 56172</code>, we can see that the process prints the following content:</p>
<pre><code class="sourceCode language-text"><span class="text plain">Process ID: 56172
Sleeping forever. Send signals to this process to see how it responds.
Received SIGUSR1 signal
Received SIGUSR2 signal
Received SIGUSR2 signal
Received SIGUSR1 signal
Received SIGUSR1 signal
Received SIGUSR2 signal
</span></code></pre>
<p><strong>Signals don't carry data</strong>. But the example we have is perfect for changing to bits, uh?</p>
<pre><code class="sourceCode language-text"><span class="text plain">Received SIGUSR1 signal # 0
Received SIGUSR2 signal # 1
Received SIGUSR2 signal # 1
Received SIGUSR1 signal # 0
Received SIGUSR2 signal # 1
Received SIGUSR1 signal # 0
Received SIGUSR1 signal # 0
Received SIGUSR1 signal # 0
</span></code></pre>
<p>That's exactly <code>01101000</code>, the binary representation of the letter "h". We're simply <strong>encoding</strong> the letter as a binary representation and sending it via signals</p>
<p>Again, we're <strong>encoding it as a binary</strong> and sending it <strong>via signals</strong>.</p>
<p><em>How cool is that</em>?</p>
<p><img src="/uploads/3299.png" alt="image" /></p>
<h3 id="decoding-the-binary-data">Decoding the binary data</h3>
<p>On the other side, the receiver should be capable of decoding the message and converting it back to the letter "h":</p>
<ul>
<li>
<p>sender <em>encodes</em> the message</p>
</li>
<li>
<p>receiver <em>decodes</em> the message</p>
</li>
</ul>
<p>So, how do we decode <code>01101000</code> (the letter "h" in ASCII)? Let's break it down into a few steps:</p>
<ol>
<li>First, we need to see the 8 bits as individual digits in their respective positions</li>
<li>The rightmost bit is at position 0, whereas the leftmost bit is at position 7. This is how we define the most significant bit (<strong>MSB</strong>, the leftmost) and the least significant bit (<strong>LSB</strong>, the rightmost)</li>
<li>For this example, we perform a <strong>left shift</strong> operation on each bit and then sum all the values, in this case from MSB to LSB (the order doesn't matter much for now): <code>(0 &lt;&lt; 7) + (1 &lt;&lt; 6) + (1 &lt;&lt; 5) + (0 &lt;&lt; 4) + ... + (0 &lt;&lt; 0)</code>:
<em>left shift on <em>zeros</em> will always produce a <em>zero</em></em></li>
</ol>
<ul>
<li>
<p><code>0 &lt;&lt; 7</code> = <code>(2 ** 7) * 0</code> = <code>128 * 0</code> = 0</p>
</li>
<li>
<p><code>1 &lt;&lt; 6</code> = <code>(2 ** 6) * 1</code> = <code>64 * 1</code> = 64</p>
</li>
</ul>
<p>Similarly to the remaining bits:</p>
<ul>
<li>
<p><code>1 &lt;&lt; 5</code> = 32</p>
</li>
<li>
<p><code>0 &lt;&lt; 4</code> = 0</p>
</li>
<li>
<p><code>1 &lt;&lt; 3</code> = 8</p>
</li>
<li>
<p><code>0 &lt;&lt; 2</code> = 0</p>
</li>
<li>
<p><code>0 &lt;&lt; 1</code> = 0</p>
</li>
<li>
<p><code>0 &lt;&lt; 0</code> = 0</p>
</li>
</ul>
<p>So, our sum becomes, from MSB to LSB:</p>
<pre><code class="sourceCode language-text"><span class="text plain">MSB                          LSB
0   1    1    0   1   0   0   0
0 + 64 + 32 + 0 + 8 + 0 + 0 + 0 = 104
</span></code></pre>
<p>104 is exactly the <strong>decimal representation</strong> of the letter "h" in ASCII.</p>
<p><em>How wonderful is that?</em></p>
<h3 id="sending-the-letter-h">Sending the letter "h"</h3>
<p>Now let's convert these operations to Ruby code. We'll write a simple program <code>receiver.rb</code> that receives signals in order from LSB to MSB (positions 0 to 7) and then converts them back to ASCII characters, printing to <code>STDOUT</code>.</p>
<p>Basically, we'll <strong>accumulate</strong> bits and whenever we form a complete byte, we'll decode it to its ASCII representation. The very basic implementation of our <code>accumulate_bit(bit)</code> method would look like as follows:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> start with the LSB
</span><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span>

<span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">accumulate_bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> The left shift operator (&lt;&lt;) is used to 
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> shift the bits of the number to the left.
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> This is equivalent of: (2 ** @position) * bit
</span>  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="punctuation definition group begin ruby">(</span>bit <span class="keyword operator assignment augmented ruby">&lt;&lt;</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span><span class="punctuation definition group end ruby">)</span>
  <span class="keyword control pseudo-method ruby">return</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword control ruby">if</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator comparison ruby">==</span> <span class="constant numeric ruby">7</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> stop accumulating after 8 bits (byte)
</span>
  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="constant numeric ruby">1</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> move to the next bit position: 0 becomes 1, 1 becomes 2, etc.
</span><span class="keyword control ruby">end</span>

<span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Letter &quot;h&quot; in binary is 01101000
</span><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> But we&#39;ll send from the LSB to the MSB
</span><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>
</span><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> 0110 1000 (MSB -&gt; LSB) becomes 0001 0110 (LSB -&gt; MSB)
</span><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> The order doesn&#39;t matter that much, it&#39;ll depend on 
</span><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> the receiver&#39;s implementation.
</span>accumulate_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span>
accumulate_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span>
accumulate_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span>
accumulate_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">1</span><span class="punctuation definition group end ruby">)</span>
accumulate_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span>
accumulate_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">1</span><span class="punctuation definition group end ruby">)</span>
accumulate_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">1</span><span class="punctuation definition group end ruby">)</span>
accumulate_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span>

<span class="support function builtin ruby">puts</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> should print 104, which is the ASCII code for &quot;h&quot;
</span></span></code></pre>
<p><em>Pay attention to this code. It's very important and builds the foundation for the next steps. If you didn't get it, go back and read it again. Try it yourself in the terminal or using your preferred programming language.</em></p>
<p>Now, how to convert the decimal <code>104</code> to the ASCII character representation? Luckily, Ruby provides a method called <code>chr</code> which does the job:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby">irb<span class="keyword operator comparison ruby">&gt;</span> <span class="support function builtin ruby">puts</span> <span class="constant numeric ruby">104</span><span class="punctuation accessor ruby">.</span>chr
<span class="punctuation separator key-value ruby">=&gt;</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>h<span class="punctuation definition string end ruby">&quot;</span></span>
</span></code></pre>
<p>We could do the same job for the rest of the word "hello", for instance. According to the <a href="https://www.ascii-code.com/">ASCII table</a>, it should be the following:</p>
<ul>
<li>
<p><code>e</code> in decimal is <code>101</code></p>
</li>
<li>
<p><code>l</code> in decimal is <code>108</code></p>
</li>
<li>
<p><code>o</code> in decimal is <code>111</code></p>
</li>
</ul>
<p>Let's check if Ruby knows that:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="constant numeric ruby">104</span><span class="punctuation accessor ruby">.</span>chr    <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> &quot;h&quot;
</span><span class="constant numeric ruby">101</span><span class="punctuation accessor ruby">.</span>chr    <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> &quot;e&quot;
</span><span class="constant numeric ruby">108</span><span class="punctuation accessor ruby">.</span>chr    <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> &quot;l&quot;
</span><span class="constant numeric ruby">111</span><span class="punctuation accessor ruby">.</span>chr    <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> &quot;o&quot;
</span></span></code></pre>
<p>We can even "decode" the word to the decimal representation in ASCII:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby">irb<span class="keyword operator comparison ruby">&gt;</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>hello<span class="punctuation definition string end ruby">&quot;</span></span><span class="punctuation accessor ruby">.</span>bytes
<span class="punctuation separator key-value ruby">=&gt;</span> <span class="punctuation section array ruby">[</span><span class="constant numeric ruby">104</span><span class="punctuation separator ruby">,</span> <span class="constant numeric ruby">101</span><span class="punctuation separator ruby">,</span> <span class="constant numeric ruby">108</span><span class="punctuation separator ruby">,</span> <span class="constant numeric ruby">108</span><span class="punctuation separator ruby">,</span> <span class="constant numeric ruby">111</span><span class="punctuation section array ruby">]</span>
</span></code></pre>
<p>Now, time to finish our receiver implementation to properly print the letter "h":</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> start with the LSB
</span><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span>

<span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> decode_signal<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>
<span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR2<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> decode_signal<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">1</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>

<span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">decode_signal</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  accumulate_bit<span class="punctuation definition group begin ruby">(</span>bit<span class="punctuation definition group end ruby">)</span>
  <span class="keyword control pseudo-method ruby">return</span> <span class="keyword control ruby">unless</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator comparison ruby">==</span> <span class="constant numeric ruby">8</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> if not yet accumulated a byte, keep accumulating
</span>
  <span class="support function builtin ruby">print</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Received byte: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span><span class="punctuation section embedded ruby">}</span></span> (<span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span><span class="punctuation accessor ruby">.</span>chr<span class="punctuation section embedded ruby">}</span></span>)<span class="constant character escape ruby">\n</span><span class="punctuation definition string end ruby">&quot;</span></span>

  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> reset the accumulator
</span>  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> reset position for the next byte
</span><span class="keyword control ruby">end</span>

<span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">accumulate_bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> The left shift operator (&lt;&lt;) is used to 
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> shift the bits of the number to the left.
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> This is equivalent of: (2 ** @position) * bit
</span>  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="punctuation definition group begin ruby">(</span>bit <span class="keyword operator assignment augmented ruby">&lt;&lt;</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span><span class="punctuation definition group end ruby">)</span>
  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="constant numeric ruby">1</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> move to the next bit position: 0 becomes 1, 1 becomes 2, etc.
</span><span class="keyword control ruby">end</span>

<span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Process ID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
<span class="support function builtin ruby">sleep</span>
</span></code></pre>
<p><em>Read that code and its comments. It's very important. Do not continue reading until you really get what's happening here.</em></p>
<ul>
<li>
<p>Whenever we get <code>SIGUSR1</code>, we accumulate the bit <code>0</code></p>
</li>
<li>
<p>When getting <code>SIGUSR2</code>, accumulate then the bit <code>1</code></p>
</li>
<li>
<p>When accumulator reaches  the position<code>8</code>, it means we have a byte. At this moment we should print the ASCII representation using the <code>.chr</code> we seen earlier. Then, reset bit position and accumulator</p>
</li>
</ul>
<p>Let's see our receiver in action! Start the receiver in one terminal:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ruby receiver.rb</span>
<span class="meta function-call shell"><span class="variable function shell">Process</span></span><span class="meta function-call arguments shell"> ID: 58219</span>
</span></code></pre>
<p>Great! Now the receiver is listening for signals. In another terminal, let's manually send signals
to form the letter "h" (which is <code>01101000</code> in binary, remember?):</p>
<pre><code class="sourceCode language-text"><span class="text plain">  # Sending from LSB to MSB: 0, 0, 0, 1, 0, 1, 1, 0
  $ kill -SIGUSR1 58219  # 0
  $ kill -SIGUSR1 58219  # 0
  $ kill -SIGUSR1 58219  # 0
  $ kill -SIGUSR2 58219  # 1
  $ kill -SIGUSR1 58219  # 0
  $ kill -SIGUSR2 58219  # 1
  $ kill -SIGUSR2 58219  # 1
  $ kill -SIGUSR1 58219  # 0
</span></code></pre>
<p>And in the receiver terminal, we should see:</p>
<pre><code class="sourceCode language-text"><span class="text plain">Received byte: 104 (h)
</span></code></pre>
<p><em>How amazing is that?</em> We just sent the letter "h" using only two UNIX signals!</p>
<p>But wait. Manually sending 8 signals for each character? That's tedious and error-prone. What if we wanted to send the word "hello"? That's 5 characters × 8 bits = 40 signals to send manually. No way.</p>
<p><em>We need a sender.</em></p>
<h3 id="building-the-sender">Building the sender</h3>
<p>The sender's job is the opposite of the receiver: it should encode a message (string) into bits and send them as signals to the receiver process.</p>
<p>Let's think about what we need:</p>
<ol>
<li>Take a message as input (like "hello")</li>
<li>Convert each character to its byte representation</li>
<li>Extract the 8 bits from each byte</li>
<li>Send <code>SIGUSR1</code> for bit 0, <code>SIGUSR2</code> for bit 1</li>
<li>Repeat for all characters</li>
</ol>
<p>The tricky part here is the step 3: <strong>how do we extract individual bits from a byte?</strong> To extract the bit at position <code>i</code>, we can use the following formula:</p>
<pre><code class="sourceCode language-text"><span class="text plain">bit = (byte &gt;&gt; i) &amp; 1
</span></code></pre>
<p>Let me break this down:</p>
<ul>
<li>
<p><code>byte &gt;&gt; i</code> performs a <em>right shift</em> by <code>i</code> positions</p>
</li>
<li>
<p><code>&amp; 1</code> is a bitwise <code>AND</code> operation that extracts only the <em>rightmost</em> bit</p>
</li>
</ul>
<p>For the letter "h" (<code>01101000</code> in binary, <code>104</code> in decimal):</p>
<p><strong>Position 0 (LSB):</strong></p>
<ul>
<li>
<p><code>(104 &gt;&gt; 0)</code> = <code>104 / (2 ** 0)</code> = <code>104 / 1</code> = 104</p>
</li>
<li>
<p><code>01101000</code> &gt;&gt; 0 = <code>01101000</code></p>
</li>
<li>
<p><code>01101000</code> &amp; <code>00000001</code> = 0 (<em>one</em> AND <em>zero</em> is <em>zero</em>)</p>
</li>
</ul>
<p><strong>Position 1:</strong></p>
<ul>
<li>
<p><code>(104 &gt;&gt; 1)</code> = <code>104 / (2 ** 1)</code> = <code>104 / 2</code> = 52</p>
</li>
<li>
<p><code>01101000</code> &gt;&gt; 1 = <code>00110100</code></p>
</li>
<li>
<p><code>00110100</code> &amp; <code>00000001</code> = 0</p>
</li>
</ul>
<p><strong>Position 2:</strong></p>
<ul>
<li>
<p><code>(104 &gt;&gt; 2)</code> = <code>104 / (2 ** 2)</code> = <code>104 / 4</code> = 26</p>
</li>
<li>
<p><code>01101000</code> &gt;&gt; 2 = <code>00011010</code></p>
</li>
<li>
<p><code>00011010</code> &amp; <code>00000001</code> = 0</p>
</li>
</ul>
<p><strong>Position 3:</strong></p>
<ul>
<li>
<p><code>(104 &gt;&gt; 3)</code> = <code>104 / (2 ** 3)</code> = <code>104 / 8</code> = 13</p>
</li>
<li>
<p><code>01101000</code> &gt;&gt; 3 = <code>00001101</code></p>
</li>
<li>
<p><code>00001101</code> &amp; <code>00000001</code> = 1 (<em>one</em> AND <em>one</em> equals <em>one</em>)</p>
</li>
</ul>
<p>And so on for positions 4, 5, 6, and 7. This gives us: <code>0, 0, 0, 1, 0, 1, 1, 0</code> — exactly the bits we need from LSB to MSB!</p>
<ul>
<li>
<p><code>(104 &gt;&gt; 0) &amp; 1</code> = <code>104 &amp; 1</code> = 0</p>
</li>
<li>
<p><code>(104 &gt;&gt; 1) &amp; 1</code> = <code>52 &amp; 1</code> = 0</p>
</li>
<li>
<p><code>(104 &gt;&gt; 2) &amp; 1</code> = <code>26 &amp; 1</code> = 0</p>
</li>
<li>
<p><code>(104 &gt;&gt; 3) &amp; 1</code> = <code>13 &amp; 1</code> = 1</p>
</li>
<li>
<p><code>(104 &gt;&gt; 4) &amp; 1</code> = <code>6 &amp; 1</code> = 0</p>
</li>
<li>
<p><code>(104 &gt;&gt; 5) &amp; 1</code> = <code>3 &amp; 1</code> = 1</p>
</li>
<li>
<p><code>(104 &gt;&gt; 6) &amp; 1</code> = <code>1 &amp; 1</code> = 1</p>
</li>
<li>
<p><code>(104 &gt;&gt; 7) &amp; 1</code> = <code>0 &amp; 1</code> = 0</p>
</li>
</ul>
<blockquote>
<p>Pay close attention to this technique. It's a fundamental operation in low-level programming.</p>
</blockquote>
<p>So now time to build the <code>sender.rb</code> which is pretty simple:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby">receiver_pid <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">ARGV</span><span class="punctuation section array ruby">[</span><span class="constant numeric ruby">0</span><span class="punctuation section array ruby">]</span><span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">to_i</span>
message <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">ARGV</span><span class="punctuation section array ruby">[</span><span class="constant numeric ruby">1</span><span class="keyword operator ruby">..</span><span class="keyword operator arithmetic ruby">-</span><span class="constant numeric ruby">1</span><span class="punctuation section array ruby">]</span><span class="punctuation accessor ruby">.</span>join<span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span> <span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span>

<span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">encode_byte</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">byte</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="constant numeric ruby">8</span><span class="punctuation accessor ruby">.</span>times<span class="punctuation accessor ruby">.</span>map <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">i</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
    <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Extract each bit from the byte, starting from the LSB
</span>    <span class="punctuation definition group begin ruby">(</span>byte <span class="keyword operator other ruby">&gt;&gt;</span> i<span class="punctuation definition group end ruby">)</span> <span class="keyword operator arithmetic ruby">&amp;</span> <span class="constant numeric ruby">1</span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>

message<span class="punctuation accessor ruby">.</span>bytes<span class="punctuation accessor ruby">.</span>each <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">byte</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
  encode_byte<span class="punctuation definition group begin ruby">(</span>byte<span class="punctuation definition group end ruby">)</span><span class="punctuation accessor ruby">.</span>each <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">bit</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
    signal <span class="keyword operator assignment ruby">=</span> bit <span class="keyword operator comparison ruby">==</span> <span class="constant numeric ruby">0</span> <span class="keyword operator conditional ruby">?</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span> <span class="keyword operator conditional ruby">:</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR2<span class="punctuation definition string end ruby">&#39;</span></span>
    <span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>kill<span class="punctuation definition group begin ruby">(</span>signal<span class="punctuation separator ruby">,</span> receiver_pid<span class="punctuation definition group end ruby">)</span>
    <span class="support function builtin ruby">sleep</span> <span class="constant numeric ruby">0.001</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Delay to allow the receiver to process the signal
</span>  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>
</span></code></pre>
<p>For each byte (8-bit structure) we extract the bit performing the <em>right shift</em> + <em>AND</em> oprerations. The result is the extracted bit.</p>
<p>In the receiver window:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ruby receiver.rb</span>
<span class="meta function-call shell"><span class="variable function shell">Process</span></span><span class="meta function-call arguments shell"> ID: 68968</span>
</span></code></pre>
<p>And in the sender window:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ruby sender.rb 68968 h</span>
</span></code></pre>
<p>The receiver will print:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ruby receiver.rb</span>
<span class="meta function-call shell"><span class="variable function shell">Process</span></span><span class="meta function-call arguments shell"> ID: 68968</span>
<span class="meta function-call shell"><span class="variable function shell">Received</span></span><span class="meta function-call arguments shell"> byte: 104 (h</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
</span></code></pre>
<p><em>Processes sending messages with only two signals!</em> How wonderful is that?</p>
<h3 id="sending-the-hello-message">Sending the "hello" message</h3>
<p>Now, sending the hello message is super easy. The sender is already able to send not only a letter but any message using signals:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ruby sender.rb 68968 hello</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> And the receiver:</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">Received</span></span><span class="meta function-call arguments shell"> byte: 104 (h</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">Received</span></span><span class="meta function-call arguments shell"> byte: 101 (e</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">Received</span></span><span class="meta function-call arguments shell"> byte: 108 (l</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">Received</span></span><span class="meta function-call arguments shell"> byte: 108 (l</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">Received</span></span><span class="meta function-call arguments shell"> byte: 111 (o</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
</span></code></pre>
<p>Just change the <code>receiver</code> implementation a little bit:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">decode_signal</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  accumulate_bit<span class="punctuation definition group begin ruby">(</span>bit<span class="punctuation definition group end ruby">)</span>
  <span class="keyword control pseudo-method ruby">return</span> <span class="keyword control ruby">unless</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator comparison ruby">==</span> <span class="constant numeric ruby">8</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> if not yet accumulated a byte, keep accumulating
</span>
  <span class="support function builtin ruby">print</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span><span class="punctuation accessor ruby">.</span>chr <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> print the byte as a character
</span>
  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> reset the accumulator
</span>  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> reset position for the next byte
</span><span class="keyword control ruby">end</span>
</span></code></pre>
<p>And then:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ruby sender.rb 96875 Hello</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> In the receiver&#39;s terminal</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">Process</span></span><span class="meta function-call arguments shell"> ID: 96875</span>
<span class="meta function-call shell"><span class="variable function shell">Hello</span></span>
</span></code></pre>
<p>However, if we send the message again, the receiver will print everything in the same line:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby">$ ruby sender<span class="punctuation accessor ruby">.</span>rb <span class="constant numeric ruby">96875</span> <span class="variable other constant ruby">Hello</span>
$ ruby sender<span class="punctuation accessor ruby">.</span>rb <span class="constant numeric ruby">96875</span> <span class="variable other constant ruby">Hello</span>

<span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> In the receiver&#39;s terminal
</span><span class="variable other constant ruby">Process</span> <span class="constant other symbol ruby">ID<span class="punctuation definition constant ruby">:</span></span> <span class="constant numeric ruby">96875</span>
<span class="variable other constant ruby">HelloHello</span>
</span></code></pre>
<p>It's obvious: the receiver doesn't know where the sender finished the message, so it's impossible to know where we should stop one message and print the next one on a new line with <code>\n</code>.</p>
<p>We should then determine how the sender indicates the end of the message. How about being it all <em>zeroes</em> (<code>0000 0000</code>)?</p>
<ul>
<li>
<p>We send the message: first 5 bytes representing the "hello" message</p>
</li>
<li>
<p>Then we send a "NULL terminator", just one byte <em>0</em> (<code>0000 0000</code>)</p>
</li>
</ul>
<pre><code class="sourceCode language-text"><span class="text plain">0110 1000 # h
0110 0101 # e
0110 1000 # l
0110 1000 # l
0110 1111 # o
0000 0000 # NULL
</span></code></pre>
<p>Hence, when the <em>receiver</em> gets a NULL terminator, it will print a line feed <code>\n</code>. Let's change the <code>sender.rb</code> first:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby">receiver_pid <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">ARGV</span><span class="punctuation section array ruby">[</span><span class="constant numeric ruby">0</span><span class="punctuation section array ruby">]</span><span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">to_i</span>
message <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">ARGV</span><span class="punctuation section array ruby">[</span><span class="constant numeric ruby">1</span><span class="keyword operator ruby">..</span><span class="keyword operator arithmetic ruby">-</span><span class="constant numeric ruby">1</span><span class="punctuation section array ruby">]</span><span class="punctuation accessor ruby">.</span>join<span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span> <span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span>

<span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">encode_byte</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">byte</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="constant numeric ruby">8</span><span class="punctuation accessor ruby">.</span>times<span class="punctuation accessor ruby">.</span>map <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">i</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
    <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Extract each bit from the byte, starting from the LSB
</span>    <span class="punctuation definition group begin ruby">(</span>byte <span class="keyword operator other ruby">&gt;&gt;</span> i<span class="punctuation definition group end ruby">)</span> <span class="keyword operator arithmetic ruby">&amp;</span> <span class="constant numeric ruby">1</span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>

message<span class="punctuation accessor ruby">.</span>bytes<span class="punctuation accessor ruby">.</span>each <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">byte</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
  encode_byte<span class="punctuation definition group begin ruby">(</span>byte<span class="punctuation definition group end ruby">)</span><span class="punctuation accessor ruby">.</span>each <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">bit</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
    signal <span class="keyword operator assignment ruby">=</span> bit <span class="keyword operator comparison ruby">==</span> <span class="constant numeric ruby">0</span> <span class="keyword operator conditional ruby">?</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span> <span class="keyword operator conditional ruby">:</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR2<span class="punctuation definition string end ruby">&#39;</span></span>
    <span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>kill<span class="punctuation definition group begin ruby">(</span>signal<span class="punctuation separator ruby">,</span> receiver_pid<span class="punctuation definition group end ruby">)</span>
    <span class="support function builtin ruby">sleep</span> <span class="constant numeric ruby">0.001</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Delay to allow the receiver to process the signal
</span>  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>

<span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Send NULL terminator (0000 0000)
</span><span class="constant numeric ruby">8</span><span class="punctuation accessor ruby">.</span>times <span class="keyword control start-block ruby">do</span>
  <span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>kill<span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation separator ruby">,</span> receiver_pid<span class="punctuation definition group end ruby">)</span>
  <span class="support function builtin ruby">sleep</span> <span class="constant numeric ruby">0.001</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Delay to allow the receiver to process the signal
</span><span class="keyword control ruby">end</span>

<span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Message sent to receiver (PID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span>receiver_pid<span class="punctuation section embedded ruby">}</span></span>)<span class="punctuation definition string end ruby">&quot;</span></span>
</span></code></pre>
<p>Then, the <code>receiver.rb</code>:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> start with the LSB
</span><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span>

<span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> decode_signal<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>
<span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR2<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> decode_signal<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">1</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>

<span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">decode_signal</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  accumulate_bit<span class="punctuation definition group begin ruby">(</span>bit<span class="punctuation definition group end ruby">)</span>
  <span class="keyword control pseudo-method ruby">return</span> <span class="keyword control ruby">unless</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator comparison ruby">==</span> <span class="constant numeric ruby">8</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> if not yet accumulated a byte, keep accumulating
</span>
  <span class="keyword control ruby">if</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span><span class="punctuation accessor ruby">.</span>zero? <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> NULL terminator received
</span>    <span class="support function builtin ruby">print</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span><span class="constant character escape ruby">\n</span><span class="punctuation definition string end ruby">&quot;</span></span>
  <span class="keyword control ruby">else</span>
    <span class="support function builtin ruby">print</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span><span class="punctuation accessor ruby">.</span>chr <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> print the byte as a character
</span>  <span class="keyword control ruby">end</span>

  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> reset the accumulator
</span>  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> reset position for the next byte
</span><span class="keyword control ruby">end</span>

<span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">accumulate_bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> The left shift operator (&lt;&lt;) is used to 
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> shift the bits of the number to the left.
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>
</span>  <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> This is equivalent of: (2 ** @position) * bit
</span>  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="punctuation definition group begin ruby">(</span>bit <span class="keyword operator assignment augmented ruby">&lt;&lt;</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span><span class="punctuation definition group end ruby">)</span>
  <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="constant numeric ruby">1</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> move to the next bit position: 0 becomes 1, 1 becomes 2, etc.
</span><span class="keyword control ruby">end</span>

<span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Process ID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
<span class="support function builtin ruby">sleep</span>
</span></code></pre>
<p>Output:</p>
<pre><code class="sourceCode language-text"><span class="text plain">$ ruby sender.rb 96875 Hello, World!
$ ruby sender.rb 96875 You&#39;re welcome
$ ruby sender.rb 96875 How are you?

# Receiver
Process ID: 97176
Hello, World!
You&#39;re welcome
How are you?
</span></code></pre>
<blockquote>
<p>OMG Leandro! That's amazing!</p>
</blockquote>
<p><em>Amazing, right?</em> We just built an entire communication system between two processes using one of the most primitive methods available: <strong>UNIX signals.</strong></p>
<p>The sky's the limit now! Why not build a <em>full-fledged message broker</em> using this crazy technique?</p>
<h2 id="a-modest-message-broker-using-unix-signals">A modest message broker using UNIX signals</h2>
<p>We'll break down the development into three components:</p>
<ol>
<li><strong>Broker</strong>: the intermediary that routes messages</li>
<li><strong>Consumer</strong>: processes that receive messages</li>
<li><strong>Producer</strong>: processes that send messages</li>
</ol>
<p><img src="/uploads/3395.png" alt="image" /></p>
<ol>
<li>Let's start with the Broker. It should register itself with the producer, then trap incoming signals, decode them, and enqueue the messages for delivery to consumers via outgoing signals:</li>
</ol>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>!/usr/bin/env ruby
</span>
<span class="meta require ruby"><span class="keyword other special-method ruby">require_relative</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>signal_codec<span class="punctuation definition string end ruby">&#39;</span></span></span>
<span class="meta require ruby"><span class="keyword other special-method ruby">require_relative</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>consumer<span class="punctuation definition string end ruby">&#39;</span></span></span>

<span class="meta class ruby"><span class="keyword control class ruby">class</span></span><span class="meta class ruby"> </span><span class="meta class ruby"><span class="entity name class ruby">Broker</span></span><span class="meta class ruby"> 
  </span><span class="meta constant ruby"><span class="entity name constant ruby">PID</span></span> <span class="keyword operator assignment ruby">=</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>broker.pid<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">freeze</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">initialize</span></span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>codec</span> <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">SignalCodec</span><span class="punctuation accessor ruby">.</span><span class="keyword other special-method ruby">new</span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>queue</span> <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">Queue</span><span class="punctuation accessor ruby">.</span><span class="keyword other special-method ruby">new</span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>consumer_index</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span>
  <span class="keyword control ruby">end</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">start</span></span><span class="meta function ruby"> </span>
    register_broker

    <span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> process_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>
    <span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR2<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> process_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">1</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>
    
    <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Broker PID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
    <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Waiting for messages...<span class="punctuation definition string end ruby">&quot;</span></span>

    distribute_messages

    <span class="support function builtin ruby">sleep</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Keep alive
</span>  <span class="keyword control ruby">end</span> 

  <span class="keyword other special-method ruby">private</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">process_bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>codec</span><span class="punctuation accessor ruby">.</span>accumulate_bit<span class="punctuation definition group begin ruby">(</span>bit<span class="punctuation definition group end ruby">)</span> <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">message</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
      <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>queue</span><span class="punctuation accessor ruby">.</span>push<span class="punctuation definition group begin ruby">(</span>message<span class="punctuation definition group end ruby">)</span> <span class="keyword control ruby">unless</span> message<span class="punctuation accessor ruby">.</span>empty?
    <span class="keyword control ruby">end</span>
  <span class="keyword control ruby">end</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">register_broker</span></span><span class="meta function ruby"> </span>
    <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span>write<span class="punctuation definition group begin ruby">(</span><span class="variable other constant ruby">PID</span><span class="punctuation separator ruby">,</span> <span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid<span class="punctuation definition group end ruby">)</span>
    <span class="support function builtin ruby">at_exit</span> <span class="punctuation section scope ruby">{</span> <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span>delete<span class="punctuation definition group begin ruby">(</span><span class="variable other constant ruby">PID</span><span class="punctuation definition group end ruby">)</span> <span class="keyword control ruby">if</span> <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span>exist?<span class="punctuation definition group begin ruby">(</span><span class="variable other constant ruby">PID</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>
  <span class="keyword control ruby">end</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">distribute_messages</span></span>
    <span class="support class ruby">Thread</span><span class="punctuation accessor ruby">.</span><span class="keyword other special-method ruby">new</span> <span class="keyword control start-block ruby">do</span>
      <span class="keyword other special-method ruby">loop</span> <span class="keyword control start-block ruby">do</span>
        <span class="support function builtin ruby">sleep</span> <span class="constant numeric ruby">0.1</span>

        <span class="keyword control pseudo-method ruby">next</span> <span class="keyword control ruby">if</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>queue</span><span class="punctuation accessor ruby">.</span>empty?

        consumers <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span>exist?<span class="punctuation definition group begin ruby">(</span><span class="support class ruby">Consumer</span><span class="punctuation accessor ruby">::</span>FILE<span class="punctuation definition group end ruby">)</span> <span class="keyword operator conditional ruby">?</span> <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">readlines</span><span class="punctuation definition group begin ruby">(</span><span class="support class ruby">Consumer</span><span class="punctuation accessor ruby">::</span>FILE<span class="punctuation definition group end ruby">)</span><span class="punctuation accessor ruby">.</span>map<span class="punctuation definition group begin ruby">(</span><span class="keyword operator arithmetic ruby">&amp;</span><span class="constant other symbol ruby"><span class="punctuation definition constant ruby">:</span>to_i</span><span class="punctuation definition group end ruby">)</span> <span class="keyword operator conditional ruby">:</span> <span class="punctuation section array ruby">[</span><span class="punctuation section array ruby">]</span>
        <span class="keyword control pseudo-method ruby">next</span> <span class="keyword control ruby">if</span> consumers<span class="punctuation accessor ruby">.</span>empty?

        message <span class="keyword operator assignment ruby">=</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>queue</span><span class="punctuation accessor ruby">.</span>pop<span class="punctuation definition group begin ruby">(</span><span class="constant language ruby">true</span><span class="punctuation definition group end ruby">)</span> <span class="keyword control ruby">rescue</span> <span class="keyword control pseudo-method ruby">next</span>

        consumer_pid <span class="keyword operator assignment ruby">=</span> consumers<span class="punctuation section array ruby">[</span><span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>consumer_index</span> <span class="keyword operator arithmetic ruby">%</span> consumers<span class="punctuation accessor ruby">.</span>size<span class="punctuation section array ruby">]</span>
        <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>consumer_index</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="constant numeric ruby">1</span>

        <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>[SEND] <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span>message<span class="punctuation section embedded ruby">}</span></span> → Consumer <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span>consumer_pid<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>

        <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>codec</span><span class="punctuation accessor ruby">.</span>send_message<span class="punctuation definition group begin ruby">(</span>message<span class="punctuation separator ruby">,</span> consumer_pid<span class="punctuation definition group end ruby">)</span>
      <span class="keyword control ruby">end</span>
    <span class="keyword control ruby">end</span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>

<span class="keyword control ruby">if</span> <span class="variable language ruby">__FILE__</span> <span class="keyword operator comparison ruby">==</span> <span class="variable other readwrite global pre-defined ruby"><span class="punctuation definition variable ruby">$</span>0</span> 
  broker <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">Broker</span><span class="punctuation accessor ruby">.</span><span class="keyword other special-method ruby">new</span>
  broker<span class="punctuation accessor ruby">.</span>start
<span class="keyword control ruby">end</span>
</span></code></pre>
<ul>
<li>
<p>The broker registers itself</p>
</li>
<li>
<p>Traps incoming signals <code>USR1</code> (bit 0) and <code>USR2</code> (bit 1)</p>
</li>
<li>
<p>Enqueues the messages</p>
</li>
<li>
<p>Send messages to consumers using outgoing signals (<code>USR1</code> and <code>USR2</code> too)</p>
</li>
</ul>
<p><em>Note that we're using a module called <code>SignalCodec</code> which will be explained soon. Basically this module contains all core components to encode/decode signals and perform bitwise operations.</em></p>
<ol start="2">
<li>Now the <code>Consumer</code> implementation:</li>
</ol>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>!/usr/bin/env ruby
</span>
<span class="meta require ruby"><span class="keyword other special-method ruby">require_relative</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>signal_codec<span class="punctuation definition string end ruby">&#39;</span></span></span>

<span class="meta class ruby"><span class="keyword control class ruby">class</span></span><span class="meta class ruby"> </span><span class="meta class ruby"><span class="entity name class ruby">Consumer</span></span><span class="meta class ruby">
  </span><span class="meta constant ruby"><span class="entity name constant ruby">FILE</span></span> <span class="keyword operator assignment ruby">=</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>consumers.txt<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">freeze</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">initialize</span></span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>codec</span> <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">SignalCodec</span><span class="punctuation accessor ruby">.</span><span class="keyword other special-method ruby">new</span>
  <span class="keyword control ruby">end</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">start</span></span>
    register_consumer

    <span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> process_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">0</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>
    <span class="support function builtin ruby">trap</span><span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR2<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> process_bit<span class="punctuation definition group begin ruby">(</span><span class="constant numeric ruby">1</span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">}</span>

    <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Consumer PID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
    <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Waiting for messages...<span class="punctuation definition string end ruby">&quot;</span></span>

    <span class="support function builtin ruby">sleep</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Keep alive
</span>  <span class="keyword control ruby">end</span>

  <span class="keyword other special-method ruby">private</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">process_bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>codec</span><span class="punctuation accessor ruby">.</span>accumulate_bit<span class="punctuation definition group begin ruby">(</span>bit<span class="punctuation definition group end ruby">)</span> <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">message</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
      <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>[RECEIVE] <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span>message<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
    <span class="keyword control ruby">end</span>
  <span class="keyword control ruby">end</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">register_consumer</span></span>
    <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">open</span><span class="punctuation definition group begin ruby">(</span><span class="variable other constant ruby">FILE</span><span class="punctuation separator ruby">,</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>a<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span> <span class="punctuation section scope ruby">{</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">f</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span> f<span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">puts</span> <span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid <span class="punctuation section scope ruby">}</span>
    <span class="support function builtin ruby">at_exit</span> <span class="punctuation section scope ruby">{</span> deregister_consumer <span class="punctuation section scope ruby">}</span>
  <span class="keyword control ruby">end</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">deregister_consumer</span></span>
    <span class="keyword control ruby">if</span> <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span>exist?<span class="punctuation definition group begin ruby">(</span><span class="variable other constant ruby">FILE</span><span class="punctuation definition group end ruby">)</span>
      consumers <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">readlines</span><span class="punctuation definition group begin ruby">(</span><span class="variable other constant ruby">FILE</span><span class="punctuation definition group end ruby">)</span><span class="punctuation accessor ruby">.</span>map<span class="punctuation definition group begin ruby">(</span><span class="keyword operator arithmetic ruby">&amp;</span><span class="constant other symbol ruby"><span class="punctuation definition constant ruby">:</span>strip</span><span class="punctuation definition group end ruby">)</span><span class="punctuation accessor ruby">.</span>reject <span class="punctuation section scope ruby">{</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">pid</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span> pid<span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">to_i</span> <span class="keyword operator comparison ruby">==</span> <span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>pid <span class="punctuation section scope ruby">}</span>
      <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span>write<span class="punctuation definition group begin ruby">(</span><span class="variable other constant ruby">FILE</span><span class="punctuation separator ruby">,</span> consumers<span class="punctuation accessor ruby">.</span>join<span class="punctuation definition group begin ruby">(</span><span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span><span class="constant character escape ruby">\n</span><span class="punctuation definition string end ruby">&quot;</span></span><span class="punctuation definition group end ruby">)</span><span class="punctuation definition group end ruby">)</span>
    <span class="keyword control ruby">end</span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>

<span class="keyword control ruby">if</span> <span class="variable language ruby">__FILE__</span> <span class="keyword operator comparison ruby">==</span> <span class="variable other readwrite global pre-defined ruby"><span class="punctuation definition variable ruby">$</span>0</span>
  consumer <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">Consumer</span><span class="punctuation accessor ruby">.</span><span class="keyword other special-method ruby">new</span>
  consumer<span class="punctuation accessor ruby">.</span>start
<span class="keyword control ruby">end</span>
</span></code></pre>
<ul>
<li>
<p>The consumer starts and registers itself with the broker</p>
</li>
<li>
<p>Consumer then traps incoming signals (bit 0 and bit 1)</p>
</li>
<li>
<p>Decodes and prints messages</p>
</li>
</ul>
<ol start="3">
<li>Last but not least, the <code>Producer</code> implementation, which is pretty straightforward:</li>
</ol>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span>!/usr/bin/env ruby
</span>
<span class="meta require ruby"><span class="keyword other special-method ruby">require_relative</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>signal_codec<span class="punctuation definition string end ruby">&#39;</span></span></span>
<span class="meta require ruby"><span class="keyword other special-method ruby">require_relative</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>broker<span class="punctuation definition string end ruby">&#39;</span></span></span>

<span class="keyword control ruby">unless</span> <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span>exist?<span class="punctuation definition group begin ruby">(</span><span class="support class ruby">Broker</span><span class="punctuation accessor ruby">::</span>PID<span class="punctuation definition group end ruby">)</span>
  <span class="support function builtin ruby">abort</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Error: Broker not running (<span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span><span class="support class ruby">Broker</span><span class="punctuation accessor ruby">::</span>PID<span class="punctuation section embedded ruby">}</span></span> not found)<span class="punctuation definition string end ruby">&quot;</span></span>
<span class="keyword control ruby">end</span>

broker_pid <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">File</span><span class="punctuation accessor ruby">.</span>read<span class="punctuation definition group begin ruby">(</span><span class="support class ruby">Broker</span><span class="punctuation accessor ruby">::</span>PID<span class="punctuation definition group end ruby">)</span><span class="punctuation accessor ruby">.</span>strip<span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">to_i</span>
message <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">ARGV</span><span class="punctuation accessor ruby">.</span>join<span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span> <span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span>

<span class="keyword control ruby">if</span> message<span class="punctuation accessor ruby">.</span>empty?
  <span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Usage: ruby producer.rb &lt;message&gt;<span class="punctuation definition string end ruby">&quot;</span></span>
  <span class="support function builtin ruby">exit</span> <span class="constant numeric ruby">1</span>
<span class="keyword control ruby">end</span>

codec <span class="keyword operator assignment ruby">=</span> <span class="support class ruby">SignalCodec</span><span class="punctuation accessor ruby">.</span><span class="keyword other special-method ruby">new</span>

<span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Sending: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span>message<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
codec<span class="punctuation accessor ruby">.</span>send_message<span class="punctuation definition group begin ruby">(</span>message<span class="punctuation separator ruby">,</span> broker_pid<span class="punctuation definition group end ruby">)</span>
<span class="support function builtin ruby">puts</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Message sent to broker (PID: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span>broker_pid<span class="punctuation section embedded ruby">}</span></span>)<span class="punctuation definition string end ruby">&quot;</span></span>
</span></code></pre>
<ul>
<li>
<p>Producer receives a ASCII message from the <em>STDIN</em></p>
</li>
<li>
<p>Encode and sends the message to the broker via outgoing signals</p>
</li>
</ul>
<p>So far, this architecture should look familiar. Many broker implementations follow these basic foundations.</p>
<blockquote>
<p>Of course, production-ready implementations are far more robust than this one. Here, we're just poking around with hacking and experimentation</p>
</blockquote>
<p>The coolest part is the <code>SignalCodec</code> though:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="meta class ruby"><span class="keyword control class ruby">class</span></span><span class="meta class ruby"> </span><span class="meta class ruby"><span class="entity name class ruby">SignalCodec</span></span><span class="meta class ruby"> 
  </span><span class="meta constant ruby"><span class="entity name constant ruby">SIGNAL_DELAY</span></span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0.001</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Delay between signals to allow processing
</span>
  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">initialize</span></span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>buffer</span> <span class="keyword operator assignment ruby">=</span> <span class="punctuation section array ruby">[</span><span class="punctuation section array ruby">]</span>
  <span class="keyword control ruby">end</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">accumulate_bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">bit</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="punctuation definition group begin ruby">(</span>bit <span class="keyword operator assignment augmented ruby">&lt;&lt;</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span><span class="punctuation definition group end ruby">)</span>
    <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment augmented ruby">+=</span> <span class="constant numeric ruby">1</span>

    <span class="keyword control ruby">if</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator comparison ruby">==</span> <span class="constant numeric ruby">8</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Byte is complete
</span>      <span class="keyword control ruby">if</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span><span class="punctuation accessor ruby">.</span>zero? <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Message complete - NULL terminator
</span>        decoded <span class="keyword operator assignment ruby">=</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>buffer</span><span class="punctuation accessor ruby">.</span>pack<span class="punctuation definition group begin ruby">(</span><span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>C*<span class="punctuation definition string end ruby">&quot;</span></span><span class="punctuation definition group end ruby">)</span><span class="punctuation accessor ruby">.</span>force_encoding<span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>UTF-8<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation definition group end ruby">)</span>
        <span class="keyword control pseudo-method ruby">yield</span><span class="punctuation definition group begin ruby">(</span>decoded<span class="punctuation definition group end ruby">)</span> <span class="keyword control ruby">if</span> <span class="keyword control pseudo-method ruby">block_given?</span>
        <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>buffer</span><span class="punctuation accessor ruby">.</span>clear
      <span class="keyword control ruby">else</span> 
        <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>buffer</span> <span class="keyword operator assignment augmented ruby">&lt;&lt;</span> <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span>
      <span class="keyword control ruby">end</span>

      <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>position</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span>
      <span class="variable other readwrite instance ruby"><span class="punctuation definition variable ruby">@</span>accumulator</span> <span class="keyword operator assignment ruby">=</span> <span class="constant numeric ruby">0</span>
    <span class="keyword control ruby">end</span>
  <span class="keyword control ruby">end</span>

  <span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">send_message</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">message</span><span class="punctuation separator ruby">,</span> <span class="variable parameter ruby">pid</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
    message<span class="punctuation accessor ruby">.</span>each_byte <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">byte</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
      <span class="constant numeric ruby">8</span><span class="punctuation accessor ruby">.</span>times <span class="keyword control start-block ruby">do</span> <span class="meta block parameters ruby"><span class="punctuation definition parameters begin ruby">|</span></span><span class="meta block parameters ruby"><span class="variable parameter ruby">i</span><span class="meta block parameters ruby"><span class="punctuation definition parameters end ruby">|</span></span></span>
        bit <span class="keyword operator assignment ruby">=</span> <span class="punctuation definition group begin ruby">(</span>byte <span class="keyword operator other ruby">&gt;&gt;</span> i<span class="punctuation definition group end ruby">)</span> <span class="keyword operator arithmetic ruby">&amp;</span> <span class="constant numeric ruby">1</span>
        signal <span class="keyword operator assignment ruby">=</span> bit <span class="keyword operator comparison ruby">==</span> <span class="constant numeric ruby">0</span> <span class="keyword operator conditional ruby">?</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span> <span class="keyword operator conditional ruby">:</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR2<span class="punctuation definition string end ruby">&#39;</span></span>
        <span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>kill<span class="punctuation definition group begin ruby">(</span>signal<span class="punctuation separator ruby">,</span> pid<span class="punctuation definition group end ruby">)</span>
        <span class="support function builtin ruby">sleep</span> <span class="variable other constant ruby">SIGNAL_DELAY</span>
      <span class="keyword control ruby">end</span>
    <span class="keyword control ruby">end</span>

    <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> Send NULL terminator (0000 0000)
</span>    <span class="constant numeric ruby">8</span><span class="punctuation accessor ruby">.</span>times <span class="keyword control start-block ruby">do</span>
      <span class="support class ruby">Process</span><span class="punctuation accessor ruby">.</span>kill<span class="punctuation definition group begin ruby">(</span><span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>SIGUSR1<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation separator ruby">,</span> pid<span class="punctuation definition group end ruby">)</span>
      <span class="support function builtin ruby">sleep</span> <span class="variable other constant ruby">SIGNAL_DELAY</span>
    <span class="keyword control ruby">end</span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>
</span></code></pre>
<p>If you've been following along, this shouldn't be hard to understand, but I'll break down how this beautiful piece of code works:</p>
<ul>
<li>
<p>The codec is initialized with the bit position at zero, as well as the accumulator</p>
</li>
<li>
<p>A buffer is also initialized to store accumulated bits until a complete byte is formed</p>
</li>
<li>
<p>The <code>accumulate_bit</code> method should be familiar from our earlier implementation, but it now accepts a closure (block) that lets the caller decide what to do with each decoded byte</p>
</li>
<li>
<p><code>send_message</code> encodes a message into bits and sends them via UNIX signals</p>
</li>
</ul>
<p>Everything in action:</p>
<p><img src="/uploads/3170.png" alt="image" /></p>
<p><em>How cool, amazing, wonderful, impressive, astonishing is that?</em></p>
<h2 id="conclusion">Conclusion</h2>
<p>Yes, we built a message broker using nothing but <strong>UNIX signals</strong> and a bit of Ruby magic. Sure, <strong>it's not production-ready</strong>, and you definitely shouldn't use this in your next startup (please don't), but that was never the point.</p>
<p>The real takeaway here isn't the broker itself: it's understanding how the fundamentals work. We explored binary operations, UNIX signals, and IPC in a hands-on way that most people never bother with.</p>
<p>We took something "useless" and made it work, just for fun. So next time someone asks you about message brokers, you can casually mention that you once built (or saw) one using just two signals. And if they look at you weird, well, that's their problem. Now go build something equally useless and amazing. The world needs more hackers who experiment just for the fun of it.</p>
<p><em>Happy hacking!</em></p>
]]></description>
<pubDate>2025-10-21</pubDate>
</item>
<item>
<title>Um resumo do meu 2024</title>
<link>https://leandronsp.com/articles/um-resumo-do-meu-2024-1lf4.html</link>
<guid>https://leandronsp.com/articles/um-resumo-do-meu-2024-1lf4.html</guid>
<description><![CDATA[<p>31 de Dezembro de 2024.</p>
<p>Sentado no sofá e assistindo Frozen, tive a ideia de escrever sobre minha retrospectiva deste ano. Nunca fiz isso antes, então bora lá, porque acho que foi muita coisa.</p>
<hr />
<h2 id="mas-antes-um-aftermath-de-2023">Mas antes, um aftermath de 2023</h2>
<p>2023 foi um ano bastante agitado pra mim. Passei por uma <a href="https://pt.wikipedia.org/wiki/Tiroidectomia">tireoidectomia</a> (mas estou bem, obrigado) e também foi o ano em que resolvi fazer "learn in public" e deixar tudo gravado no <a href="https://www.youtube.com/@leandronsp">meu canal do Youtube</a>.</p>
<p>Iniciei cobrindo a rinha de compiladores, onde submeti <a href="https://github.com/leandronsp/patropi">uma versão em Ruby</a>, e depois fui trazendo <a href="https://www.youtube.com/watch?v=6VSgMbFNUuQ">conteúdo para iniciantes</a> em Rust.
Teve também transmissão ao vivo criando uma <a href="https://www.youtube.com/watch?v=4jY_Vwnm-es">Rede Neural Artificial em Ruby</a>, então vi que eu realmente estava gostando de compartilhar minha jornada <em>coding in public</em>.</p>
<p>Na parte de artigos, <a href="https://dev.to/leandronsp">escrevi muita coisa</a> em 2023:</p>
<ul>
<li>
<p>Introdução ao <a href="https://leandronsp.com/articles/tekton-ci-part-i-a-gentle-introduction-ilj">Tekton CI/CD</a></p>
</li>
<li>
<p><a href="https://leandronsp.com/articles/kubernetes-101-part-i-the-fundamentals-23a1">Kubernetes 101</a></p>
</li>
<li>
<p>Um guia completo cobrindo <a href="https://leandronsp.com/articles/git-fundamentals-a-complete-guide-do7">os fundamentos de Git</a></p>
</li>
<li>
<p>Criando <a href="https://leandronsp.com/articles/ai-ruby-an-introduction-to-neural-networks-23f3">redes neurais em Ruby</a></p>
</li>
<li>
<p>Teve até artigo sobre <a href="https://leandronsp.com/articles/vencendo-os-numeros-de-ponto-flutuante-um-guia-de-sobrevivencia-4n7n">ponto flutuante</a></p>
</li>
<li>
<p><a href="https://leandronsp.com/articles/entendendo-fundamentos-de-recursao-2ap4">Fundamentos de recursão</a></p>
</li>
<li>
<p><a href="https://leandronsp.com/articles/compiladores-trampolim-deque-e-thread-pool-dd1">Resumo da rinha de compiladores</a> e trampolim</p>
</li>
<li>
<p><a href="https://leandronsp.com/articles/understanding-the-basics-of-smart-pointers-in-rust-3dff">Mais Rust</a></p>
</li>
</ul>
<p>E o famoso <a href="https://web101.leandronsp.com/">Guia Web 101</a> também.</p>
<blockquote>
<p>Mentira, esse guia web foi em 2021, mas eu quis colocar ele aqui só pra fazer propaganda mesmo</p>
</blockquote>
<hr />
<h2 id="as-metas-para-2024">As metas para 2024</h2>
<p>No fim de 2023 estabeleci algumas metas pra 2024 nessa parte de criação de conteúdo. Mas não foram metas muito arrojadas pois eu queria dar uma desaquecida do que foi o agitado 2023.</p>
<p>Dentre as metas estava continuar explorando Rust; escrever um <strong>guia completo de concorrência</strong>; criar um interpretador em Ruby; fazer lives com Kubernetes; falar sobre tédio e; Awk.</p>
<blockquote>
<p>Sim, Awk</p>
</blockquote>
<p>Podemos confirmar isto em meio a tantos rascunhos que tenho nesta plataforma:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34ejih5wbhkmueyxz0qk.png" alt="Image description" /></p>
<hr />
<h2 id="e-chegou-2024">E chegou 2024</h2>
<p>Comecei o ano de 2024 focado em me aprofundar em Rust, tanto que em Janeiro até cheguei a criar o <a href="https://github.com/leandronsp/crust">crust</a> (outro CRUD, mas desta vez em Rust) e o <a href="https://github.com/leandronsp/aspirina">aspirina</a> (outra rede neural, mas desta vez em Rust) durante algumas lives. Queria também iniciar meus estudos em Rust na parte de I/O assíncrono. Era esse o plano.</p>
<p><em>Era</em>.</p>
<h3 id="a-rinha-de-backend-2ª-edição">A Rinha de Backend, 2ª edição</h3>
<p>Mas aí veio a rinha de backend do Zan pra tirar meu foco e resolvi fazer lives compartilhando minha solução submetida, que inicialmente seria em Ruby, com o <a href="https://github.com/leandronsp/agostinho">agostinho</a>.</p>
<p><a href="https://www.youtube.com/watch?v=VR4mF9TMPws">Ledo</a> <a href="https://www.youtube.com/watch?v=5nDfz1dkX2o">engano</a>. Acabei por submeter 5 diferentes soluções:</p>
<ul>
<li>
<p>3 em Ruby: <a href="https://github.com/leandronsp/agostinho">agostinho</a>, que usa meus micro frameworks favoritos Adelnor e Chespirito; <a href="https://github.com/leandronsp/tortuga">tortuga</a> que não usa framework nem biblioteca alguma, o puro suco de uma linguagem criada no Japão; e <a href="https://github.com/leandronsp/tonico">tonico</a>, uma versão sem frameworks que usa I/O assíncrono <em>all the way down</em></p>
</li>
<li>
<p>1 em Rust: <a href="https://github.com/leandronsp/quokka">quokka</a>, criado durante uma live</p>
</li>
<li>
<p>e claro, a famosa versão em Bash, <a href="https://github.com/leandronsp/canabrava">canabrava</a></p>
</li>
</ul>
<p>Foram muitas horas em lives, inclusive esta onde eu mostrava como criar uma <a href="https://www.youtube.com/watch?v=lD3gaazwptk">thread pool e connection pool em Rust</a>.</p>
<blockquote>
<p>Nossa Leandro, como você arranja tempo pra fazer lives? Eu não consigo ter tempo pra isso</p>
</blockquote>
<p>Isso é problema seu, e não meu.</p>
<h3 id="um-leve-sopro-do-gleam-e-o-grande-tutorial-de-assembly">Um leve sopro do Gleam e o grande tutorial de Assembly</h3>
<p>No início do ano notei um pequeno hype em cima do <strong>Gleam</strong>. Decidi <a href="https://www.youtube.com/watch?v=0XTtAra0l8Q">explorar em live</a>. Até que gostei da linguagem, e estava determinado a continuar estudando.</p>
<p>Mas aí minha amiga e meu amigo, algumas pessoas do trabalho começaram a me provocar. Ficavam colocando <strong>Assembly</strong> na minha frente. Foi quando numa 6a feira sem pretensão, no Discord, eu e mais alguns colegas fizemos um <a href="https://www.tutorialspoint.com/assembly_programming/index.htm">tutorial rápido</a> de Assembly x86.</p>
<p>Foi quando pensei "ta aí, vou aprender esse negócio e criar um web server multi-threaded simples em Assembly, compartilhando a jornada tanto em artigos quanto em lives".</p>
<h3 id="a-saga-do-assembly-x86">A saga do Assembly x86</h3>
<p>Fiz várias lives pela manhã (que eu chamava de lives matinais, duh), mostrando o desenvolvimento do web server e minha saga de aprendizado. Foi incrível, pude ter contato com pessoas como o <a href="https://www.youtube.com/@debxp">Blau Araújo</a> que é referência em conteúdo pt-BR em Assembly e outras coisas de baixo nível.</p>
<p>Tem um vídeo no meu canal, que é a minha "sincera" reação quando o server finalmente funcionou devolvendo a primeira resposta HTTP, <a href="https://www.youtube.com/watch?v=un-7IGJiXeo">ao vivo em live</a>.</p>
<p>Não obstante, resolvi também <a href="https://www.youtube.com/watch?v=bMGrJU1eRXU">escrever artigos em live</a>. Me diga, quem em sã consciência acompanha alguém escrevendo um artigo em live durante umas 4 ou 5 horas?</p>
<blockquote>
<p>Não sei quem é mais maluco</p>
</blockquote>
<p>Brincadeiras a parte, e ideia é mesmo compartilhar o processo. É sobre o <em>modus operandi</em>, a forma como eu quebro o raciocínio em partes na hora de escrever. E também o que me inspira.</p>
<p>No mundo dos artigos, eu <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-i-introducao-14p5">comecei em Abril</a> a saga "Escrevendo um Web server em Assembly x86". Foram um total de 6 artigos, onde no final conseguimos implementar um web server simples, porém multi-threaded em Assembly. Foram 3 meses escrevendo, fazendo lives e <a href="https://github.com/leandronsp/monica">muitos conceitos abordados</a>, muita coisa mesmo.</p>
<p>Aproveitei também para escrever sobre <a href="https://leandronsp.com/articles/arrays-em-assembly-x86-55hb">Arrays em Assembly x86</a>.</p>
<p>Esta saga foi muito enriquecedora pra mim. Pude aprender e firmar muitos conceitos. Vale muito a pena aprender Assembly e coisas de baixo nível.</p>
<h3 id="enfim-o-guia-de-concorrência-101">Enfim o "Guia de Concorrência 101"</h3>
<p>Quando finalizei a saga de Assembly, resolvi voltar para uma das coisas que eu tinha como meta para 2024: escrever sobre <strong>concorrência</strong>. Este é um tema que estudo há mais de 5 anos quase que diariamente, experimentando e validando conceitos.</p>
<p>Foi então que bem agora, agorinha mesmo (risos) no final de Novembro que comecei a escrever o <a href="https://concorrencia101.leandronsp.com/">guia de concorrência</a> (pt-BR). Por enquanto já abordei conceitos de concorrência no sistema operacional e como a linguagem C implementa as principais primitivas de concorrência. Mas o intuito é cobrir com mais linguagens de programação: Ruby, Python, PHP, NodeJS, Go, Rust, Elixir, Java, Kotlin e mais o que vier à cabeça.</p>
<p>Com uma brincadeira no bluesky, o <a href="https://bsky.app/profile/rdenadai.com.br">Rodolfo de Nadai</a> (meu primeiro investidor) deu uma ideia de eu lançar um "buy me a coffee" neste guia. Lancei e gostei da ideia, tanto que no momento são <a href="https://concorrencia101.leandronsp.com/agradecimentos">23 apoiadores</a> do projeto. Apesar de que faço de forma genuína sem interesse financeiro, pois defendo muito o conhecimento livre, este apoio da galera tem sido crucial para que eu continuasse, desde o apoio com Pix, revisão ou mesmo compartlihamento do conteúdo.</p>
<p>Gratidão a todos vocês que fazem isto acontecer ❤</p>
<h3 id="misc">Misc</h3>
<p>Outras coisas que explorei ao longo deste ano, enquanto ia focando nas coisas de Assembly e concorrência:</p>
<ul>
<li>
<p><a href="https://github.com/leandronsp/necelu">leandronsp/necelu</a>, brincando com Lucene em Java (relembrando <em>the good old days</em>)</p>
</li>
<li>
<p><a href="https://github.com/leandronsp/otel-rails">open telemetry</a>: OTel é um assunto bem interessante, onde quero me aprofundar em 2025</p>
</li>
<li>
<p><a href="https://github.com/leandronsp/yacs">leandronsp/yacs</a>, Yet Another City Search, uma busca textual ultra-rápida em PostgreSQL em mais de 12 milhões de geonames/cidades</p>
</li>
</ul>
<hr />
<h2 id="o-que-esperar-pra-2025">O que esperar pra 2025</h2>
<p>Para 2025, espero mergulhar mais fundo em Rust, explorar OpenTelemetry e, quem sabe, encarar outra linguagem inusitada.</p>
<p>Afinal, aprender nunca é demais. 🚀</p>
<p><strong>Feliz 2025 a todes &lt;3</strong></p>
]]></description>
<pubDate>2025-10-18</pubDate>
</item>
<item>
<title>Voltando às raízes de blogueiro</title>
<link>https://leandronsp.com/articles/voltando-as-raizes-de-blogueiro.html</link>
<guid>https://leandronsp.com/articles/voltando-as-raizes-de-blogueiro.html</guid>
<description><![CDATA[<p>Já faz um tempo que não escrevo aqui no blog.</p>
<p>E também já faz bastante tempo que tenho o interesse em voltar a escrever mais como fazia antigamente, quando tudo o que tinha era algo na mente e simplesmente convertia em um punhado de texto solto no meu blog, como <a href="https://leandromaringolo.blogspot.com/">essa relíquia</a> aqui.</p>
<p>Gosto de escrever artigos técnicos, mas por outro lado também gosto de simplesmente sentar e começar a escrever sem grandes pretensões. Só que me faltava algo. Eu só não sabia o que era.</p>
<p>Para entender o que me faltava, vamos dar uns passos atrás e entender o contexto de como eu vinha utilizando plataformas de blogging e o cenário de blogging moderno.</p>
<h2 id="blogpost">Blogpost</h2>
<p>A primeira plataforma que utilizei foi o <a href="https://www.blogger.com/">Blogger</a>, antigo <em>blogspot</em>, onde comecei a escrever meus primeiros artigos quando eu ainda "mexia com TI". <strong>O ano era 2009</strong>.</p>
<p>Eu compartilhava <a href="https://leandromaringolo.blogspot.com/">estudo de programação</a> quando tinha terminado a faculdade e também as gambiarras que eu fazia instalando e corrigindo problemas no Windows XP com Service Pack 3®.</p>
<p>Atualmente o editor é assim, mas na época era bastante limitado:</p>
<p><img src="/uploads/835.png" alt="image" /></p>
<p>Não é ruim até, mas repara como que o <strong>espaço não é aproveitado</strong>. E uma coisa que eu sempre prezo ao escrever é, no caso, o <em>conforto em escrever</em>. Gosto de uma pegada fluída, com fonte agradável e que tenha um bom contraste. No caso desta plataforma em questão, eu tenho que clicar num botão de "Preview" e assim sou direcionado para outra página, saindo completamente do contexto.</p>
<p>Isso me entristece, muito.</p>
<p>Foram bons momentos como blogueirinho no Blogger, mas fiquei uns anos sem escrever por conta de vários motivos até que...</p>
<h2 id="medium">Medium</h2>
<p>Circa 2014 <a href="https://medium.com/@leandronsp">decidi experimentar</a> voltar a escrever, mas desta vez no Medium. Fiz apenas um punhado de artigos sem grandes pretensões, mas eu tinha gostado da fluidez (na época) de escrever na plataforma deles.</p>
<p>Entretanto a experiência de escrever ainda tava longe de ser a que eu queria. Mas eu nem sabia o que queria.</p>
<p><img src="/uploads/899.png" alt="image" /></p>
<blockquote>
<p>Cadê o botão de preview? Oh, gosh...</p>
</blockquote>
<p>Fast-forward para 2021.</p>
<h2 id="dev.to-e-hashnode">DEV.to e Hashnode</h2>
<p>A plataforma dev.to me pareceu a princípio bastante intuitiva. Tem um lance de comunidade que é bacana, porque para além de ser uma plataforma de blogging é também uma comunidade em volta disso. Sem contar com o <strong>suporte a Markdown</strong> que nos dias de hoje é crucial para escrever artigos.</p>
<p>Decidi <a href="https://dev.to/leandronsp">criar uma conta</a> lá e desde então tenho <strong>publicado quase 100 artigos</strong>:</p>
<p><img src="/uploads/931.png" alt="image" /></p>
<p>Ao mesmo tempo, a experiência de escrever era a melhor de todas que eu encontrei, mas ainda faltava uma coisa que eu já estava começando a perceber: <em>preview em tempo real</em>.</p>
<p>É muito chato você escrever bastante coisa e ter que clicar num botão lá em cima pra abrir outra página que, não raramente, demora pra carregar. É uma experiência que não sou fã 100%.</p>
<p><img src="/uploads/7650.png" alt="image" /></p>
<p>Na mesma época eu queria algo parecido mas que pudesse ter uma "landing page" no estilo dos blogs antigos com um menu customizado com os links que eu quisesse colocar. Para além do suporte a Markdown e um editor fluído. Foi quando conheci o <a href="https://hashnode.com/@leandronsp">Hashnode</a>.</p>
<p>Com Hashnode, eu pude criar uma página "customizada" com menu e assim organizar melhor meus artigos. Mas me faltava ainda algo mais configurável.</p>
<p>Pra não mencionar que a experiência de escrita continuava a ser a mesma: <em>ter que clicar num botão de preview</em> que, com uma latência absurda, faz 412 coisas menos mostrar o preview que você verdadeiramente quer naquele momento.</p>
<p><img src="/uploads/995.png" alt="image" /></p>
<p>Acabou que deixei o Hashnode flopar, mas ficou com meu domínio <code>leandronsp.com</code> e passei a escrever mais pelo DEV.to mesmo.</p>
<p><em>Era o que tinha pra janta</em>.</p>
<blockquote>
<p>Mas Leandro, existem ferramentas de visualização de Markdown, você consegue usar isso no Obsidian, na linha de comando, com plugin do Vim, com extensão do VSCode, etc etc</p>
</blockquote>
<p>Calma, calabreso. Eu quero apenas escrever, ver em tempo real o que estou escrevendo <em>sendo renderizado</em> e a seguir publicar. That's it. Pra mim o web browser é ainda a ferramenta onde sinto mais conforto ao fazer esse tipo de tarefa.</p>
<blockquote>
<p>Desculpa galera do terminal, mas como um heavy-terminal user e Vimer raiz, eu ainda prefiro blogar no browser</p>
</blockquote>
<p>Foi assim até 2 dias atrás.</p>
<h2 id="a-vontade-de-escrever-sobre-unix-signals">A vontade de escrever sobre UNIX signals</h2>
<p>Como aqueles momentos em que do nada me vem a cabeça experimentar algo inútil que ninguém pediu e que provavelmente não vai pedir, decidi criar um broker de mensageria utilizando apenas sinais UNIX.</p>
<blockquote>
<p>Em breve publico isto, foi divertido</p>
</blockquote>
<p>Então, como de praxe, resolvi sentar pra escrever sobre. No DEV.to como habitual. Mas quer saber?</p>
<p><em>Cansei</em>.</p>
<p>Resolvi criar meu próprio motor de blog que iria me atender em todos os aspectos que sinto falta nos motores atuais: aproveitar espaço, trazer <em>preview em tempo real</em>, navegação fluída, simples e sem muito ruído, tudo com suporte a Markdown.</p>
<p>Eu queria algo mais ou menos assim:</p>
<p><img src="/uploads/7778.png" alt="image" /></p>
<p>Com isto em mente, resolvi criar o <a href="https://github.com/leandronsp/curupira">curupira</a>.</p>
<h2 id="curupira">Curupira</h2>
<p>Pra quem já me conhece sabe que sou péssimo com nomes, mas resolvi dar esse nome em homenagem ao nosso folclore brasileiro e ao protetor das nossas matas. Só porque sim.</p>
<p>No intuito de ter uma navegação fluída como a que eu sonhava, decidi utilizar <a href="https://hexdocs.pm/phoenix_live_view/welcome.html">Phoenix LiveView</a>. Em resumo, é uma tecnologia que escala absurdamente por conta da VM que roda por baixo, a <em>BEAM</em>. Meu objetivo de ter de um lado o editor para escrever e do outro um preview em tempo real poderia ser finalmente atingido de forma simples.</p>
<p>É muito, mas muito simples criar apps real-time com Phoenix LiveView. A seguir uma demonstração de como pode ficar a página inicial do curupira:</p>
<p><img src="/uploads/484.png" alt="image" /></p>
<p>Basicamente você tem de um lado uma bio que resume teu blog, e do outro a lista de artigos. <em>É isto</em>. Não precisa ser complicado, temos que aproveitar o máximo de espaço possível na tela.</p>
<p><img src="/uploads/516.png" alt="image" /></p>
<p>Dá também pra alternar entre tema claro e escuro:</p>
<p><img src="/uploads/4098.png" alt="image" /></p>
<p>Além de tudo isso, é possível também gerar o site estático a partir de um comando <code>make</code>.</p>
<blockquote>
<p>Isto vai ser melhorado em breve, quero também deixar o processo de geração do site estático mais fluído e UX-friendly em um futuro próximo</p>
</blockquote>
<h2 id="leandronsp.com">leandronsp.com</h2>
<p>Após gerar o site estático, mudei o apontamento do meu domínio principal para o Cloudflare Pages, mas poderia ser qualquer outro como Github Pages, Vercel, etc (esta parte ainda está manual no momento, vem mais coisa em breve).</p>
<p>Meu novo site ficou então assim:</p>
<p><img src="/uploads/4194.png" alt="image" /></p>
<p><img src="/uploads/4258.png" alt="image" /></p>
<p>Preferi fazer com que a página do artigo tivesse espaço suficiente para o conteúdo, e não para ruídos.</p>
<hr />
<h2 id="conclusão">Conclusão</h2>
<p>É isto, pra quem tiver curiosidade em ver o repositório <a href="https://github.com/leandronsp/curupira">leandronsp/curupira</a>, publiquei hoje mas ainda está WIP.</p>
<p>Este artigo já foi escrito com o curupira, e em breve será publicado neste blog.</p>
]]></description>
<pubDate>2025-10-18</pubDate>
</item>
<item>
<title>Arrays em Assembly x86</title>
<link>https://leandronsp.com/articles/arrays-em-assembly-x86-55hb.html</link>
<guid>https://leandronsp.com/articles/arrays-em-assembly-x86-55hb.html</guid>
<description><![CDATA[<p>Recentemente escrevi <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-i-introducao-14p5">uma saga de 6 artigos</a> sobre Assembly x86, abordando conceitos fundamentais de arquitetura de computadores e programação low-level enquanto ia desenvolvendo um web server minimalista multi-threaded.</p>
<p>Durante o processo, acabei deixando de lado alguns conceitos importantes para artigos posteriores, pois se fosse abordar durante a saga, iria ficar maior do que já foi. Entretanto são conceitos que podem ser tratados à parte, como no caso das filas implementadas na thread pool.</p>
<p>E quando falamos de filas, <strong>fica inevitável abordar arrays</strong> e como estes são organizados na memória do computador.</p>
<p>Neste artigo, vamos abordar conceitos fundamentais como manipulação de memória, registradores e memória heap ao longo da implementação de arrays.</p>
<blockquote>
<p>Vou assumir que você já tem familiaridade com Assembly x86 e a ferramenta GDB. Caso não tenha, recomendo fortemente a leitura da minha saga.</p>
</blockquote>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#arrays-n%C3%A3o-existem">Arrays não existem</a></p>
</li>
<li>
<p><a href="#strings-tamb%C3%A9m-n%C3%A3o-existem">Strings também não existem</a></p>
</li>
<li>
<p><a href="#o-array-mais-simples-do-universo">O array mais simples do universo</a></p>
</li>
<li>
<p><a href="#utilizando-um-array-com-dados-n%C3%A3o-inicializados">Utilizando um array com dados não inicializados</a></p>
<ul>
<li><a href="#%C3%ADndice-para-o-resgate">Índice para o resgate</a></li>
<li><a href="#atingindo-o-limite-do-array">Atingindo o limite do array</a></li>
</ul>
</li>
<li>
<p><a href="#heap-heap-horray">Heap, heap, hooray!</a></p>
<ul>
<li><a href="#aloca%C3%A7%C3%A3o-din%C3%A2mica-de-mem%C3%B3ria-com-brk">Alocação dinâmica de memória com brk</a></li>
<li><a href="#ponteiros-ponteiros-everywhere">Ponteiros, ponteiros everywhere</a></li>
<li><a href="#resize-com-brk">Resize com brk</a></li>
</ul>
</li>
<li>
<p><a href="#o-programa-final">O programa final</a></p>
</li>
<li>
<p><a href="#conclus%C3%A3o">Conclusão</a></p>
</li>
<li>
<p><a href="#refer%C3%AAncias">Referências</a></p>
</li>
</ul>
<hr />
<h2 id="arrays-não-existem">Arrays não existem</h2>
<p><em>Arrays não existem.</em> Simples assim.</p>
<p>Como vimos <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iv-um-assembly-modesto-oif">na parte IV</a> da saga, a memória é organizada de forma contígua, onde as informações são alocadas uma após a outra.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u90q0z4ka96nccs1syef.png" alt="memoria é contígua" /></p>
<p>Supondo que queremos declarar a seguinte sequência de informações:</p>
<pre><code class="sourceCode"><span class="text plain">1, 2, &#39;H&#39;, 0
</span></code></pre>
<blockquote>
<p>Eu sei, eu sei, os tipos estão misturados, mas isto não importa para este momento. Todos eles cabem em 1 byte</p>
</blockquote>
<p>Em assembly x86 (vamos chamar de asm no restante do artigo), podemos declarar estas informações da seguinte forma na seção de dados:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
stuff<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0x1</span>, <span class="constant numeric actionscript 2">0x2</span>, <span class="constant numeric actionscript 2">0x48</span>, <span class="constant numeric actionscript 2">0x0</span>
</span></code></pre>
<blockquote>
<p>Lembrando que o caracter 'H' na tabela ASCII representa 0x48 em hexadecimal</p>
</blockquote>
<p>Ao utilizarmos o <code>gdb</code> para fazer debugging, podemos confirmar que esta sequência de hexadecimal no rótulo <code>stuff</code> está armazenada da seguinte forma:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Leitura do primeiro hexabyte em stuff</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/1xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">stuff</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>stuff<span class="keyword operator assignment redirection shell">&gt;</span>:       0x01</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Leitura do segundo hexabyte em stuff</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/1xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">stuff+1</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402001:</span></span><span class="meta function-call arguments shell">       0x02</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Leitura do terceiro hexabyte em stuff</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/1xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">stuff+2</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002:</span></span><span class="meta function-call arguments shell">       0x48</span>
</span></code></pre>
<p>Podemos também representar o hexadecimal <code>0x48</code> em formato de string utilizando <code>x/s</code></p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/s (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">stuff+2</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002:</span></span><span class="meta function-call arguments shell">       <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>H<span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<p><em>É tudo hexadecimal!</em></p>
<p>Com isto, caso queiramos representar a string "Hello", de acordo com a tabela ASCII, poderia ficar assim:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0x48</span>, <span class="constant numeric actionscript 2">0x65</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6F</span>, <span class="constant numeric actionscript 2">0x0</span>
</span></code></pre>
<p>No gdb vamos verificar a representação string do rótulo <code>msg</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/s</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">msg</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>msg<span class="keyword operator assignment redirection shell">&gt;</span>: <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Hello<span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<p>Em asm, é possível declarar a string já com a representação direta da tabela ASCII:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0x0</span>

; é o mesmo que
; msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0x48</span>, <span class="constant numeric actionscript 2">0x65</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6F</span>, <span class="constant numeric actionscript 2">0x0</span>
</span></code></pre>
<hr />
<h2 id="strings-também-não-existem">Strings também não existem</h2>
<p>Ou seja, é tudo hexadecimal na memória. Um array, assim como uma string, é simplesmente uma sequência contígua de dados <strong>com mesmo tamanho</strong> na memória.</p>
<p>A diferença é que a string é um "array especial" que tem dados que representam caracteres da tabela ASCII (note que ambos precisam delimitar um byte "final" para representar o término da string ou array):</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dw5cjo8fvoh7rvp8t2l3.png" alt="string e array" /></p>
<h2 id="o-array-mais-simples-possível">O array mais simples possível</h2>
<p>A seguir temos a implementação de um array bastante simples em asm, pelo que iremos explorar cada passo nas seções subsequentes:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">data</span>
array<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">1</span>, <span class="constant numeric actionscript 2">2</span>, <span class="constant numeric actionscript 2">3</span>, <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov al, [array]        ; array[<span class="constant numeric actionscript 2">0</span>]
	mov bl, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>]    ; array[<span class="constant numeric actionscript 2">1</span>]
	mov cl, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">2</span>]    ; array[<span class="constant numeric actionscript 2">2</span>]
	mov sil, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">3</span>]   ; array[<span class="constant numeric actionscript 2">3</span>]
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
</span></code></pre>
<p>Na seção de dados inicializados <code>.data</code>, declaramos um array com 3 elementos de 1 byte cada (inteiros de 1 a 3), utilizando o número 0 como término do array:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
array<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">1</span>, <span class="constant numeric actionscript 2">2</span>, <span class="constant numeric actionscript 2">3</span>, <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<p>A seguir, na seção <code>.text</code>, que é onde vai o código fonte do programa, podemos acessar os elementos do array utilizando aritmética de ponteiros, armazenando o resultado em registradores:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
mov al, [array]        ; array[<span class="constant numeric actionscript 2">0</span>]
</span></code></pre>
<p>No código acima, estamos acessando o valor contido no endereço de memória <code>0x402000</code> e armazenando o resultado em um registrador (AL) que tem o tamanho de 1 byte, ou seja, vai ser armazenado no registrador apenas o primeiro byte do array.</p>
<p>Vamos conferir com gdb:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O array está armazenado no endereço 0x402000</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> e contém o valor em hexa 0x00 0x03 0x02 0x01,</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> lembrando que esta arquitetura utiliza o formato little-endian</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00030201</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 13</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> No registrador AL temos o primeiro elemento do array</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r al</span>
<span class="meta function-call shell"><span class="variable function shell">al</span></span><span class="meta function-call arguments shell">             0x1                 1</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> É o mesmo que acessar o primeiro hexabyte contido no endereço</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x402000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/1xb 0x402000</span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x01</span>

</span></code></pre>
<blockquote>
<p>Lembrando que o registrador AL representa os 8-bits menores dentro do espectro do registrador RAX que contempla um total de 64-bits na arquitetura x86_64</p>
</blockquote>
<p>Para acessar os demais elementos do array, basta fazer aritmética de ponteiros e ir armazenando em outros registradores de 1 byte:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov al, [array]        ; array[<span class="constant numeric actionscript 2">0</span>] <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">1</span>
mov bl, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>]    ; array[<span class="constant numeric actionscript 2">1</span>] <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">2</span>
mov cl, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">2</span>]    ; array[<span class="constant numeric actionscript 2">2</span>] <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">3</span>
mov sil, [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">3</span>]   ; array[<span class="constant numeric actionscript 2">3</span>] <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">0</span> (aqui termina o array)
</span></code></pre>
<hr />
<h2 id="utilizando-um-array-com-dados-não-inicializados">Utilizando um array com dados não inicializados</h2>
<p>Até agora, estamos declarando o array na seção <code>.data</code> onde os dados são inicializados. Mas podemos deixar o programa mais "dinâmico", declarando o array na seção de dados <strong>não inicializados</strong>, que é a <code>.bss</code>.</p>
<p>Mantendo a compatibilidade com o exemplo anterior, vamos declarar um array de 4 bytes utilizando a diretiva <code>resb</code> que significa "reserve byte", onde os 3 primeiros bytes são reservados para armazenar elementos do array e o último byte representando 0x0 que é o término do array.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">4</span> ; <span class="constant numeric actionscript 2">3</span> bytes <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span> byte de término
</span></code></pre>
<p>No gdb, podemos ver que o array está inicializado com os valores tudo a zero, o que indica que o array está vazio mas com 4 bytes reservados:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000000</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/4xb</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00    0x00    0x00    0x00</span>
</span></code></pre>
<p>Para adicionar elementos no array, precisamos também utilizar aritmética de ponteiros, tal como fizemos no exemplo anterior para acessar um array com dados pré-inicializados.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; Move o valor <span class="constant numeric actionscript 2">1</span> para o primeiro byte <span class="keyword control actionscript 2">do</span> endereço de memória em array
mov byte [array], <span class="constant numeric actionscript 2">1</span>  ; array[<span class="constant numeric actionscript 2">0</span>] <span class="keyword operator symbolic actionscript 2">=</span> <span class="constant numeric actionscript 2">1</span>
</span></code></pre>
<p>Com gdb confirmamos que no endereço 0x402000 que é onde está o array, foi adicionado o byte 1:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000001</span>
</span></code></pre>
<p>E se quisermos adicionar o valor 2 no próximo byte do array?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>], <span class="constant numeric actionscript 2">2</span>
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000201</span>
</span></code></pre>
<p>Repare que o que modifica é o "índice" do array. Na posição inicial do array, é como se o índice fosse zero, e na posição subsequente, utilizamos o índice 1, podendo incrementar até o término array.</p>
<p>Seria muito complicado ficar manipulando índice hard-coded. Precisamos de um <em>ponteiro</em> para representar este índice.</p>
<h3 id="índice-para-o-resgate">Índice para o resgate</h3>
<p>Assumindo que o ponteiro do array começa com <em>zero</em>, que é o endereço de memória onde está o array, podemos declará-lo na seção de dados inicializados <code>.data</code>:</p>
<pre><code class="sourceCode"><span class="text plain">section .bss
array: resb 4 ; 3 bytes + 1 byte de término

section .data
pointer: db 0
</span></code></pre>
<p>Logo, poderíamos adicionar o primeiro elemento da seguinte forma, certo?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> pointer], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<p>Ao rodar o programa, temos o seguinte erro:</p>
<pre><code class="sourceCode"><span class="text plain">src/live.asm:14: error: invalid effective address: multiple base segments
</span></code></pre>
<p><strong>Este erro indica que estamos tentando fazer manipulação de ponteiros a partir de múltiplos segmentos na memória</strong>, no caso o array e pointer.</p>
<p>Para resolver isto, precisamos fazer manipulação de ponteiros com valores imediatos (que foi o caso anterior com número hard-coded) ou com registradores:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; append(<span class="constant numeric actionscript 2">1</span>)
mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<ul>
<li>
<p>a primeira instrução move o primeiro byte contido no endereço de <code>pointer</code> e armazena no registrador AL</p>
</li>
<li>
<p>a segunda instrução move o valor imediato 1 (elemento do array) para o endereço de memória do array. Como em RAX (versão 64-bits de AL) temos o valor <code>0x0</code> que representa o ponteiro, então estamos fazendo a inserção no primeiro byte do array</p>
</li>
</ul>
<p>E para armazenar o segundo elemento no array?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; append(<span class="constant numeric actionscript 2">2</span>)
mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">2</span>
</span></code></pre>
<p>No gdb, vamos verificar o que está acontecendo:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000002</span>
</span></code></pre>
<p><em>Uh, oh...</em> Desta forma estamos sobrescrevendo o valor anterior. Queremos na verdade que o ponteiro "ande", ou seja, precisa ser incrementado em um byte para que o <code>append(2)</code> resulte com os 2 elementos no array.</p>
<p>Com a instrução <code>INC</code> podemos resolver este problema:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov al, byte [pointer]      ; pointer <span class="keyword operator symbolic actionscript 2">-</span>&gt; <span class="constant numeric actionscript 2">0</span>
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
inc byte [pointer]          ; pointer <span class="keyword operator symbolic actionscript 2">-</span>&gt; <span class="constant numeric actionscript 2">1</span>

mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">2</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000201</span>
</span></code></pre>
<p><em>Yay!</em> Que dia maravilhoso!</p>
<h3 id="atingindo-o-limite-do-array">Atingindo o limite do array</h3>
<p>E se continuarmos incrementando o ponteiro até atingir o limite do array?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
inc byte [pointer]

mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">2</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>
inc byte [pointer]

mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">3</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">2</span>
inc byte [pointer]
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Lendo os primeiros 4 hexabytes do array, temos a representação</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> do array cheio com todos os espaços ocupados, lembrando que</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> o último byte é o término do array</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /4xb</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x01    0x02    0x03    0x00</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O ponteiro está no fim do array</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x03</span>
</span></code></pre>
<p>Maravilha, e se adicionar mais um elemento, nosso programa deveria permitir?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov al, byte [pointer]
mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">4</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">3</span>
inc byte [pointer]
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Não deveríamos permitir que mais um elemento fosse adicionado,</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> pois nosso array já estava cheio</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /4xb</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x01    0x02    0x03    0x04</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O ponteiro está para além da capacidade array (not good...)</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x04</span>
</span></code></pre>
<p>Vamos utilizar um jump condicional (explico mais sobre isto na <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iv-um-assembly-modesto-oif">saga</a>) para não permitir que o elemento seja adicionado. Com isto, antes de fazer o append no array, devemos verificar se o ponteiro já não está no fim do array:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; verifica se o array está cheio
je .exit                ; salta para a rotina .exit caso a flag seja levantada
</span></code></pre>
<p>Assim fica o programa completo:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>

section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">4</span> ; <span class="constant numeric actionscript 2">3</span> bytes <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span> byte de término

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; verifica se o array está cheio
	je .exit
	
	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">1</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">0</span>
	inc byte [pointer]
	
	cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; verifica se o array está cheio
	je .exit

	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">2</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>
	inc byte [pointer]

	cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; verifica se o array está cheio
	je .exit

	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">3</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">2</span>
	inc byte [pointer]

	cmp byte [pointer], <span class="constant numeric actionscript 2">3</span>   ; verifica se o array está cheio
	je .exit

	; não deveria permitir adicionar o quarto elemento,
	; pois o array suporta até <span class="constant numeric actionscript 2">3</span> elementos. desta forma,
	; estaríamos escrevendo no endereço de memória de outros
	; dados <span class="keyword control actionscript 2">do</span> programa
	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], <span class="constant numeric actionscript 2">4</span>   ; array <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">3</span>
	inc byte [pointer]
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x00000003</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00030201</span>
</span></code></pre>
<p>Perfeito, vamos agora fazer um pequeno refactoring no código separando a lógica de append para uma subrotina:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb CAPACITY <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">1</span>
	<span class="support function actionscript 2">call</span> .append

	mov rdi, <span class="constant numeric actionscript 2">2</span>
	<span class="support function actionscript 2">call</span> .append

	mov rdi, <span class="constant numeric actionscript 2">3</span>
	<span class="support function actionscript 2">call</span> .append

	mov rdi, <span class="constant numeric actionscript 2">4</span>
	<span class="support function actionscript 2">call</span> .append
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; verifica se o array está cheio
	je .done

	mov al, byte [pointer]
	mov byte [array <span class="keyword operator symbolic actionscript 2">+</span> rax], dil
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
</span></code></pre>
<blockquote>
<p>Se você quer entender mais sobre conditional jump, rotinas, call, ret e flags, sugiro a leitura da minha saga que foi referenciada diversas vezes neste artigo</p>
</blockquote>
<p>Executando com gdb e...</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00030201</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x00000003</span>
</span></code></pre>
<p>Um grande <em>Yay!</em></p>
<p>Entretanto, podem haver situações onde queremos que nosso array seja <em>redimensionado</em> para suportar mais elementos, ou seja, o tamanho do array seria dinâmico.</p>
<p>Como adicionar mais elementos além da <em>capacidade inicial</em> de forma que não podemos escrever em outras áreas da memória que pertencem ao array?</p>
<hr />
<h2 id="heap-heap-hooray">Heap, heap, hooray!</h2>
<p>Antes de falar sobre o heap, vamos relembrar como funciona o layout de memória de um programa de computador:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s81vxvgfylw0wfcf6if7.png" alt="layout de memória" /></p>
<ul>
<li>
<p>o layout é representado como uma área na memória do computador onde temos os endereços de memória mais baixos do programa em direção aos endereços mais altos que ficam no topo</p>
</li>
<li>
<p>nos endereços de memória mais baixos, temos a seção <code>.text</code>, onde já vimos que é referente ao programa em si</p>
</li>
<li>
<p>depois temos a <strong>seção de dados</strong> que contempla os dados inicializados <code>.data</code> e a seção a seguir que representa os dados não-inicializados <code>.bss</code></p>
</li>
<li>
<p>nos endereços mais altos, temos a <em>stack</em> do programa, que armazena metadados tais como o nome do programa, seus argumentos e qualquer informação do programa que tenha um tamanho fixo cabendo dentro da stack, bem como chamadas de funções e seus respectivos argumentos</p>
</li>
<li>
<p>a stack tem um formato de <em>pilha</em> e "cresce pra baixo", ou seja, conforme adicionamos elementos na stack, esta cresce em direção aos endereços mais baixos na memória</p>
</li>
</ul>
<p>No "meio" do layout, entre a seção de dados e a stack, temos uma grande área na memória que muitos acabam associando como <em>heap</em>. No heap, podemos alocar dados de forma dinâmica, diferente da forma estática que fazemos na seção de dados.</p>
<p>Para acomodar um array de tamanho dinâmico que suporte redimensionamento (resize), temos de alocar memória nesta área.</p>
<blockquote>
<p>Neste artigo, vamos chamar esta região no meio da memória que fica entre a seção de dados e a stack de <strong>heap</strong></p>
</blockquote>
<h3 id="alocação-dinâmica-de-memória-com-brk">Alocação dinâmica de memória com brk</h3>
<p>Uma das formas de manipular esta área da memória é através da <a href="https://man7.org/linux/man-pages/man2/brk.2.html">syscall brk</a>, que muda o <em>program break</em>, que é <strong>onde termina a seção de dados</strong>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3c703vs0c7bl1eosh5i8.png" alt="program break" /></p>
<p>Com <code>brk</code>, podemos modificar esse <em>program break</em> para endereços mais altos, ou seja, permitindo a manipulação de áreas na memória que vão além da seção de programa e dados.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jh2x79f2nb1m1v4dcaxe.png" alt="program break visualizado" /></p>
<p>A primeira coisa que precisamos fazer é mapear a syscall e fazer a chamada que traz o endereço do break atual:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
....

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
; syscall para acessar o program <span class="keyword control actionscript 2">break</span> (<span class="constant numeric actionscript 2">0x403000</span>), que é onde termina 
; a seção de dados e começa o heap
mov rdi, <span class="constant numeric actionscript 2">0</span>
mov rax, SYS_brk
syscall
....
</span></code></pre>
<p>Com gdb, vamos analisar o estado do programa:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na linha da syscall brk</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 18</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O início do programa fica na seção .text e começa com </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x401000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x _start</span>
<span class="meta function-call shell"><span class="variable function shell">0x401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>:      0x000000bf</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O pointer está na seção .data um pouco mais acima e começa com</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x402000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x00000000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O array está na seção .bss um pouco mais acima e começa com </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x402004</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Executa a syscall brk</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> A syscall brk armazena em RAX o endereço de memória do program break, </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> no caso um pouco mais acima em 0x403000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rax</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x403000            4206592</span>
</span></code></pre>
<ul>
<li>
<p><code>0x401000</code>: seção <code>.text</code> que é onde começa o programa</p>
</li>
<li>
<p><code>0x402000</code>: seção <code>.data</code> onde ficam os dados inicializados</p>
</li>
<li>
<p><code>0x402004</code>: seção <code>.bss</code> onde ficam os dados não-inicializados</p>
</li>
<li>
<p><code>0x403000</code>: program break, que é onde termina a seção de dados e começa o nosso "heap"</p>
</li>
</ul>
<p>Com isto, a partir do endereço <code>0x403000</code> é onde vamos colocar os elementos do nosso array, pelo que o endereço do array pode utilizar apenas um byte, que aponta para o endereço onde começa o primeiro elemento no heap.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mkuui4ot8ta2ohpf05bx.png" alt="array no heap" /></p>
<p>Na syscall que fizemos, se o argumento em RDI tiver zero, significa que brk vai retornar o program break atual, no caso <code>0x403000</code>. Mas podemos fazer mais syscalls brk com o argumento RDI diferente (incrementado), sinalizando que estamos mudando o program break.</p>
<p>A partir de agora, na seção de dados <code>.bss</code>, não precisamos mais reservar 4 bytes para o array, pelo que é necessário apenas 1 byte que irá representar o endereço de memória do array no heap:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

; inicialmente começa com <span class="constant numeric actionscript 2">0x000000</span>, mas depois irá conter 
; o endereço <span class="constant numeric actionscript 2">0x403000</span>
section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">1</span>  

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

...
...
</span></code></pre>
<p>Ao analisarmos com gdb:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na primeira syscall</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 18</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Executa a linha da syscall</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Em RAX a syscall armazena o endereço do program break, no caso</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x403000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rax</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x403000            4206592</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       Cannot access memory at address 0x403000</span>
</span></code></pre>
<p>Neste momento, este endereço ainda não é acessível pois não reservamos novos bytes no heap. Vamos andar com a próxima syscall:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Antes de executar a syscall, verificamos que o argumento RDI vai </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> conter o endereço desejado para o novo program break, no caso com</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 3 bytes adicionados, 0x403003</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdi</span>
<span class="meta function-call shell"><span class="variable function shell">rdi</span></span><span class="meta function-call arguments shell">            0x403003            4206595</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Executa a syscall...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Após a execução da segunda syscall, vemos que em RAX, o program break foi alterado para 0x403003</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rax</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x403003            4206595</span>
</span></code></pre>
<p>Agora, podemos acessar os endereços de memória entre <code>0x403000</code> e <code>0x403003</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       0x00000000</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403001</span>
<span class="meta function-call shell"><span class="variable function shell">0x403001:</span></span><span class="meta function-call arguments shell">       0x00000000</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403002</span>
<span class="meta function-call shell"><span class="variable function shell">0x403002:</span></span><span class="meta function-call arguments shell">       0x00000000</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403003</span>
<span class="meta function-call shell"><span class="variable function shell">0x403003:</span></span><span class="meta function-call arguments shell">       0x00000000</span>
</span></code></pre>
<p><em>Uau!</em> Agora temos no heap uma área reservada especialmente para o nosso querido array, olha que coisa!</p>
<p>Como vamos manipular o array nesta região da memória?</p>
<h3 id="ponteiros-ponteiros-everywhere">Ponteiros, ponteiros everywhere</h3>
<p>Após a primeira syscall, devemos pegar o endereço de memória <code>0x403000</code> que representa o primeiro program break e armazenar no ponteiro do array que está em <code>.bss</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">...
mov rdi, <span class="constant numeric actionscript 2">0</span>
mov rax, SYS_brk
syscall
mov [array], rax      ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> breakpoint aqui

mov rdi, rax
<span class="support function actionscript 2">add</span> rdi, CAPACITY
mov rax, SYS_brk
syscall
...
</span></code></pre>
<p>Vamos verificar com gdb o breakpoint na linha que muda o ponteiro do array:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 19</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00000000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Executa a linha que muda o ponteiro</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> n</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Agora o ponteiro aponta para o endereço 0x403000, </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> é isto o que queremos</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00403000</span>
</span></code></pre>
<p><em>Importante notar</em> que <strong>array</strong> está no endereço <code>0x402004</code>, na seção <code>.bss</code>, pelo que seu valor representa outro endereço de memória <code>0x403000</code> que é onde deve começar o primeiro elemento do array no heap.</p>
<p>Agora, quando fizermos a próxima syscall para alocar 3 bytes no heap, o program break será modificado e iremos conseguir manipular o array pois o ponteiro já aponta para o endereço correto.</p>
<p>Após a segunda syscall, já não podemos mais manipular o <code>array</code> pelo seu valor, pois agora o valor do array já não é mais um elemento de fato, mas sim um endereço para outro lugar na memória.</p>
<p>Vamos ao programa na versão atual:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">1</span>   ; <span class="constant numeric actionscript 2">0x403000</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall
	mov [array], rax

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

	mov rbx, [array]

	mov r8, <span class="constant numeric actionscript 2">1</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">2</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">3</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">4</span>
	<span class="support function actionscript 2">call</span> .append
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; verifica se o array está cheio
	je .done

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
</span></code></pre>
<p>Explicando cada bloco:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov rdi, <span class="constant numeric actionscript 2">0</span>
mov rax, SYS_brk
syscall
mov [array], rax
</span></code></pre>
<ul>
<li>busca o program break atual e armazena o endereço no ponteiro <code>array</code></li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov rdi, rax
<span class="support function actionscript 2">add</span> rdi, CAPACITY
mov rax, SYS_brk
syscall
</span></code></pre>
<ul>
<li>modifica o program break atual, incrementando 3 bytes que é a capacidade inicial do array no heap</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; atribuir ao registrador o endereço de memória ao qual o
; ponteiro <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>array<span class="punctuation definition string end actionscript 2">&quot;</span></span> está apontando
mov rbx, [array] 
</span></code></pre>
<ul>
<li>armazena o endereço de memória do ponteiro no registrador RBX. Isto é necessário pois não queremos fazer aritmética diretamente no ponteiro da seção <code>.bss</code>, mas sim através de um registrador que permite</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov r8, <span class="constant numeric actionscript 2">1</span>
<span class="support function actionscript 2">call</span> .append
</span></code></pre>
<ul>
<li>como agora o RDI foi usado como argumento na syscall brk, não convém mais utilizarmos este registrador para representar o elemento a ser adicionado no array, pelo que trocamos pelo registrador R8</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; verifica se o array está cheio
	je .done

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b    ; indirect<span class="keyword operator symbolic actionscript 2">-</span><span class="support function actionscript 2">mode</span> addressing
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
</span></code></pre>
<p>Agora a rotina <code>.append</code> foi modificado para que a manipulação do array no heap seja através do registrador RBX. Também não podemos mais usar o registrador RAX para representar o ponteiro pois a syscall brk também utilizou como retorno do program break; neste caso trocamos para o RSI (que tem o SIL como sua representação de 8-bits menores).</p>
<p>Ao executar com gdb, podemos verificar que os elementos estão sendo adicionados no endereço <code>0x403000</code> que fica no heap, através do ponteiro que foi armazenado no registrador RBX:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Array aponta para o endereço 0x403000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">array</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>array<span class="keyword operator assignment redirection shell">&gt;</span>:       0x00403000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> No endereço, temos os elementos adicionados. Yay!</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       0x00030201</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> E o ponteiro de &quot;índice&quot; corretamente representando o fim do array no heap</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">pointer</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>pointer<span class="keyword operator assignment redirection shell">&gt;</span>:     0x00000003</span>
</span></code></pre>
<p>Neste momento, o programa está com o mesmo comportamento do exemplo anterior com array estático em <code>.bss</code>, não permitindo adicionar mais elementos quando o array atinge seu limite.</p>
<p>Vamos mudar isto, redimensionando o array e permitir que novos elementos sejam adicionados.</p>
<h3 id="resize-com-brk">Resize com brk</h3>
<p>A seguir, iniciamos os passos para que o redimensionamento do array seja feito quando <strong>este atingir o limite da capacidade</strong>. Começamos por alterar a rotina <code>.append</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; verifica se o array está cheio
	je .<span class="support function actionscript 2">resize</span>

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
.<span class="support function actionscript 2">resize</span><span class="keyword operator symbolic actionscript 2">:</span>
	...
</span></code></pre>
<p>Ao invés de fazer jump para <code>.done</code> quando o array estiver cheio, fazemos jump para outra sub-rotina chamada <code>.resize</code>, que deverá fazer a syscall brk novamente, modificando assim o <strong>program break</strong> em uma nova área na memória, obedecendo a capacidade inicial do array:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.append<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [pointer], CAPACITY ; verifica se o array está cheio
	je .<span class="support function actionscript 2">resize</span>

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
.<span class="support function actionscript 2">resize</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall

	mov rdi, rax            ; RDI passa a representar o <span class="keyword control actionscript 2">break</span> atual
	<span class="support function actionscript 2">add</span> rdi, CAPACITY       ; adiciona <span class="constant numeric actionscript 2">3</span> bytes, ficando <span class="constant numeric actionscript 2">0x403006</span>
	mov rax, SYS_brk
	syscall
	jmp .append
</span></code></pre>
<ul>
<li>
<p>a primeira syscall de resize traz o break atual, no caso já sabemos que é <code>0x403003</code>, que foi alocado no início do programa para o array</p>
</li>
<li>
<p>a segunda syscall de resize modifica o break atual, alocando assim mais 3 bytes no heap</p>
</li>
<li>
<p>ao fim do resize, ao invés de retornar a função, vamos voltar para o início do <code>.append</code> e executar a lógica necessária para adicionar o elemento no array</p>
</li>
</ul>
<p>Desta forma, podemos manipular esta nova área na memória para adicionar mais elementos no array, modificando assim sua capacidade dinamicamente.</p>
<p>Se executarmos o programa exatamente assim, vamos enfrentar um problema, pois:</p>
<ul>
<li>
<p>a cada vez que é feito o resize, salta para o início da rotina</p>
</li>
<li>
<p>é verificado o tamanho do array (pointeiro) com a capacidade inicial, que no caso é 3. Como o ponteiro atingiu o valor 3, então vai entrar novamente no resize caracterizando assim um loop infinito com resize infinito até acabar a memória</p>
</li>
</ul>
<p>Para resolver isto, precisamos comparar o pointer com a capacidade atual (modificada), e portanto vamos adicionar um valor na seção <code>.data</code> que representa a capacidade atual:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>
currentCapacity<span class="keyword operator symbolic actionscript 2">:</span> db CAPACITY ; começa com <span class="constant numeric actionscript 2">3</span>
</span></code></pre>
<p>Na rotina <code>.append</code>, vamos fazer a comparação com o <code>currentCapacity</code>, que vai ser modificado a cada resize, ao invés de ser com <code>CAPACITY</code>, que vai permanecer fixo com o valor inicial enquanto durar o programa.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.append<span class="keyword operator symbolic actionscript 2">:</span>
	mov r9, [currentCapacity]
	cmp byte [pointer], r9b     ; verifica se o array está cheio
	je .<span class="support function actionscript 2">resize</span>
...
</span></code></pre>
<p>E, após o redimensionamento antes de voltar pro <code>.append</code>, vamos incrementar o valor da capacidade inicial à capacidade atual:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">resize</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

	mov r10, currentCapacity
	<span class="support function actionscript 2">add</span> byte [r10], CAPACITY
	jmp .append
</span></code></pre>
<p>Ao executar o programa, podemos ver que o elemento 4 foi adicionado com sucesso no array após o redimensionamento:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       0x04030201</span>
</span></code></pre>
<p>E se adicionarmos mais e mais elementos?</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">...
	mov r8, <span class="constant numeric actionscript 2">4</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">5</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">6</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">7</span>
	<span class="support function actionscript 2">call</span> .append
...
</span></code></pre><pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Podemos ver que o currentCapacity é 9, ou seja, foram feitos </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 2 redimensionamentos. Nosso array consegue agora acomodar até 9 elementos, </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> pelo que ao adicionar o décimo elemento, mais um resize seria feito.</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">currentCapacity</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402001</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>currentCapacity<span class="keyword operator assignment redirection shell">&gt;</span>:     0x09</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Buscando os 9 primeiros hexabytes no endereço do array no heap</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/9xb  0x403000</span>
<span class="meta function-call shell"><span class="variable function shell">0x403000:</span></span><span class="meta function-call arguments shell">       0x01    0x02    0x03    0x04    0x05    0x06    0x07    0x00</span>
<span class="meta function-call shell"><span class="variable function shell">0x403008:</span></span><span class="meta function-call arguments shell">       0x00</span>
</span></code></pre>
<p><em>How cool is that?</em></p>
<hr />
<h2 id="o-programa-final">O programa final</h2>
<p>A seguir o programa final, com um array de capacidade inicial de 3 elementos no heap que pode ser redimensionado utilizando a syscall <code>brk</code>, conforme mais elementos vão sendo adicionados no array:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_SUCCESS <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CAPACITY <span class="constant numeric actionscript 2">3</span>

section .bss
array<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
pointer<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>
currentCapacity<span class="keyword operator symbolic actionscript 2">:</span> db CAPACITY ; capacidade inicial é <span class="constant numeric actionscript 2">3</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall
	mov [array], rax

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

	mov rbx, [array]

	mov r8, <span class="constant numeric actionscript 2">1</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">2</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">3</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">4</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">5</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">6</span>
	<span class="support function actionscript 2">call</span> .append

	mov r8, <span class="constant numeric actionscript 2">7</span>
	<span class="support function actionscript 2">call</span> .append
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, EXIT_SUCCESS
	mov rax, SYS_exit
	syscall
.append<span class="keyword operator symbolic actionscript 2">:</span>
	mov r9, [currentCapacity]
	cmp byte [pointer], r9b ; verifica se o array está cheio
	je .<span class="support function actionscript 2">resize</span>

	mov sil, byte [pointer]
	mov byte [rbx <span class="keyword operator symbolic actionscript 2">+</span> rsi], r8b
	inc byte [pointer]
.done<span class="keyword operator symbolic actionscript 2">:</span>
	ret
.<span class="support function actionscript 2">resize</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CAPACITY
	mov rax, SYS_brk
	syscall

	mov r10, currentCapacity
	<span class="support function actionscript 2">add</span> byte [r10], CAPACITY
	jmp .append
</span></code></pre>
<hr />
<h2 id="conclusão">Conclusão</h2>
<p>Neste artigo, mostramos a implementação de um array em Assembly x86, passando por conceitos importantes como layout de memória, manipulação de registradores e alocação dinâmica de memória com <code>brk</code>.</p>
<p>Este artigo é base para artigos futuros sobre estruturas de dados, onde pretendo escrever sobre a implementação de filas e posteriormente listas ligadas.</p>
<p><em>Stay tuned!</em></p>
<hr />
<h2 id="referências">Referências</h2><sub>
Addressing modes
https://www.tutorialspoint.com/assembly_programming/assembly_addressing_modes.htm
Syscall brk
https://man7.org/linux/man-pages/man2/brk.2.html
ASCII table
https://www.asciicharstable.com/_site_media/ascii/ascii-chars-table-landscape.jpg
</sub>
]]></description>
<pubDate>2024-08-17</pubDate>
</item>
<item>
<title>Construindo um web server em Assembly x86, the grand finale, multi-threading</title>
<link>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-the-grand-finale-multi-threading-24hp.html</link>
<guid>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-the-grand-finale-multi-threading-24hp.html</guid>
<description><![CDATA[<p>Uma vez que temos um <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-v-finalmente-o-server-9e5">web server funcional</a>, podemos dar o próximo (e último) passo, que é deixar o servidor <strong>minimamente escalável</strong> fazendo uso de uma pool de threads.</p>
<p>Neste artigo, vamos mergulhar nas entranhas da implementação de uma pool de threads com sincronização através de locks, e para atingir tal feito em assembly abordaremos filas, alocação dinâmica de memória e controle de locks com futex.</p>
<p>Ao fim deste artigo, que é o último da saga, teremos uma visão mais holística sobre como funciona um web server e como uma pool de threads poderia ser implementada em linguagens de baixo nível.</p>
<p>Respira e vem comigo, esta última parte será uma avalanche de conceitos.</p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#simulando-a-lat%C3%AAncia-com-nanosleep">Simulando a latência com nanosleep</a></p>
</li>
<li>
<p><a href="#simulando-requests-em-escala-com-xargs">Simulando requests em escala com xargs</a></p>
</li>
<li>
<p><a href="#concorr%C3%AAncia-com-forking-de-processos">Concorrência com forking de processos</a></p>
</li>
<li>
<p><a href="#concorr%C3%AAncia-com-clone-de-processo">Concorrência com clone de processo</a></p>
</li>
<li>
<p><a href="#concorr%C3%AAncia-com-threads">Concorrência com threads</a></p>
<ul>
<li><a href="#entendendo-a-cria%C3%A7%C3%A3o-de-uma-thread">Entendendo a criação de uma thread</a></li>
<li><a href="#thread-flags">Thread flags</a></li>
<li><a href="#aloca%C3%A7%C3%A3o-de-mem%C3%B3ria-com-brk">Alocação de memória com brk</a></li>
<li><a href="#modificando-o-server-para-suportar-multi--threading">Modificando o server para suportar multi-threading</a></li>
</ul>
</li>
<li>
<p><a href="#concorr%C3%AAncia-com-thread-pool">Concorrência com thread pool</a></p>
<ul>
<li><a href="#uma-thread-em-loop">Uma thread em loop</a></li>
<li><a href="#5-threads-em-loop">5 threads em loop</a></li>
<li><a href="#sincroniza%C3%A7%C3%A3o-com-futex">Sincronização com futex</a></li>
</ul>
</li>
<li>
<p><a href="#aloca%C3%A7%C3%A3o-de-mem%C3%B3ria-com-mmap">Alocação de memória com mmap</a></p>
</li>
<li>
<p><a href="#conclus%C3%A3o">Conclusão</a></p>
</li>
<li>
<p><a href="#refer%C3%AAncias">Referências</a></p>
</li>
</ul>
<hr />
<h2 id="simulando-a-latência-com-nanosleep">Simulando a latência com nanosleep</h2>
<p>Quando uma requisição é feita a um web server, o tempo de resposta total é um somatório de toda a latência envolvida na comunicação, desde o momento em que o pedido sai da origem (client), passando pela rede de computadores (internet), chegando no destino (server), <strong>sendo processado</strong>, para então a resposta fazer o caminho inverso até voltar ao client.</p>
<p>Quanto maior a latência em qualquer parte do processo, maior o tempo de resposta, e portanto menor a capacidade de entregar respostas de diferentes requisições em um determinado intervalo de tempo.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/89cfxfykz32gd02sdjci.png" alt="server-database" /></p>
<blockquote>
<p>A esta capacidade de processar requisições em um intervalo de tempo chamamos de <strong>throughput</strong>. O que queremos no fim das contas é <em>aumentar o throughput sem comprometer a latência</em>. Esta é uma das premissas para sistemas escaláveis, mas o foco deste artigo não será em escalabilidade necessariamente.</p>
</blockquote>
<p>No artigo anterior, finalizamos o web server que apenas responde no socket uma mensagem HTML contendo "Hello, world". A seguir o código inicial do server, que será a base para o restante do artigo:</p>
<pre><code class="sourceCode language-asm"><span class="text plain">global _start

%define SYS_socket 41
%define SYS_bind 49
%define SYS_listen 50
%define SYS_accept4 288
%define SYS_write 1
%define SYS_close 3

%define AF_INET 2
%define SOCK_STREAM 1
%define SOCK_PROTOCOL 0
%define BACKLOG 2
%define CR 0xD
%define LF 0xA

section .data
sockaddr:
	sa_family: dw AF_INET   ; 2 bytes
	port: dw 0xB80B         ; 2 bytes
	ip_addr: dd 0           ; 4 bytes
	sin_zero: dq 0          ; 8 bytes
response: 
	headline: db &quot;HTTP/1.1 200 OK&quot;, CR, LF
	content_type: db &quot;Content-Type: text/html&quot;, CR, LF
	content_length: db &quot;Content-Length: 22&quot;, CR, LF
	crlf: db CR, LF
	body: db &quot;&lt;h1&gt;Hello, World!&lt;/h1&gt;&quot;
responseLen: equ $ - response

section .bss
sockfd: resb 1

section .text
_start:
.socket:
	; int socket(int domain, int type, int protocol)
	mov rdi, AF_INET
	mov rsi, SOCK_STREAM
	mov rdx, SOCK_PROTOCOL
	mov rax, SYS_socket
	syscall
.bind:
	mov [sockfd], rax
	; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
	mov rdi, [sockfd]
	mov rsi, sockaddr
	mov rdx, 16
	mov rax, SYS_bind
	syscall
.listen:
	; int listen(int sockfd, int backlog)
	mov rdi, [sockfd]
	mov rsi, BACKLOG
	mov rax, SYS_listen
	syscall
.accept:
	; int accept(int sockfd, struct *addr, int addrlen, int flags)
	mov rdi, [sockfd]
	mov rsi, 0
	mov rdx, 0
	mov r10, 0
	mov rax, SYS_accept4
	syscall
	mov r8, rax
	call handle
	jmp .accept
handle:
	; int write(fd)
	mov rdi, r8
	mov rsi, response
	mov rdx, responseLen
	mov rax, SYS_write
	syscall

	; int close(fd)
	mov rdi, r8
	mov rax, SYS_close
	syscall
	ret
</span></code></pre>
<p>Até aqui tudo normal. A rotina <code>accept</code> fica em loop chamando a rotina <code>handle</code> que escreve "Hello, world" na resposta de cada requisição que chega no socket.</p>
<p>Com <em>strace</em>, podemos ver as chamadas que foram feitas após uma requisição com <em>curl</em>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">listen</span></span><span class="meta function-call arguments shell">(3, 2</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                            <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">close</span></span><span class="meta function-call arguments shell">(4</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span>
</span></code></pre>
<blockquote>
<p><strong>socket</strong>, bind, listen, para então iniciar o <strong>accept</strong>, que ao receber uma requisição HTTP, passa para <strong>write</strong>, <strong>close</strong> e então voltar ao <strong>accept</strong> novamente em loop.</p>
</blockquote>
<p>Para simular um pouco de latência, vamos fazer com que a resposta demore cerca de 1 segundo, e para tanto precisamos utilizar uma syscall no Linux chamada <code>nanosleep</code>, que suspende a execução da thread atual até atingir um tempo decorrido especificado com base no relógio monotônico do sistema:</p>
<p>Primeiro definimos a syscall, que tem o código 35:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_nanosleep <span class="constant numeric actionscript 2">35</span>
</span></code></pre>
<p>Na rotina <code>handle</code>, antes de escrever a resposta no socket, fazemos a chamada de sistema para <strong>nanosleep</strong> passando como argumento uma struct que representa um <em>timespec</em>, que contempla o tempo decorrido em segundos e nano-segundos:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">handle<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> nanosleep(timespec <span class="support function actionscript 2">duration</span>)
	lea rdi, [timespec]
	mov rax, SYS_nanosleep
	syscall

	; <span class="support function actionscript 2">int</span> write(fd)
	...

	; <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">close</span>(fd)
	...
</span></code></pre>
<p>E na seção de dados, definimos o tempo decorrido em segundos, que são os primeiros 8 bytes da struct, deixando a <em>zero</em> os 8 bytes restantes que representam o tempo em nano-segundos</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
timespec<span class="keyword operator symbolic actionscript 2">:</span>
	tv_sec<span class="keyword operator symbolic actionscript 2">:</span> dq <span class="constant numeric actionscript 2">1</span>
	tv_nsec<span class="keyword operator symbolic actionscript 2">:</span> dq <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<blockquote>
<p>Neste exemplo queremos que o sleep seja de 1 segundo</p>
</blockquote>
<p>Com <em>strace</em>, podemos ver que a syscall <code>nanosleep</code> foi executada após o <strong>accept</strong> e antes do <strong>write</strong>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">listen</span></span><span class="meta function-call arguments shell">(3, 2</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                            <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>

<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">nanosleep</span></span><span class="meta function-call arguments shell">(<span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>tv_sec=1<span class="punctuation separator shell">,</span> tv_nsec=0<span class="punctuation section expansion brace end shell">}</span></span>, NULL</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>  <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>

<span class="meta function-call shell"><span class="variable function shell">close</span></span><span class="meta function-call arguments shell">(4</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span>
</span></code></pre>
<p>Calculando o tempo decorrido com o utilitário <code>time</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> time curl localhost:3000</span>

<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">real</span></span><span class="meta function-call arguments shell">    0m1.040s</span>
<span class="meta function-call shell"><span class="variable function shell">user</span></span><span class="meta function-call arguments shell">    0m0.005s</span>
<span class="meta function-call shell"><span class="variable function shell">sys</span></span><span class="meta function-call arguments shell">     0m0.009s</span>
</span></code></pre>
<p>Podemos também encurtar a resposta do time trazendo apenas o tempo real, exportando a variável na sessão shell atual ou adicionando no <code>bashrc</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="storage modifier shell">export</span> <span class="variable other readwrite assignment shell">TIMEFORMAT</span><span class="keyword operator assignment shell">=</span><span class="string unquoted shell"><span class="meta group expansion job shell"><span class="punctuation definition variable job shell">%</span><span class="variable other readwrite shell">R</span></span></span></span>

<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> time curl localhost:3000</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.036</span>
</span></code></pre>
<p><em>Yay!</em> Já conseguimos simular uma latência de 1 segundo em Assembly. Agora vamos ver se nosso web server tem a capacidade de atender a <strong>requests em escala</strong>.</p>
<hr />
<h2 id="simulando-requests-em-escala-com-xargs">Simulando requests em escala com xargs</h2>
<p>Para começar, vamos simular 10 requests sequenciais com curl. Poderíamos ficar digitando <code>curl localhost:3000</code> 10 vezes, ou então ser pragmáticos, automatizar sem reinventar a roda e nem instalar nada adicional no sistema.</p>
<blockquote>
<p>Como?</p>
</blockquote>
<p><em>xargs.</em></p>
<p><strong>xargs</strong> é um utilitário presente na maioria dos sistemas operacionais UNIX-like, que lê strings a partir de arquivos ou standard input e utiliza estas strings como argumentos para comandos arbitrários.</p>
<p>Vamos ter como exemplo uma sequência de 1 a 10 em bash:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> echo <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="punctuation section expansion parameter begin shell">{</span></span><span class="meta group expansion parameter shell"><span class="variable other readwrite shell">1..10</span></span><span class="meta group expansion parameter shell"><span class="punctuation section expansion parameter end shell">}</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">1</span></span><span class="meta function-call arguments shell"> 2 3 4 5 6 7 8 9 10</span>
</span></code></pre>
<p>Podemos utilizar cada valor do <strong>echo</strong> como argumento para o xargs:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> echo <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>1..10<span class="punctuation section expansion brace end shell">}</span></span></span> <span class="keyword operator logical pipe shell">|</span> <span class="meta function-call shell"><span class="variable function shell">xargs</span></span><span class="meta function-call arguments shell"><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>n1</span></span>
<span class="meta function-call shell"><span class="variable function shell">1</span></span>
<span class="meta function-call shell"><span class="variable function shell">2</span></span>
<span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">5</span></span>
<span class="meta function-call shell"><span class="variable function shell">6</span></span>
<span class="meta function-call shell"><span class="variable function shell">7</span></span>
<span class="meta function-call shell"><span class="variable function shell">8</span></span>
<span class="meta function-call shell"><span class="variable function shell">9</span></span>
<span class="meta function-call shell"><span class="variable function shell">10</span></span>
</span></code></pre>
<p>A opção <code>-n1</code> significa a quantidade de argumentos que serão usados para o comando que vem a seguir ao xargs, que no caso queremos apenas 1 argumento, o que neste caso tanto faz pois não queremos fazer nada com o argumento: queremos apenas executar o comando <strong>curl</strong> 10 vezes.</p>
<p>Podemos então agora executar o <strong>curl</strong> com o time para saber o tempo decorrido de cada request:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> time echo <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>1..10<span class="punctuation section expansion brace end shell">}</span></span></span> <span class="keyword operator logical pipe shell">|</span> <span class="meta function-call shell"><span class="variable function shell">xargs</span></span><span class="meta function-call arguments shell"><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>n1</span> bash<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>c</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>time curl localhost:3000<span class="punctuation definition string end shell">&quot;</span></span></span>

<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.037</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.033</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.025</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.037</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.032</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.026</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.019</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.046</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.053</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.041</span>
<span class="meta function-call shell"><span class="variable function shell">10.426</span></span>
</span></code></pre>
<p>Claramente, vemos que cada request demorou cerca de 1 segundo, o que no total o tempo decorrido foi de <strong>10,4</strong> segundos. Esta é a latência total para o caso de fazermos requisições sequenciais.</p>
<p>E se fizermos <strong>requisições simultâneas</strong>? Num cenário mais próximo do real, vamos supor que nossa aplicação web recebe 10 requisições no mesmo segundo em horários de pico.</p>
<p>Para isto, conseguimos também utilizar o <strong>xargs</strong> para simular, através da opção <code>-P</code>, que representa a quantidade de processos simultâneos que o xargs irá utilizar para realizar os comandos.</p>
<blockquote>
<p>Incrível! Com isto nosso web server atende 10 requisições simultâneas, fazendo com que o throughput total dos 10 requests fique em torno de 1 segundo, certo?</p>
</blockquote>
<p><em>Calma, calabreso</em>, vamos testar.</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> time echo <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>1..10<span class="punctuation section expansion brace end shell">}</span></span></span> <span class="keyword operator logical pipe shell">|</span> <span class="meta function-call shell"><span class="variable function shell">xargs</span></span><span class="meta function-call arguments shell"><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>n1</span><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>P10</span> bash<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>c</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>time curl localhost:3000<span class="punctuation definition string end shell">&quot;</span></span></span>

<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.053</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.071</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">3</span>.076</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">4</span>.087</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">5</span>.088</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">6</span>.106</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">7</span>.140</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">8</span>.154</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">9</span>.168</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">10</span>.183</span>
<span class="meta function-call shell"><span class="variable function shell">10.214</span></span>
</span></code></pre>
<p><strong>Não melhorou nada!</strong> Ter 10 requests simultâneos não quer dizer que nosso server consiga atender os 10 requests ao mesmo tempo. Muito pelo contrário, pode até piorar e prejudicar a latência total, pois há diversos requests na fila esperando para serem atendidos.</p>
<ul>
<li>
<p>o primeiro request demora 1 segundo</p>
</li>
<li>
<p>o segundo request chega ao mesmo tempo mas demora 2 segundos</p>
</li>
<li>
<p>o terceiro request chega ao mesmo tempo mas demora 3 segundos</p>
</li>
<li>
<p>e assim sucessivamente...</p>
</li>
</ul>
<p>Nosso server é síncrono, e com isto podemos criar gargalos. Precisamos então que o server consiga lidar com <strong>concorrência</strong>.</p>
<hr />
<h2 id="concorrência-com-forking-de-processos">Concorrência com forking de processos</h2>
<p>Uma das formas primitivas de concorrência e escalar um web server para atender mais de um request em simultâneo é com o uso de <strong>processos</strong>. Como cada processo no sistema operacional tem sua <em>memória isolada</em> dos demais, podemos fazer com que cada request seja atendido em um processo diferente.</p>
<p>Para entender esta técnica, precisamos compreender que <em>todo programa de computador</em> roda em um <strong>processo</strong> no sistema operacional, e isto vimos bastante nos artigos anteriores. Dentro deste processo, o programa ainda roda em uma unidade de execução no SO chamada <strong>thread</strong>.</p>
<blockquote>
<p>Todo processo tem uma thread chamada <em>thread principal</em>, que é onde está sendo executado o programa</p>
</blockquote>
<p>No exemplo anterior, quando chamamos o <em>sleep</em>, a thread que está sendo suspensa por um tempo determinado é justamente a <strong>thread principal</strong> do programa.</p>
<p>A thread compartilha a memória do processo o qual ela faz parte, mas como precisamos criar <strong>outro processo</strong>, temos de fazer um <em>forking</em>, que basicamente <em>cria um processo filho copiando tudo</em> o que o programa principal tem.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fhz3hnrjktfwv33zqdpv.png" alt="forking de processos" /></p>
<p>Repare que cada processo filho tem uma cópia do processo principal. O loop é basicamente o <strong>accept</strong> do nosso web server, que fica em loop. Desta forma cada request pode ser atendido por um processo diferente, <strong>de forma concorrente</strong>.</p>
<p>Podemos fazer forking de processo com o uso da syscall <em>fork</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_fork <span class="constant numeric actionscript 2">57</span>
</span></code></pre>
<p>A rotina <em>handle</em> mantém igual, com o sleep antes de escrever a resposta no socket:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">handle<span class="keyword operator symbolic actionscript 2">:</span>
	lea rdi, [timespec]
	mov rax, SYS_nanosleep
	syscall

	; <span class="support function actionscript 2">int</span> write(fd)
	mov rdi, r8
	mov rsi, <span class="support function actionscript 2">response</span>
	mov rdx, responseLen
	mov rax, SYS_write
	syscall

	; <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">close</span>(fd)
	mov rdi, r8
	mov rax, SYS_close
	syscall
	ret
</span></code></pre>
<p>E na rotina <strong>accept</strong>, adicionamos a chamada do fork logo após o request chegar no socket:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.accept<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> accept(<span class="support function actionscript 2">int</span> sockfd, struct <span class="keyword operator symbolic actionscript 2">*</span>addr, <span class="support function actionscript 2">int</span> addrlen, <span class="support function actionscript 2">int</span> flags)
	mov rdi, [sockfd]
	mov rsi, <span class="constant numeric actionscript 2">0</span>
	mov rdx, <span class="constant numeric actionscript 2">0</span>
	mov r10, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_accept4
	syscall
	mov r8, rax

	; fork de processo
	mov rax, SYS_fork
	syscall

	; se o retorno <span class="keyword control actionscript 2">do</span> fork <span class="keyword control actionscript 2">for</span> ZERO, significa que está sendo executado
	; a partir <span class="keyword control actionscript 2">do</span> processo filho. Então a rotina <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>handle<span class="punctuation definition string end actionscript 2">&quot;</span></span> é executada
	<span class="support function actionscript 2">test</span> rax, rax
	jz handle

	; quando o retorno não é ZERO, significa que a execução <span class="keyword control actionscript 2">do</span> programa 
	; principal continuou. Então o processo principal volta para o loop
	jmp .accept
</span></code></pre>
<ul>
<li>
<p>depois de uma chamada ao <strong>fork</strong>, a syscall retorna ZERO quando se está dentro do processo filho. Neste caso, a execução do processo filho continua com a rotina <em>handle</em> e depois termina</p>
</li>
<li>
<p>após a chamada do fork, se o retorno NÃO for ZERO, significa que a execução é do programa principal, então neste caso volta-se ao loop para esperar um novo request no socket</p>
</li>
</ul>
<p>Ao executar com strace, podemos ver várias chamadas à syscall <em>fork</em>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">listen</span></span><span class="meta function-call arguments shell">(3, 2</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                            <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">fork</span></span><span class="meta function-call arguments shell">(strace: Process 12787 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                  <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">12787</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] accept4(3, NULL, NULL, 0 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12787] nanosleep(<span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>tv_sec=1<span class="punctuation separator shell">,</span> tv_nsec=0<span class="punctuation section expansion brace end shell">}</span></span>,  <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] <span class="keyword operator assignment redirection shell">&lt;</span>... accept4 resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>      <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">5</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] fork(strace: Process 12788 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                      <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">12788</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12788] nanosleep(<span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>tv_sec=1<span class="punctuation separator shell">,</span> tv_nsec=0<span class="punctuation section expansion brace end shell">}</span></span>,  <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] accept4(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">6</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] fork(strace: Process 12789 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                      <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">12789</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] accept4(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">7</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] fork( <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12789] nanosleep(<span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>tv_sec=1<span class="punctuation separator shell">,</span> tv_nsec=0<span class="punctuation section expansion brace end shell">}</span></span>, strace: Process 12790 attached</span>
 <span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] <span class="keyword operator assignment redirection shell">&lt;</span>... fork resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>         <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">12790</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12790] nanosleep(<span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>tv_sec=1<span class="punctuation separator shell">,</span> tv_nsec=0<span class="punctuation section expansion brace end shell">}</span></span>,  <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] accept4(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">8</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 12786] fork(strace: Process 12791 attached</span>
</span></code></pre>
<p>E os tempos de resposta para 10 requests simultâneos:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> time echo <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>1..10<span class="punctuation section expansion brace end shell">}</span></span></span> <span class="keyword operator logical pipe shell">|</span> <span class="meta function-call shell"><span class="variable function shell">xargs</span></span><span class="meta function-call arguments shell"><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>n1</span><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>P10</span> bash<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>c</span> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>time curl localhost:3000<span class="punctuation definition string end shell">&quot;</span></span></span>

<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.049</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.051</span>
<span class="meta function-call shell"><span class="variable function shell">1.053</span></span>
<span class="meta function-call shell"><span class="variable function shell">1.052</span></span>
<span class="meta function-call shell"><span class="variable function shell">1.055</span></span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.051</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.052</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.056</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.106</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.116</span>
<span class="meta function-call shell"><span class="variable function shell">2.138</span></span>
</span></code></pre>
<p>Yay! Podemos ver que os requests são atendidos de forma concorrente, e que o tempo total ficou em <strong>2,1 segundos</strong> para 10 requests simultâneos!</p>
<blockquote>
<p>Lembrando que, quando estamos lidando com concorrência, não temos controle da ordem de execução dos processos, que são escalonados pelo sistema operacional. Esta preempção de processos pode fazer com que um request que chegou depois seja atendido primeiro. É uma das características de <em>race condition</em> e é por isso que vemos os requests chegando fora de ordem.</p>
</blockquote>
<p>Mas no nosso caso não importa. Cada request é único e não depende do anterior.</p>
<hr />
<h2 id="concorrência-com-clone-de-processo">Concorrência com clone de processo</h2>
<p>Outra forma muito similar à chamada <em>fork</em> é através da syscall <strong>clone</strong>, que basicamente clona um processo, tal como fizemos no exemplo anterior, garantindo isolamento e concorrência.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_clone <span class="constant numeric actionscript 2">56</span>
</span></code></pre>
<p>E a diferença é que chamamos a syscall de clone, ao invés da syscall fork:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.accept<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> accept(<span class="support function actionscript 2">int</span> sockfd, struct <span class="keyword operator symbolic actionscript 2">*</span>addr, <span class="support function actionscript 2">int</span> addrlen, <span class="support function actionscript 2">int</span> flags)
	mov rdi, [sockfd]
	mov rsi, <span class="constant numeric actionscript 2">0</span>
	mov rdx, <span class="constant numeric actionscript 2">0</span>
	mov r10, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_accept4
	syscall
	mov r8, rax

	; chamada à syscall <span class="support function actionscript 2">clone</span>
	; com argumentos a ZERO, significa que será feito um <span class="support function actionscript 2">clone</span> <span class="keyword control actionscript 2">do</span> processo
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rsi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_clone
	syscall

	; se o retorno <span class="keyword control actionscript 2">for</span> zero, execução é a partir <span class="keyword control actionscript 2">do</span> processo filho
	<span class="support function actionscript 2">test</span> rax, rax
	jz handle

	; continuação da execução <span class="keyword control actionscript 2">do</span> processo principal
	jmp .accept
</span></code></pre>
<ul>
<li>depois de uma chamada ao <strong>clone</strong>, a syscall retorna ZERO quando se está dentro do processo filho. Neste caso, a execução do processo filho continua com a rotina <em>handle</em> e depois termina</li>
</ul>
<ul>
<li>após a chamada do clone, se o retorno NÃO for ZERO, significa que a execução é do programa principal, então neste caso volta-se ao loop para esperar um novo request no socket</li>
</ul>
<p>Executamos com strace e:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.062</span>
<span class="meta function-call shell"><span class="variable function shell">1.064</span></span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.063</span>
<span class="meta function-call shell"><span class="variable function shell">1.061</span></span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.071</span>
<span class="meta function-call shell"><span class="variable function shell">1.061</span></span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.059</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.069</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.135</span>
<span class="meta function-call shell"><span class="variable function shell">2.128</span></span>
<span class="meta function-call shell"><span class="variable function shell">2.148</span></span>
</span></code></pre>
<p>Ainda servindo 10 requests simultâneos <strong>perto dos 2 segundos</strong>! <em>Not bad</em>.</p>
<p>Entretanto, forking ou clone de processos leva a um <strong>gasto excessivo de memória</strong>, pois cada processo filho é exatamente uma cópia do processo principal. Se o principal tem 200MB de memória, com 4 forks teríamos um gasto total de 800MB de memória.</p>
<p>Chegou o momento de falarmos das <strong>threads</strong>.</p>
<hr />
<h2 id="concorrência-com-threads">Concorrência com threads</h2>
<p>Vamos relembrar o que falamos no início do artigo:</p>
<blockquote>
<p>Todo processo tem uma thread chamada <em>thread principal</em>, que é onde está sendo executado o programa</p>
</blockquote>
<p>Apesar de todo programa rodar dentro de uma thread, podemos também criar mais threads que <strong>compartilham a memória do mesmo processo</strong>, e para isto podemos fazer uso da mesma syscall <strong>clone</strong>, mas passando argumentos diferentes que tornam este clone uma <em>thread dentro do mesmo processo</em>, e não uma cópia inteira do processo.</p>
<p>Desta forma, ficamos sempre com UM processo mas atendendo requests em threads diferentes, <strong>gastando assim menos memória</strong> se comparado com forking de processos.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vszydp3du1ntg72xizmd.png" alt="threads" /></p>
<h3 id="entendendo-a-criação-de-uma-thread">Entendendo a criação de uma thread</h3>
<p>Antes de adaptarmos o código do server para utilizar threads, vamos dar um passo atrás e entender como se cria uma thread em Assembly.</p>
<p>Para criar uma thread, fazemos uso da syscall <strong>clone</strong>. De acordo com a <a href="https://man7.org/linux/man-pages/man2/clone.2.html">documentação</a>, a syscall clone cria um processo "filho", similar ao que fizemos no fork. Mas a diferença é que a syscall clone permite um maior controle sobre o que será compartilhado entre o processo principal e o processo filho.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_clone <span class="constant numeric actionscript 2">56</span>
</span></code></pre>
<p>Coisas que podem ser compartilhadas (ou não):</p>
<ul>
<li>
<p>espaço de endereço de memória virtual</p>
</li>
<li>
<p>tabela de descritores de arquivos</p>
</li>
<li>
<p>tabela de handlers de sinais</p>
</li>
<li>
<p>entre outros recursos...</p>
</li>
</ul>
<blockquote>
<p>No exemplo anterior utilizamos a syscall clone passando argumentos a ZERO, o que significa que não queríamos compartilhar nada entre os processos, portanto uma cópia seria feita como no forking de processos</p>
</blockquote>
<p>Para a execução da syscall, precisamos enviar 2 argumentos:</p>
<ul>
<li>
<p><strong>rdi</strong>: representa as <em>flags</em>, que modificam o comportamento do que será compartilhado com o processo filho (thread)</p>
</li>
<li>
<p><strong>rsi</strong>: ponteiro para a função que a thread irá executar, que precisa ser definido dentro de uma <strong>área reservada na memória</strong>, ou seja, precisamos alocar um novo bloco de memória para a thread poder colocar a função e seus argumentos</p>
</li>
</ul>
<p>Portanto, para criar uma thread, precisamos de <strong>thread flags</strong> e <strong>alocação de memória</strong>.</p>
<h3 id="thread-flags">Thread flags</h3>
<p>Em RDI, vamos passar as seguintes flags:</p>
<ul>
<li>
<p><strong>CLONE_VM</strong>: processo principal e processo filho compartilham o mesmo espaço de memória virtual</p>
</li>
<li>
<p><strong>CLONE_FS</strong>: processos compartilham o mesmo sistema de arquivos</p>
</li>
<li>
<p><strong>CLONE_FILES</strong>: processos compartilham a mesma tabela de descritor de arquivos (file descriptor table)</p>
</li>
<li>
<p><strong>CLONE_SIGHAND</strong>: processos compartilham a mesma tabela de handlers de sinais (signal handlers)</p>
</li>
<li>
<p><strong>CLONE_PARENT</strong>: processos compartilham o mesmo parent, ou seja, o processo "filho" na verdade é filho do processo parent do processo original (mesmo porque estamos falando de uma thread que compartilha o mesmo processo)</p>
</li>
<li>
<p><strong>CLONE_THREAD</strong>: o processo filho é colocado no mesmo grupo de threads do processo original</p>
</li>
<li>
<p><strong>CLONE_IO</strong>: processos compartilham o mesmo contexto de I/O</p>
</li>
</ul>
<blockquote>
<p>No fim das contas, estamos criando um processo "filho" mas que compartilha recursos com o processo principal. <strong>Este é o princípio da thread.</strong></p>
</blockquote>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov rdi, CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_PARENT|CLONE_THREAD|CLONE_IO
</span></code></pre><h3 id="alocação-de-memória-com-brk">Alocação de memória com brk</h3>
<p>Em RSI, precisamos indicar o ponteiro para a função na memória, neste caso o ponteiro da rotina <strong>handle</strong>, que tem a lógica de imprimir a mensagem  e etc. Mas aqui não basta indicar o ponteiro, mas sim em <strong>que região da memória</strong> do processo a thread irá armazenar a função, seus argumentos e variáveis locais.</p>
<blockquote>
<p>Cada thread precisa ter sua própria região na memória para armazenar a função e argumentos. É como se a thread tivesse uma área de "stack" só dela</p>
</blockquote>
<p>Para alocar memória, vamos relembrar como funciona o layout de um programa na memória:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/co0lxnlhbx2nz7uhx4k6.png" alt="layout de memória" /></p>
<p>Nos endereços de memória mais baixos, temos o programa, e a seguir temos os <em>dados estáticos</em> (data). No topo, que é onde ficam os endereços mais altos, temos a <em>stack</em>.</p>
<p>E no meio, o que temos <strong>a seguir a seção de dados</strong> é uma área enorme disponível na memória. A syscall <strong>brk</strong> permite mudar o ponto onde <em>termina a seção de dados</em>, também chamado de <strong>program break</strong>.</p>
<p>Podemos ficar mudando este break em direção aos endereços mais altos. Por exemplo, se chamarmos a syscall brk passando argumento ZERO, ela devolve o endereço de memória do program break, que é onde termina a seção de dados:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>

...

mov rdi, <span class="constant numeric actionscript 2">0</span>
mov rax, SYS_brk
syscall
</span></code></pre>
<p>O que temos em RAX é <code>0x403000</code>, que é exatamente o endereço de memória onde termina a seção de dados. Vamos modificar o break <strong>andando UM byte pra frente</strong>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov rdi, rax
<span class="support function actionscript 2">add</span> rdi, <span class="constant numeric actionscript 2">1</span>
mov rax, SYS_brk
syscall
</span></code></pre>
<p>Agora, RAX traz o endereço do novo program break, que é <code>0x403001</code>. Ou seja, agora podemos manipular este endereço de memória no nosso programa.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d32sk2d6w5eitngvri0y.png" alt="program break" /></p>
<blockquote>
<p>E o quê isto tem a ver com a thread?</p>
</blockquote>
<p>Podemos alocar <strong>uma quantidade arbitrária de bytes</strong> para a thread utilizar nesta área na memória. Como o break é sempre modificado, a próxima thread irá utilizar outra área de memória, e assim sucessivamente!</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bir1ll5slqqmsmhu7q25.png" alt="criação de threads" /></p>
<h3 id="um-hello-world-com-threads-em-assembly">Um "Hello, world" com threads em Assembly</h3>
<p>Vamos escrever um exemplo simples antes de ir para o web server. Primeiro, definimos as constantes, dentre elas as syscalls e as flags pra criação de threads:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_clone <span class="constant numeric actionscript 2">56</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>        
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>

<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CHILD_STACK_SIZE <span class="constant numeric actionscript 2">4096</span>

<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_VM <span class="constant numeric actionscript 2">0x00000100</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_FS <span class="constant numeric actionscript 2">0x00000200</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_FILES <span class="constant numeric actionscript 2">0x00000400</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_PARENT <span class="constant numeric actionscript 2">0x00008000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_THREAD <span class="constant numeric actionscript 2">0x00010000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_IO <span class="constant numeric actionscript 2">0x80000000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_SIGHAND <span class="constant numeric actionscript 2">0x00000800</span>
</span></code></pre>
<p>A seguir, na seção de dados, temos a mensagem "Hello, world" que a thread irá imprimir:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello<span class="punctuation definition string end actionscript 2">&quot;</span></span>
msgLen<span class="keyword operator symbolic actionscript 2">:</span> equ $ <span class="keyword operator symbolic actionscript 2">-</span> msg
</span></code></pre>
<p>Na seção <em>text</em>, o entrypoint do programa faz uma chamada à rotina da <em>thread</em> e a seguir termina:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">call</span> thread

	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
</span></code></pre>
<p>Agora, a definição da rotina <code>handle</code> que a thread irá executar:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">handle<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, msg
	mov rdx, msgLen
	mov rax, SYS_write
	syscall

	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
</span></code></pre>
<blockquote>
<p>A thread imprime a mensagem no STDOUT e termina. Sim, a thread precisa terminar, caso contrário o sistema emite um segmentation fault</p>
</blockquote>
<p>E por fim, vamos detalhar o processo da rotina da <em>thread</em> (explicação nos comentários do exemplo a seguir):</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">thread<span class="keyword operator symbolic actionscript 2">:</span>
	; Busca o <span class="keyword control actionscript 2">break</span> atual e guarda em RDX. Na primeira vez, o valor
	; é <span class="constant numeric actionscript 2">0x403000</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall
	mov rdx, rax

	; Modifica o <span class="keyword control actionscript 2">break</span> atual andando <span class="constant numeric actionscript 2">4096</span> bytes à frente.
	; Após esta chamada, o <span class="keyword control actionscript 2">break</span> passa a ser <span class="constant numeric actionscript 2">0x404000</span>
	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CHILD_STACK_SIZE
	mov rax, SYS_brk
	syscall

	; (<span class="constant numeric actionscript 2">1</span>) Thread flags<span class="keyword operator symbolic actionscript 2">:</span> como deve ser feito o compartilhamento de recursos
	; entre o processo principal e o processo filho
	mov rdi, CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_PARENT|CLONE_THREAD|CLONE_IO
	
	; (2a) Endereço de memória em RSI<span class="keyword operator symbolic actionscript 2">:</span> é o <span class="keyword control actionscript 2">break</span> atual <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">4096</span> bytes.
	; Retiramos também <span class="constant numeric actionscript 2">8</span> bytes para caber o ponteiro da função
	lea rsi, [rdx <span class="keyword operator symbolic actionscript 2">+</span> CHILD_STACK_SIZE <span class="keyword operator symbolic actionscript 2">-</span> <span class="constant numeric actionscript 2">8</span>]

	; (2b) No endereço em RSI colocamos o ponteiro da função <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>handle<span class="punctuation definition string end actionscript 2">&quot;</span></span>.
	; Como endereçamento em x86_64 é de <span class="constant numeric actionscript 2">8</span> bytes, é por isto
	; que no passo anterior fizemos [rdx <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">4096</span> <span class="keyword operator symbolic actionscript 2">-</span> <span class="constant numeric actionscript 2">8</span>]
	mov qword [rsi], handle
	mov rax, SYS_clone
	syscall
	ret
</span></code></pre>
<p>E pronto, ao executar o programa, temos a mensagem "Hello" na saída do programa que foi feita pela thread.</p>
<p>Caso o programa principal faça <code>call thread</code> 2 vezes, a próxima thread irá ter em RSI o break modificado, iniciando em <code>0x404000</code>.</p>
<h3 id="modificando-o-server-para-suportar-multi-threading">Modificando o server para suportar multi-threading</h3>
<p>Agora vamos trazer o código necessário para modificar o server:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_clone <span class="constant numeric actionscript 2">56</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
</span></code></pre>
<p>Thread flags:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define CHILD_STACK_SIZE <span class="constant numeric actionscript 2">4096</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_VM <span class="constant numeric actionscript 2">0x00000100</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_FS <span class="constant numeric actionscript 2">0x00000200</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_FILES <span class="constant numeric actionscript 2">0x00000400</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_PARENT <span class="constant numeric actionscript 2">0x00008000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_THREAD <span class="constant numeric actionscript 2">0x00010000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_IO <span class="constant numeric actionscript 2">0x80000000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_SIGHAND <span class="constant numeric actionscript 2">0x00000800</span>
</span></code></pre>
<p>Rotina <em>accept</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.accept<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> accept(<span class="support function actionscript 2">int</span> sockfd, struct <span class="keyword operator symbolic actionscript 2">*</span>addr, <span class="support function actionscript 2">int</span> addrlen, <span class="support function actionscript 2">int</span> flags)
	mov rdi, [sockfd]
	mov rsi, <span class="constant numeric actionscript 2">0</span>
	mov rdx, <span class="constant numeric actionscript 2">0</span>
	mov r10, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_accept4
	syscall
	mov r8, rax

	; Chamada da thread. Irá ser executada assincronamente tal como no
	; forking de processos, mas compartilhando a memória <span class="keyword control actionscript 2">do</span>
	; processo principal
	<span class="support function actionscript 2">call</span> thread

	; Processo principal volta para o loop
	jmp .accept
</span></code></pre>
<p>Definição da <em>thread</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">thread<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall
	mov rdx, rax

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CHILD_STACK_SIZE
	mov rax, SYS_brk
	syscall

	mov rdi, CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_PARENT|CLONE_THREAD|CLONE_IO
	lea rsi, [rdx <span class="keyword operator symbolic actionscript 2">+</span> CHILD_STACK_SIZE <span class="keyword operator symbolic actionscript 2">-</span> <span class="constant numeric actionscript 2">8</span>]
	mov qword [rsi], handle
	mov rax, SYS_clone
	syscall
	ret
</span></code></pre>
<blockquote>
<p>Aqui seguimos o mesmo padrão do exemplo anterior: aloca memória com brk e a seguir executa a syscall clone com as flags de compartilhamento de recursos</p>
</blockquote>
<p>E a lógica da rotina <em>handle</em> <strong>que será executada pela thread</strong>, que faz o <em>sleep</em>, a seguir escreve no socket a mensagem, fecha o socket da requisição e por fim termina sua execução:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">handle<span class="keyword operator symbolic actionscript 2">:</span>
	lea rdi, [timespec]
	mov rax, SYS_nanosleep
	syscall

	; <span class="support function actionscript 2">int</span> write(fd)
	mov rdi, r8
	mov rsi, <span class="support function actionscript 2">response</span>
	mov rdx, responseLen
	mov rax, SYS_write
	syscall

	; <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">close</span>(fd)
	mov rdi, r8
	mov rax, SYS_close
	syscall

	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
</span></code></pre>
<p>Com 1 chamada isolada, temos o seguinte output com strace:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">listen</span></span><span class="meta function-call arguments shell">(3, 2</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                            <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">brk</span></span><span class="meta function-call arguments shell">(NULL</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x9da000</span></span>
<span class="meta function-call shell"><span class="variable function shell">brk</span></span><span class="meta function-call arguments shell">(0x9db000</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                           <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x9db000</span></span>
<span class="meta function-call shell"><span class="variable function shell">clone</span></span><span class="meta function-call arguments shell">(child_stack=0x9daff8, flags=CLONE_VM</span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FS</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FILES</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_SIGHAND</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_PARENT</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_THREAD</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_IOstrace:</span></span><span class="meta function-call arguments shell"> Process 13078 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">13078</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13078] nanosleep(<span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>tv_sec=1<span class="punctuation separator shell">,</span> tv_nsec=0<span class="punctuation section expansion brace end shell">}</span></span>,  <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13077] accept4(3, NULL, NULL, 0 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13078] <span class="keyword operator assignment redirection shell">&lt;</span>... nanosleep resumed<span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">0</span>x9daff8</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13078] write(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13078] close(4</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                    <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13078] exit(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                     <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13078] +++ exited with 0 +++</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>... accept4 resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                  <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span><span class="meta function-call arguments shell"> ERESTARTSYS (To be restarted if SA_RESTART is set</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">---</span></span><span class="meta function-call arguments shell"> SIGWINCH <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>si_signo=SIGWINCH<span class="punctuation separator shell">,</span> si_code=SI_KERNEL<span class="punctuation section expansion brace end shell">}</span></span> ---</span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span>
</span></code></pre>
<p>Vamos reparar na sequência de chamadas:</p>
<ul>
<li>
<p>depois do accept, foi feita uma chamada a <strong>brk</strong> modificando o program break (alocando memória)</p>
</li>
<li>
<p>a seguir, vemos a chamada <strong>clone</strong>, que acoplou o processo filho 13078</p>
</li>
<li>
<p>a thread (13078) é suspensa com <strong>nanosleep</strong> por 1 segundo</p>
</li>
<li>
<p>o processo principal (13077) volta para o <strong>accept</strong> e fica a espera de mais requests</p>
</li>
<li>
<p>a thread <strong>escreve</strong> no socket</p>
</li>
<li>
<p>a thread <strong>fecha</strong> o socket</p>
</li>
<li>
<p>a thread é encerrada com <strong>exit</strong></p>
</li>
</ul>
<p>Agora, simulando os 10 requests simultâneos:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.060</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.064</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.064</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.062</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.068</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.073</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.098</span>
<span class="meta function-call shell"><span class="variable function shell">2.094</span></span>
<span class="meta function-call shell"><span class="variable function shell">2.097</span></span>
<span class="meta function-call shell"><span class="variable function shell">2.091</span></span>
<span class="meta function-call shell"><span class="variable function shell">2.113</span></span>
</span></code></pre>
<p><em>Superb!</em> Temos o mesmo tempo total de <strong>2,1 segundos</strong> mas gastando <strong>muito menos memória</strong>!</p>
<p>Entretanto, temos um pequeno problema. Imagina que num momento de grande número de acessos, a nossa aplicação recebe 1000 requests concorrentes. E se receber 5000? Ou então <strong>dezenas de milhares</strong> de requests simultâneos?</p>
<p>Uma <strong>chamada de sistema tem custo</strong>. O sistema operacional oferece um limite de threads que podem ser criadas ao mesmo tempo por processo. Se deixarmos assim, nossa aplicação corre um grande risco de ultrapassar esse limite, além de que chamadas a <em>brk + clone</em> têm seus custos de criação.</p>
<p>E se pudéssemos reciclar um número limitado de threads? Sim, estamos falando de <strong>pool de threads</strong>.</p>
<hr />
<h2 id="concorrência-com-thread-pool">Concorrência com thread pool</h2>
<p>A forma mais comum de trabalhar com thread é com <em>thread pool</em>. Basicamente, definimos um número arbitrário de threads <strong>que nunca terminam</strong>, mas ficam em loop consumindo mensagens de alguma estrutura de dados. Esta estrutura pode ser uma <strong>fila</strong>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8ysvzs13lo7jju7opfs.png" alt="thread pool" /></p>
<h3 id="uma-thread-em-loop">Uma thread em loop</h3>
<p>Vamos inicialmente definir que teremos apenas UMA thread em loop lendo mensagens da fila. O processo deverá ser o seguinte:</p>
<ul>
<li>
<p>processo principal inicia uma thread</p>
</li>
<li>
<p>a thread fica em loop lendo mensagens (socket) da fila. Quando tiver vazia, repete o loop. Quando houver algum socket na fila, a thread executa a lógica que é fazer o <em>nanosleep</em>, escrever no socket, fechar o socket, e voltar para o loop de leitura da fila</p>
</li>
<li>
<p>processo principal continua execução após criação da thread, onde fica em loop lendo requisições que chegam no socket (accept). Quando uma requisição chega, adiciona o socket na fila e volta para o loop do <strong>accept</strong>.</p>
</li>
</ul>
<p>Vamos passo a passo, começando pelas constantes:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_socket <span class="constant numeric actionscript 2">41</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_bind <span class="constant numeric actionscript 2">49</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_listen <span class="constant numeric actionscript 2">50</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_accept4 <span class="constant numeric actionscript 2">288</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_close <span class="constant numeric actionscript 2">3</span>

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_nanosleep <span class="constant numeric actionscript 2">35</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_clone <span class="constant numeric actionscript 2">56</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_brk <span class="constant numeric actionscript 2">12</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>

<span class="keyword operator symbolic actionscript 2">%</span>define AF_INET <span class="constant numeric actionscript 2">2</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SOCK_STREAM <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SOCK_PROTOCOL <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define BACKLOG <span class="constant numeric actionscript 2">2</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CR <span class="constant numeric actionscript 2">0xD</span>
<span class="keyword operator symbolic actionscript 2">%</span>define LF <span class="constant numeric actionscript 2">0xA</span>

<span class="keyword operator symbolic actionscript 2">%</span>define CHILD_STACK_SIZE <span class="constant numeric actionscript 2">4096</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_VM <span class="constant numeric actionscript 2">0x00000100</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_FS <span class="constant numeric actionscript 2">0x00000200</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_FILES <span class="constant numeric actionscript 2">0x00000400</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_PARENT <span class="constant numeric actionscript 2">0x00008000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_THREAD <span class="constant numeric actionscript 2">0x00010000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_IO <span class="constant numeric actionscript 2">0x80000000</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CLONE_SIGHAND <span class="constant numeric actionscript 2">0x00000800</span>
</span></code></pre>
<p>A seguir, a seção de dados:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
sockaddr<span class="keyword operator symbolic actionscript 2">:</span>
	sa_family<span class="keyword operator symbolic actionscript 2">:</span> dw AF_INET   ; <span class="constant numeric actionscript 2">2</span> bytes
	port<span class="keyword operator symbolic actionscript 2">:</span> dw <span class="constant numeric actionscript 2">0xB80B</span>         ; <span class="constant numeric actionscript 2">2</span> bytes
	ip_addr<span class="keyword operator symbolic actionscript 2">:</span> dd <span class="constant numeric actionscript 2">0</span>           ; <span class="constant numeric actionscript 2">4</span> bytes
	sin_zero<span class="keyword operator symbolic actionscript 2">:</span> dq <span class="constant numeric actionscript 2">0</span>          ; <span class="constant numeric actionscript 2">8</span> bytes
<span class="support function actionscript 2">response</span><span class="keyword operator symbolic actionscript 2">:</span> 
	headline<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>HTTP/1.1 200 OK<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	content_type<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Content-Type: text/html<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	content_length<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Content-Length: 22<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	crlf<span class="keyword operator symbolic actionscript 2">:</span> db CR, LF
	body<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>&lt;h1&gt;Hello, World!&lt;/h1&gt;<span class="punctuation definition string end actionscript 2">&quot;</span></span>
responseLen<span class="keyword operator symbolic actionscript 2">:</span> equ $ <span class="keyword operator symbolic actionscript 2">-</span> <span class="support function actionscript 2">response</span>
timespec<span class="keyword operator symbolic actionscript 2">:</span>
	tv_sec<span class="keyword operator symbolic actionscript 2">:</span> dq <span class="constant numeric actionscript 2">1</span>
	tv_nsec<span class="keyword operator symbolic actionscript 2">:</span> dq <span class="constant numeric actionscript 2">0</span>
queuePtr<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0</span>

section .bss
sockfd<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">8</span>
queue<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">8</span>
</span></code></pre>
<p>Repare que a fila representa 8 bytes fixos (para nosso exemplo é o suficiente), utilizando também um ponteiro para manipular a fila.</p>
<p>Seguindo com o código, o programa inicia logo disparando a thread:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">call</span> thread        
</span></code></pre>
<p>A seguir vêm as rotinas habituais (vou omitir pra poupar caracteres neste artigo): <em>socket, bind e listen</em>.</p>
<p>O <strong>accept</strong> fica da seguinte forma:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.accept<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> accept(<span class="support function actionscript 2">int</span> sockfd, struct <span class="keyword operator symbolic actionscript 2">*</span>addr, <span class="support function actionscript 2">int</span> addrlen, <span class="support function actionscript 2">int</span> flags)
	mov rdi, [sockfd]
	mov rsi, <span class="constant numeric actionscript 2">0</span>
	mov rdx, <span class="constant numeric actionscript 2">0</span>
	mov r10, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_accept4
	syscall

	mov r8, rax
	<span class="support function actionscript 2">call</span> enqueue

	jmp .accept
</span></code></pre>
<p>Okay, agora, ao invés de <em>chamar uma thread</em>, o programa principal enfileira o socket da requisição. Lógica do <code>enqueue</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">enqueue<span class="keyword operator symbolic actionscript 2">:</span>
	xor rdx, rdx
	mov dl, [queuePtr]	
	mov [queue <span class="keyword operator symbolic actionscript 2">+</span> rdx], r8	
	inc byte [queuePtr]
	ret
</span></code></pre>
<p>Aqui, estamos manipulando o ponteiro em <code>queue</code> utilizando <code>queuePtr</code>, incrementando um byte quando algo é adicionado na fila.</p>
<p>Agora vamos à implementação da rotina da thread:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">thread<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_brk
	syscall
	mov rdx, rax

	mov rdi, rax
	<span class="support function actionscript 2">add</span> rdi, CHILD_STACK_SIZE
	mov rax, SYS_brk
	syscall

	mov rdi, CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_PARENT|CLONE_THREAD|CLONE_IO
	lea rsi, [rdx <span class="keyword operator symbolic actionscript 2">+</span> CHILD_STACK_SIZE <span class="keyword operator symbolic actionscript 2">-</span> <span class="constant numeric actionscript 2">8</span>]
	mov qword [rsi], handle
	mov rax, SYS_clone
	syscall
	ret
</span></code></pre>
<p>Nada de novo por enquanto. O que modifica é a rotina <em>handle</em> (explicação detalhada nos comentários):</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">handle<span class="keyword operator symbolic actionscript 2">:</span>
	; Verifica se a fila está vazia. Se estiver, fica em loop infinito.
	; Repare que este código não está otimizado. Loop infinito 
	; acarreta alto consumo de CPU. Nas próximas seções vamos resolver isto.
	; Por ora, vamos aceitar este consumo de CPU.
	cmp byte [queuePtr], <span class="constant numeric actionscript 2">0</span>
	je handle

	; Remove (faz <span class="support function actionscript 2">pop</span>) da fila de socket, e guarda em R8.
	<span class="support function actionscript 2">call</span> dequeue
	mov r8, rax

	; Processo normal, faz o nanosleep de <span class="constant numeric actionscript 2">1</span> segundo simulando latência
	lea rdi, [timespec]
	mov rax, SYS_nanosleep
	syscall

	; Escreve no socket que está em R8
	; <span class="support function actionscript 2">int</span> write(fd)
	mov rdi, r8
	mov rsi, <span class="support function actionscript 2">response</span>
	mov rdx, responseLen
	mov rax, SYS_write
	syscall

	; Fecha o socket
	; <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">close</span>(fd)
	mov rdi, r8
	mov rax, SYS_close
	syscall

	; Volta para o início (loop)
	jmp handle
</span></code></pre>
<p>E por último, a lógica da rotina <em>dequeue</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">dequeue<span class="keyword operator symbolic actionscript 2">:</span>
	xor rax, rax
	xor rsi, rsi

	mov al, [queue]
	mov rcx, <span class="constant numeric actionscript 2">0</span>
.loop_dequeue<span class="keyword operator symbolic actionscript 2">:</span>
	cmp byte [queuePtr], <span class="constant numeric actionscript 2">0</span>
	je .return_dequeue

	cmp cl, [queuePtr]
	je .done_dequeue

	; <span class="support function actionscript 2">shift</span>
	xor r10, r10
	mov r10b, [queue <span class="keyword operator symbolic actionscript 2">+</span> rcx <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">1</span>]
	mov byte [queue <span class="keyword operator symbolic actionscript 2">+</span> rcx], r10b

	inc rcx
	jmp .loop_dequeue
.done_dequeue<span class="keyword operator symbolic actionscript 2">:</span>
	dec byte [queuePtr]
.return_dequeue<span class="keyword operator symbolic actionscript 2">:</span>
	ret
</span></code></pre>
<blockquote>
<p>Por enquanto não vou entrar em detalhes em como trabalhar com filas em Assembly. Vou deixar estes detalhes para outro artigo, que irá tratar especificamente de arrays, filas e listas ligadas. Em breve!</p>
</blockquote>
<p>Pronto, já podemos executar o server e...</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.042</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.059</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">3</span>.071</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">4</span>.083</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">5</span>.090</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">6</span>.094</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">7</span>.112</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">8</span>.121</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">9</span>.140</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">10</span>.150</span>
<span class="meta function-call shell"><span class="variable function shell">10.166</span></span>
</span></code></pre>
<p><em>Ouch!</em> Voltamos aos 10 segundos. Mas isto se deve ao fato de termos apenas <em>uma thread</em> em loop. Vamos aumentar o número de threads na pool.</p>
<h3 id="threads-em-loop">5 threads em loop</h3>
<p>A seguir modificamos o programa para inicializar 5 threads, para que desta forma nosso server tenha mais capacidade em atender requests simultâneos:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
.initialize_pool<span class="keyword operator symbolic actionscript 2">:</span>
	mov r8, <span class="constant numeric actionscript 2">0</span>
.pool<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">call</span> thread        
	inc r8
	cmp r8, <span class="constant numeric actionscript 2">5</span>
	je .socket
	jmp .pool
....
....
</span></code></pre>
<p>Com este loop fazemos <code>call thread</code> 5 vezes, pelo que cada thread, e ainda utilizando o exemplo anterior, irá ficar em loop buscando mensagens na fila.</p>
<p>Executamos o código com 1 request e temos sucesso:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> time curl localhost:3000</span>

<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.022</span>
</span></code></pre>
<p>Mas no output do strace, após a resposta, vemos uma sequência de erros das threads:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword control regexp set begin shell">[</span>pid 13483<span class="keyword control regexp set end shell">]</span> write(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13482] write(0, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13480] write(0, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13484] <span class="keyword operator assignment redirection shell">&lt;</span>... write resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13481] write(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86HTTP/1.1 200 OK</span>
<span class="meta function-call shell"><span class="variable function shell">Content-Type:</span></span><span class="meta function-call arguments shell"> text/html</span>
<span class="meta function-call shell"><span class="variable function shell">Content-Length:</span></span><span class="meta function-call arguments shell"> 22</span>

<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span> <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13480] <span class="keyword operator assignment redirection shell">&lt;</span>... write resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">HTTP/1.1</span></span><span class="meta function-call arguments shell"> 200 OK</span>
<span class="meta function-call shell"><span class="variable function shell">Content-Type:</span></span><span class="meta function-call arguments shell"> text/html</span>
<span class="meta function-call shell"><span class="variable function shell">Content-Length:</span></span><span class="meta function-call arguments shell"> 22</span>

<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword control regexp set begin shell">[</span>pid 13484<span class="keyword control regexp set end shell">]</span> close(0 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13483] <span class="keyword operator assignment redirection shell">&lt;</span>... write resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13482] <span class="keyword operator assignment redirection shell">&lt;</span>... write resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13480] close(0 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13484] <span class="keyword operator assignment redirection shell">&lt;</span>... close resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13481] <span class="keyword operator assignment redirection shell">&lt;</span>... write resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13484] nanosleep(<span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>tv_sec=1<span class="punctuation separator shell">,</span> tv_nsec=0<span class="punctuation section expansion brace end shell">}</span></span>,  <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13483] close(4 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13482] close(0 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13481] close(4 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13480] <span class="keyword operator assignment redirection shell">&lt;</span>... close resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">-1</span></span><span class="meta function-call arguments shell"> EBADF (Bad file descriptor</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13483] <span class="keyword operator assignment redirection shell">&lt;</span>... close resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13482] <span class="keyword operator assignment redirection shell">&lt;</span>... close resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">-1</span></span><span class="meta function-call arguments shell"> EBADF (Bad file descriptor</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13481] <span class="keyword operator assignment redirection shell">&lt;</span>... close resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">-1</span></span><span class="meta function-call arguments shell"> EBADF (Bad file descriptor</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
</span></code></pre>
<p>A thread tentou fechar o socket descriptor da requisição mas outra thread tentou ler o socket de forma concorrente (Bad file descriptor).</p>
<p>Quando envolve <strong>mais de uma thread</strong> consumindo o mesmo recurso (neste caso a fila), precisamos de um mecanismo de <strong>sincronização</strong>, que no caso são <em>locks</em>.</p>
<h3 id="sincronização-com-futex">Sincronização com futex</h3>
<p>Com <em>locks</em>, conseguimos controlar o acesso a um recurso compartilhado <em>entre diferentes threads</em>.</p>
<p>Através da syscall <strong>futex</strong>, podemos suspender uma thread baseando-se em uma "variável condicional". De forma oposta, podemos <em>tornar uma thread de volta à execução</em> baseando-se também na variável condicional.</p>
<p>Esta técnica de <em>variável condicional</em> (condvar) é um primitivo de sincronização bastante utilizado. No nosso caso para controle da fila, queremos o seguinte cenário:</p>
<ul>
<li>
<p>a thread verifica se há algo na fila. Caso a fila esteja vazia, a thread é suspensa com <em>futex wait</em> através de uma variável condicional</p>
</li>
<li>
<p>quando algo for adicionado na fila, outra thread/processo "emite um sinal" chamando a syscall <em>futex wake</em> na mesma variável condicional.</p>
</li>
<li>
<p>quando o sinal é emitido, neste momento a thread que tem o acesso ao lock (variável condicional) é trazida de volta ao contexto, então lê a mensagem da fila e executa a ação necessária. Após, se a fila estiver vazia, repete o processo com <em>futex wait</em> e fica novamente suspensa</p>
</li>
</ul>
<blockquote>
<p>Desta forma, garantimos que as threads não ficam consumindo a CPU em loop indefinidamente</p>
</blockquote>
<p>Modificando o código, começamos por definir a syscall:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_futex <span class="constant numeric actionscript 2">202</span>
</span></code></pre>
<p>A seguir, na seção de dados <code>.bss</code> declaramos a <em>variável condicional</em> ocupando 8 bytes, que será utilizada como sincronização do futex:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .bss
...
condvar<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">8</span>
</span></code></pre>
<p>Na rotina <code>enqueue</code>, <em>emitimos o sinal</em> após o socket ser adicionado na fila:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">enqueue<span class="keyword operator symbolic actionscript 2">:</span>
	xor rdx, rdx
	mov dl, [queuePtr]	
	mov [queue <span class="keyword operator symbolic actionscript 2">+</span> rdx], r8	
	inc byte [queuePtr]

	<span class="support function actionscript 2">call</span> emit_signal
	ret
</span></code></pre>
<p>A lógica o <em>emit_signal</em> (explicação nos comentários):</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">emit_signal<span class="keyword operator symbolic actionscript 2">:</span>
   ; Endereço de memória para a variável condicional (<span class="constant numeric actionscript 2">8</span> bytes)
   mov rdi, condvar
   
   ; Flags <span class="keyword control actionscript 2">do</span> Futex (WAKE), que irá trazer a thread
   ; de volta ao contexto
   mov rsi, FUTEX_WAKE | FUTEX_PRIVATE_FLAG 

   ; Argumentos adicionais, que neste caso vamos deixar a ZERO
   xor rdx, rdx
   xor r10, r10
   xor r8, r8

   ; Chamada da syscall
   mov rax, SYS_futex
   syscall
   ret
</span></code></pre>
<p>Agora, modificamos a rotina <em>handle</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">handle<span class="keyword operator symbolic actionscript 2">:</span>	
	; Caso a fila esteja vazia, fazemos jump para <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>wait<span class="punctuation definition string end actionscript 2">&quot;</span></span>
	cmp byte [queuePtr], <span class="constant numeric actionscript 2">0</span>         
	je .wait           

	; Faz <span class="support function actionscript 2">pop</span> <span class="keyword control actionscript 2">do</span> socket da fila e segue o fluxo normal
	<span class="support function actionscript 2">call</span> dequeue      
	mov r10, rax

	lea rdi, [timespec]
	mov rax, SYS_nanosleep
	syscall

	; <span class="support function actionscript 2">int</span> write(fd)
	mov rdi, r10
	mov rsi, <span class="support function actionscript 2">response</span>
	mov rdx, responseLen
	mov rax, SYS_write
	syscall

	; <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">close</span>(fd)
	mov rdi, r10
	mov rax, SYS_close
	syscall

	; Volta para o início
	jmp handle       
.wait<span class="keyword operator symbolic actionscript 2">:</span>
	; Chamada para wait_condvar, que vai suspender a thread atual com FUTEX
	<span class="support function actionscript 2">call</span> wait_condvar 
	jmp handle       
</span></code></pre>
<p>E, por último e não menos importante, a lógica da rotina <em>wait_condvar</em>, que suspende a thread de execução:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">wait_condvar<span class="keyword operator symbolic actionscript 2">:</span>
   ; Endereço de memória para a variável condicional (<span class="constant numeric actionscript 2">8</span> bytes)
   mov rdi, condvar   

   ; Flags <span class="keyword control actionscript 2">do</span> Futex (WAIT), que irá suspender a thread
   mov rsi, FUTEX_WAIT | FUTEX_PRIVATE_FLAG 
   xor rdx, rdx
   xor r10, r10              
   xor r8, r8               
   mov rax, SYS_futex
   syscall
   <span class="support function actionscript 2">test</span> rax, rax
   jz .done_condvar
.done_condvar<span class="keyword operator symbolic actionscript 2">:</span>
   ret
</span></code></pre>
<p>Assim que iniciamos o server com <em>strace</em>, podemos ver as syscalls em ação:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">brk</span></span><span class="meta function-call arguments shell">(NULL</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x155c000</span></span>
<span class="meta function-call shell"><span class="variable function shell">brk</span></span><span class="meta function-call arguments shell">(0x155d000</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                          <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x155d000</span></span>
<span class="meta function-call shell"><span class="variable function shell">clone</span></span><span class="meta function-call arguments shell">(child_stack=0x155cff8, flags=CLONE_VM</span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FS</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FILES</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_SIGHAND</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_PARENT</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_THREAD</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_IOstrace:</span></span><span class="meta function-call arguments shell"> Process 13539 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">13539</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13539] futex(0x402088, FUTEX_WAIT_PRIVATE, 0, NULL <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] brk(NULL</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x155d000</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] brk(0x155e000</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>              <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x155e000</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] clone(child_stack=0x155dff8, flags=CLONE_VM</span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FS</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FILES</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_SIGHAND</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_PARENT</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_THREAD</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_IOstrace:</span></span><span class="meta function-call arguments shell"> Process 13540 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">13540</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13540] futex(0x402088, FUTEX_WAIT_PRIVATE, 0, NULL <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] brk(NULL</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x155e000</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] brk(0x155f000</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>              <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x155f000</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] clone(child_stack=0x155eff8, flags=CLONE_VM</span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FS</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FILES</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_SIGHAND</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_PARENT</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_THREAD</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_IOstrace:</span></span><span class="meta function-call arguments shell"> Process 13541 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">13541</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13541] futex(0x402088, FUTEX_WAIT_PRIVATE, 0, NULL <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] brk(NULL</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x155f000</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] brk(0x1560000</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>              <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x1560000</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] clone(child_stack=0x155fff8, flags=CLONE_VM</span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FS</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FILES</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_SIGHAND</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_PARENT</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_THREAD</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_IOstrace:</span></span><span class="meta function-call arguments shell"> Process 13542 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">13542</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13542] futex(0x402088, FUTEX_WAIT_PRIVATE, 0, NULL <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] brk(NULL</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x1560000</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] brk(0x1561000</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>              <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0x1561000</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] clone(child_stack=0x1560ff8, flags=CLONE_VM</span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FS</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_FILES</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_SIGHAND</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_PARENT</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_THREAD</span></span><span class="keyword operator logical pipe shell">|</span><span class="meta function-call shell"><span class="variable function shell">CLONE_IOstrace:</span></span><span class="meta function-call arguments shell"> Process 13543 attached</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">13543</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] socket(AF_INET, SOCK_STREAM, IPPROTO_IP <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13543] futex(0x402088, FUTEX_WAIT_PRIVATE, 0, NULL <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] <span class="keyword operator assignment redirection shell">&lt;</span>... socket resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>       <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] bind(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] listen(3, 2</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] accept4(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span><span class="meta function-call arguments shell"> ERESTARTSYS (To be restarted if SA_RESTART is set</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] --- SIGWINCH <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>si_signo=SIGWINCH<span class="punctuation separator shell">,</span> si_code=SI_KERNEL<span class="punctuation section expansion brace end shell">}</span></span> ---</span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] accept4(3, NULL, NULL, 0</span>
</span></code></pre>
<p>Repare que cada thread faz a chamada a futex com <em>FUTEX WAIT</em>, e isto vemos acontecer 5 vezes no trace. Ou seja, as 5 threads estão suspensas <strong>sem consumir CPU</strong>.</p>
<p>Ao fazer o primeiro request, temos o seguinte resultado:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>   <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] futex(0x402088, FUTEX_WAKE_PRIVATE, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">1</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13539] <span class="keyword operator assignment redirection shell">&lt;</span>... futex resumed<span class="keyword operator assignment redirection shell">&gt;</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>        <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13538] accept4(3, NULL, NULL, 0 <span class="keyword operator assignment redirection shell">&lt;</span>unfinished ...<span class="keyword operator assignment redirection shell">&gt;</span>
</span><span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13539] nanosleep(<span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>tv_sec=1<span class="punctuation separator shell">,</span> tv_nsec=0<span class="punctuation section expansion brace end shell">}</span></span>, NULL</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13539] write(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13539] close(4</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                    <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">[pid</span></span><span class="meta function-call arguments shell"> 13539] futex(0x402088, FUTEX_WAIT_PRIVATE, 0, NULL</span>
</span></code></pre>
<ul>
<li>
<p>o processo principal recebeu a mensagem no socket, enfileirou e executou <em>futex</em> com <strong>FUTEX_WAKE</strong></p>
</li>
<li>
<p>uma das threads foi trazida de volta ao contexto e fez a sua devida execução (nanosleep + write + close)</p>
</li>
<li>
<p>o processo principal voltou para o accept a espera de mais requests no socket</p>
</li>
<li>
<p>a thread terminou seu trabalho, viu que não tinha mais nada na fila e executou <em>futex</em> com <strong>FUTEX_WAIT</strong>, ficando novamente suspensa</p>
</li>
</ul>
<p>Finalmente, podemos executar 10 requests simultâneos e...</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.079</span>
<span class="meta function-call shell"><span class="variable function shell">1.082</span></span>
<span class="meta function-call shell"><span class="variable function shell">1.083</span></span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">1</span>.062</span>
<span class="meta function-call shell"><span class="variable function shell">1.083</span></span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.087</span>
<span class="meta function-call shell"><span class="variable function shell">2.088</span></span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.100</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.101</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span><span class="constant numeric integer decimal file-descriptor shell">2</span>.110</span>
<span class="meta function-call shell"><span class="variable function shell">2.127</span></span>
</span></code></pre>
<p><em>Nice!</em> Com uma pool de 5 threads, conseguimos atingir <strong>2,1 segundos</strong> para 10 requests concorrentes. Agora temos concorrência consumindo muito menos recursos:</p>
<ul>
<li>
<p>menos memória, pois não é forking de processos</p>
</li>
<li>
<p>menos CPU, pois as threads não ficam em loop infinito</p>
</li>
<li>
<p>menos latência, pois com uma limitação de 5 threads, novos requests não criam novas threads</p>
</li>
</ul>
<hr />
<h2 id="alocação-de-memória-com-mmap">Alocação de memória com mmap</h2>
<p>Um problema comum ao utilizar <em>brk</em> é que a memória pode ficar fragmentada. Uma vez que o program break foi modificado, aquela memória pode ser utilizada, mas torna muito difícil ser reciclada.</p>
<p>Uma forma de lidar com este problema de fragmentação é utilizar uma syscall que trata de reservar uma área na memória que pode ser reciclada futuramente. Estamos falando da syscall <strong>mmap</strong>.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">thread<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0x0</span>
	mov rsi, CHILD_STACK_SIZE
	mov rdx, PROT_WRITE | PROT_READ
	mov r10, MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN
	mov rax, SYS_mmap
	syscall

	mov rdi, CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_PARENT|CLONE_THREAD|CLONE_IO
	lea rsi, [rax <span class="keyword operator symbolic actionscript 2">+</span> CHILD_STACK_SIZE <span class="keyword operator symbolic actionscript 2">-</span> <span class="constant numeric actionscript 2">8</span>]
	mov qword [rsi], handle
	mov rax, SYS_clone
	syscall
	ret
</span></code></pre>
<p>Ao invés de chamar <em>brk</em>, podemos chamar <strong>mmap</strong>, especificando:</p>
<ul>
<li>
<p><strong>rdi</strong>: endereço de memória onde deve ser mapeado. Se tiver ZERO, o sistema operacional se encarrega de trazer um endereço de memória disponível</p>
</li>
<li>
<p><strong>rsi</strong>: tamanho do espaço reservado na memória. No nosso caso, queremos 4096 bytes para a thread</p>
</li>
<li>
<p><strong>rdx</strong>: proteção de memória, neste caso queremos que a memória possa ser tanto escrita (PROT_WRITE) quanto lida (PROT_READ) pela thread</p>
</li>
<li>
<p><strong>r10</strong>: flags de mapeamento</p>
<ul>
<li><strong>MAP_ANONYMOUS</strong>: o mapeamento não é associado a nenhum arquivo ou descritor de arquivo (modo anônimo)</li>
<li><strong>MAP_PRIVATE</strong>: mapeamento privado com <em>copy-on-write</em>, ou seja, os dados serão copiados à medida em que são escritos</li>
<li><strong>MAP_GROWSDOWN</strong>: o mapeamento é usado no formato "stack", ou seja, o mapeamento é dos endereços maiores em direção aos menores</li>
</ul>
</li>
</ul>
<p>Com <em>mmap</em>, podemos fazer uso da sua contrapartida, a syscall <strong>unmmap</strong>, que permite reciclar uma determinada área na memória que não é mais utilizada, evitando fragmentação.</p>
<blockquote>
<p>Esta técnica é muito utilizada pela libc através da função <strong>malloc</strong>. Com mmap podemos definir uma memória heap para nosso programa</p>
</blockquote>
<p>É isto, na prática não terá nenhum efeito com relação ao exemplo anterior. Mas esta seção foi apenas para trazer uma forma diferente de alocar memória para a thread.</p>
<hr />
<h2 id="conclusão">Conclusão</h2>
<p>Ufa! Finalmente chegamos ao final da saga. Passamos por uma <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-i-introducao-14p5">introdução</a>, onde a seguir fizemos uma abordagem pela <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-ii-historia-e-arquitetura-2jb9">história e arquitetura de computadores</a>, para então analisar <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iii-codigo-de-maquina-bgk">código de máquina</a>, que foi a base para entrar em <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iv-um-assembly-modesto-oif">assembly x86</a> de fato, para finalmente <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-v-finalmente-o-server-9e5">concluir o desenvolvimento do web server</a>.</p>
<p>Este último artigo foi uma abordagem para multi-threading em Assembly, passando por conceitos de concorrência como <em>forking de processos</em>, <strong>clone</strong>, threading, pool de threads e sincronização com locks.</p>
<p>Declaro aqui então o fim da <strong>saga desenvolvendo um web server em Assembly x86</strong>.</p>
<p><em>Até a próxima saga!</em></p>
<hr />
<h2 id="referências">Referências</h2><sub>
Synchronization: mutexes and condition variables
https://cs61.seas.harvard.edu/site/2018/Synch3/
Synchronization, atomics and mutexes
https://cs.brown.edu/courses/csci0300/2023/notes/l22.html
Basics of Futexes
https://eli.thegreenplace.net/2018/basics-of-futexes/
Raw Linux threads via syscalls
https://nullprogram.com/blog/2015/05/15/
Condition variables with Futex
https://www.remlab.net/op/futex-condvar.shtml
</sub>
]]></description>
<pubDate>2024-07-14</pubDate>
</item>
<item>
<title>Construindo um web server em Assembly x86, parte V, finalmente o server</title>
<link>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-v-finalmente-o-server-9e5.html</link>
<guid>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-v-finalmente-o-server-9e5.html</guid>
<description><![CDATA[<p>No <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iv-um-assembly-modesto-oif">artigo anterior</a>, passamos pelos fundamentos de Assembly, onde foi possível entender alguns conceitos básicos tais como tipos de registradores, <strong>stack</strong>, loops, FLAGS etc, tudo sendo feito com debugging via <em>GDB</em>.</p>
<p>Agora, vamos de fato construir um web server muito simples que devolve um HTML com a frase "Hello, World". A meta é chegarmos nisto:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6745f6h98cph2u50aa8x.png" alt="hello world" /></p>
<p>O processo para chegarmos a este objetivo consiste em cobrir fundamentos de Web, passando por sockets, TCP e HTTP, enquanto vamos explorando conceitos práticos em Assembly x86.</p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#arquitetura-web">Arquitetura Web</a></p>
<ul>
<li><a href="#clienteservidor">Cliente-servidor</a></li>
<li><a href="#modelo-osi">Modelo OSI</a></li>
<li><a href="#sockets-e-tcp">Sockets e TCP</a></li>
<li><a href="#http">HTTP</a></li>
</ul>
</li>
<li>
<p><a href="#como-funciona-um-servidor-web">Como funciona um servidor web</a></p>
<ul>
<li><a href="#4-syscalls-para-o-resgate">4 syscalls para o resgate</a></li>
</ul>
</li>
<li>
<p><a href="#um-server-modesto-em-assembly">Um server modesto em Assembly</a></p>
<ul>
<li><a href="#criando-o-socket">Criando o socket</a></li>
<li><a href="#fazendo-bind-no-socket">Fazendo bind no socket</a></li>
<li><a href="#preparando-para-receber-conex%C3%B5es">Preparando para receber conexões</a></li>
<li><a href="#chegou-o-momento-de-aceitar-clientes">Chegou o momento de aceitar clientes</a></li>
<li><a href="#resposta-do-servidor-e-fechamento-da-conex%C3%A3o">Resposta do servidor e fechamento da conexão</a></li>
<li><a href="#mas-o-servidor-deve-ficar-em-loop-n%C3%A3o">Mas o servidor deve ficar em loop, não?</a></li>
</ul>
</li>
<li>
<p><a href="#conclus%C3%A3o">Conclusão</a></p>
</li>
<li>
<p><a href="#refer%C3%AAncias">Referências</a></p>
</li>
</ul>
<hr />
<h2 id="arquitetura-web">Arquitetura Web</h2>
<p>Para criar um servidor web, precisamos manipular <em>mensagens HTTP</em>, que são transportadas via camada de transporte TCP/IP através de uma rede.</p>
<p>Estas mensagens são enviadas entre diferentes dispositivos conectados a uma rede, que pode ser privada (local) ou pública. Regularmente, comunicação HTTP é feita entre 2 dispositivos, sendo um deles o <em>cliente</em> e outro o <em>servidor</em>.</p>
<p>Vamos brevemente falar de cada um destes conceitos.</p>
<h3 id="cliente-servidor">Cliente-servidor</h3>
<p>Numa arquitetura cliente-servidor, temos 2 dispositivos conectados a uma rede de computadores:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z9io56i8xzadm9cqvepe.png" alt="cliente servidor" /></p>
<p>Para um servidor web, é necessário que o cliente realize uma <strong>conexão</strong> com o servidor, em seguida faça uma <strong>requisição</strong>, pelo que o servidor deve devolver uma <strong>resposta</strong> e, por último, <strong>fechar a conexão</strong>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/maxau6kx9t18u6r049r0.png" alt="connect request response" /></p>
<p>Mas como esta mensagem deve ser enviada? Quem garante a entrega? E caso ocorra falha de sinal na camada física (cabeamento de rede), como assegurar que cada "pacote" da mensagem seja entregue em ordem?</p>
<p>É pra isto que foi criado o <strong>modelo de comunicação OSI</strong>.</p>
<h3 id="modelo-osi">Modelo OSI</h3>
<p>OSI é um modelo de referência para comunicação entre diferentes dispositivos através de diferentes redes, que estabelece um conjunto de camadas que vai desde a camada física até a camada de formato de mensagens.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sdfapddkf7j5uzojvgzg.png" alt="modelo OSI" /></p>
<ul>
<li>
<p><strong>Camada física</strong>: responsável pelo tráfego de informações através de meios físicos, tais como bluetooth, frequência de rádio, cabos etc</p>
</li>
<li>
<p><strong>Camada de enlace de rede</strong>: responsável pela decodificação e codificação de mensagens em frames, do meio físico para o meio digital e vice-versa</p>
</li>
<li>
<p><strong>Camada de rede</strong>: é aqui que definimos protocolos de rede, tais como o <em>protocolo de internet</em>, também conhecido como <strong>IP</strong> (Internet Protocol)</p>
</li>
</ul>
<blockquote>
<p>Na web, os dados trafegam geralmente através de uma rede de computadores pública, global e descentralizada, neste caso a Internet</p>
</blockquote>
<ul>
<li>
<p><strong>Camada de transporte</strong>: camada responsável por características de entrega, tais como definir critérios de confiabilidade e ordem dos pacotes de mensagens. Por exemplo, nesta camada temos o <em>protocolo de  controle de transmissão</em>, ou <strong>TCP</strong></p>
</li>
<li>
<p><strong>Camada de sessão e apresentação</strong>: aqui vão critérios de informações que podem ser vinculadas a uma determinada conexão entre diferentes dispositivos, bem como o formato de apresentação das informações na rede</p>
</li>
<li>
<p><strong>Camada de aplicação</strong>: nesta camada, temos a definição do formato de mensagens em um nível mais "aplicacional", como por exemplo protocolo HTTP (Hypertext Transfer Protocol), FTP, SSH entre outros</p>
</li>
</ul>
<p>Entretanto fica aqui uma questão: como que todo esse modelo de comunicação em rede se converte em algo prático num programa dentro de um sistema operacional?</p>
<p>Chegou o momento de falar sobre <em>sockets</em> e TCP.</p>
<h3 id="sockets-e-tcp">Sockets e TCP</h3>
<p>Num computador, todos os programas são encapsulados dentro de uma estrutura chamada <em>processo</em>, como vimos em artigos anteriores.</p>
<p>Quando falamos em cliente na aquitetura cliente-servidor, estamos falando de um processo rodando dentro de um computador, e o mesmo vale para o servidor, onde cada processo tem seu próprio identificador, ou <em>PID</em>:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7q9yi7cdbs42p0352s24.png" alt="pids" /></p>
<p>Sabendo que processos são isolados, foram definidas diferentes formas de comunicação entre processos (também conhecido como IPC, ou <em>inter process communication</em>), tais como pipes, arquivos do filesystem, descritores de arquivos e UNIX sockets.</p>
<blockquote>
<p>Estamos baseando a saga em sistema "UNIX-like", mais especificamente GNU/Linux</p>
</blockquote>
<p>Ou seja, temos ciência que é possível fazer 2 processos <em>dentro de um mesmo computador</em> se comunicarem através de UNIX sockets. Mas como fazer dois processos em computadores distintos se comunicarem?</p>
<p>Entramos então em <strong>Berkeley Sockets</strong>, que define uma API comum de comunicação utilizando sockets, onde diferentes sockets podem estar no mesmo computador, ou em uma mesma rede local, ou até mesmo em redes diferentes dentro da <em>Internet</em>.</p>
<p>É aqui que temos a introdução ao TCP, que é um protocolo de comunicação via sockets. Portanto, para fazer um cliente se comunicar com um servidor, é preciso estabelecer <em>endpoints de comunicação</em>, que são basicamente <strong>sockets</strong>, e neste caso para a web, vamos utilizar <em>sockets TCP</em>.</p>
<p>Estes sockets são abertos tanto do lado do cliente, quanto no servidor. No servidor, estes sockets são mapeados em descritores de arquivos, que representam um número especial e reservado, também chamado de <strong>porta de comunicação</strong>:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1x249n2k8ajhgvj2fsq.png" alt="sockets e tcp" /></p>
<blockquote>
<p>Ok Leandro, consegui entender o conceito de sockets e TCP. Mas qual deveria ser o formato da mensagem na web?</p>
</blockquote>
<p>Com vocês, o <em>HTTP</em>.</p>
<h3 id="http">HTTP</h3>
<p>HTTP é um protocolo de formato de mensagem que faz parte da camada de aplicação.</p>
<p>Com HTTP, a mensagem é definida seguindo padrões de hipertexto, que são basicamente documentos que podem ter ligações com outros documentos em sites diferentes.</p>
<p>Na web, o padrão segue um formato de <em>headline</em>, que contém o tipo de pedido, seguido de quebra de linhas com <em>cabeçalhos</em> de metadados e por fim, opcionalmente e dependendo do tipo de pedido, um <em>corpo</em> com a mensagem principal contendo majoritariamente HTML, CSS e Javascript.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7d0w16gxgauxlw4bnwe6.png" alt="tcp &amp; http" /></p>
<p>Até agora, passamos por conceitos que formam a web. Como nosso exemplo de web server é bastante simples, estes fundamentos já são o suficiente para entrarmos na próxima seção, que é de fato escrever o web server em Assembly x86.</p>
<hr />
<h2 id="como-funciona-um-servidor-web">Como funciona um servidor web</h2>
<p>Conforme vimos na seção anterior, arquitetura web passa por manipulação de sockets TCP.</p>
<p>Tal manipulação é feita via <em>chamadas de sistema</em> (syscalls) no sistema operacional, portanto, para darmos início ao servidor, vamos entender como devem ser criados os sockets a nível do OS.</p>
<h3 id="syscalls-para-o-resgate">4 syscalls para o resgate</h3>
<p>Resumidamente temos que fazer 4 syscalls para termos um server operante, que são:</p>
<p><strong>socket</strong>
A syscall <em>socket</em> é responsável por criar um endpoint de comunicação de rede e retornar um descritor de arquivo (fd) relativo ao endpoint criado.</p>
<p>Na libc, <em>socket</em> é referenciada pelo número 41 e tem a seguinte assinatura:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="storage type c">int</span> <span class="meta function c"><span class="entity name function c">socket</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="storage type c">int</span> <span class="variable parameter c">domain</span><span class="punctuation separator c">,</span> <span class="storage type c">int</span> <span class="variable parameter c">type</span><span class="punctuation separator c">,</span> <span class="storage type c">int</span> <span class="variable parameter c">protocol</span><span class="punctuation section group end c">)</span></span></span><span class="meta function c">
</span></span></code></pre>
<blockquote>
<p>Lembrando que estamos utilizando arquitetura x86_64, ou x64</p>
</blockquote>
<p><strong>bind</strong>
<em>bind</em> atribui nome e porta ao socket previamente criado. Esta syscall na libc responde pelo número 49 e tem a assinatura a seguir:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="storage type c">int</span> <span class="meta function c"><span class="entity name function c">bind</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="storage type c">int</span> <span class="variable parameter c">sockfd</span><span class="punctuation separator c">,</span> <span class="storage modifier c">const</span> <span class="storage type c">struct</span> sockaddr <span class="keyword operator c">*</span><span class="variable parameter c">addr</span><span class="punctuation separator c">,</span> socklen_t <span class="variable parameter c">addrlen</span><span class="punctuation section group end c">)</span></span></span><span class="meta function c">
</span></span></code></pre>
<p><strong>listen</strong>
A syscall <em>listen</em> marca o socket criado (precisa ser do tipo stream, no caso TCP) para aceitar conexões. É conhecida pelo número 50 e tem a seguinte assinatura em C:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="storage type c">int</span> <span class="meta function c"><span class="entity name function c">listen</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="storage type c">int</span> <span class="variable parameter c">sockfd</span><span class="punctuation separator c">,</span> <span class="storage type c">int</span> <span class="variable parameter c">backlog</span><span class="punctuation section group end c">)</span></span></span><span class="meta function c">
</span></span></code></pre>
<p><strong>accept</strong>
A syscall <em>accept</em> admite uma conexão de um cliente no socket e cria um <em>novo socket de conexão específico</em> para aquele cliente. Esta syscall, a princípio, bloqueia o programa e só continua a execução quando uma nova conexão com novo cliente é estabelecida.</p>
<p>É referenciada pelo número 288 e tem a seguinte assintaura:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="storage type c">int</span> <span class="meta function c"><span class="entity name function c">accept</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="storage type c">int</span> <span class="variable parameter c">sockfd</span><span class="punctuation separator c">,</span> <span class="storage type c">struct</span> <span class="keyword operator c">*</span><span class="variable parameter c">addr</span><span class="punctuation separator c">,</span> <span class="storage type c">int</span> <span class="variable parameter c">addrlen</span><span class="punctuation separator c">,</span> <span class="storage type c">int</span> <span class="variable parameter c">flags</span><span class="punctuation section group end c">)</span></span></span><span class="meta function c">
</span></span></code></pre>
<p>Em resumo, tudo o que precisamos para criar um web server, independente do programa, linguagem de programação ou tecnologia, é de chamar estas 4 syscalls.</p>
<blockquote>
<p>Não se engane, o teu servidor Express, Rails, Django ou NGINX, faz estas chamadas de sistema por baixo dos panos: <em>socket, bind, listen e accept</em></p>
</blockquote>
<p>Sem mais delongas, vamos ver como tudo isto se aplica naquilo que importa para esta saga: <strong>assembly</strong>.</p>
<hr />
<h2 id="um-server-modesto-em-assembly">Um server modesto em Assembly</h2>
<p>Montar as syscalls para o web server em Assembly não é tão difícil quanto parece. Para começar, vamos fazer a primeira syscall, que é a <em>socket</em>.</p>
<h3 id="criando-o-socket">Criando o socket</h3>
<p>Como de costume, vamos montar as instruções de acordo com o <a href="https://man7.org/linux/man-pages/man2/socket.2.html">manual</a> e <a href="https://x64.syscall.sh/">tabela de syscalls</a>.</p>
<blockquote>
<p>Já vimos na seção anterior quais são os números das syscalls e suas respectivas assinaturas na libc</p>
</blockquote>
<p>Iniciamos definindo as constantes, apenas as necessárias para a syscall <em>socket</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

; syscalls constants
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_socket <span class="constant numeric actionscript 2">41</span>

; other constants
<span class="keyword operator symbolic actionscript 2">%</span>define AF_INET <span class="constant numeric actionscript 2">2</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SOCK_STREAM <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SOCK_PROTOCOL <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<p>Após isto, vamos reservar 1 byte com a diretiva <code>resb 1</code> que significa "reservar 1 byte". Este byte será utilizado para armazenar o número do descritor de arquivo que referencia o <em>socket</em> que vai ser criado.</p>
<p>Como <strong>não queremos inicializar</strong> o valor deste byte, não vamos colocar na seção <code>.data</code> como temos utilizado até o momento na saga, mas sim na seção <code>.bss</code>.</p>
<ul>
<li>
<p>Na seção <code>.data</code>, ficam apenas dados inicializados</p>
</li>
<li>
<p>Na seção <code>.bss</code>, ficam os dados não-inicializados</p>
</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .bss
sockfd<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">1</span>
</span></code></pre>
<p>Vamos relembrar o layout de memória:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3wznvwyjq68cs1ln7aj3.png" alt="layout de memória" /></p>
<p>Como vemos na imagem, a seção <code>.bss</code> vem a seguir a seção <code>.data</code>, ou seja, fica em endereços de memória mais altos que a seção <code>.data</code>.</p>
<p>Agora, vamos montar os registradores seguindo a convenção de chamada e a ordem dos parâmetros da função <em>socket</em> na libc:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
.socket<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> socket(<span class="support function actionscript 2">int</span> <span class="support function actionscript 2">domain</span>, <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">type</span>, <span class="support function actionscript 2">int</span> protocol)
	mov rdi, AF_INET
	mov rsi, SOCK_STREAM
	mov rdx, SOCK_PROTOCOL
	mov rax, SYS_socket
	syscall
	mov [sockfd], rax 
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, <span class="constant numeric actionscript 2">60</span>
	syscall
</span></code></pre>
<ul>
<li>
<p><strong>domain</strong>: representa o domínio de comunicação. No caso queremos usar AF_INET, que significa IPv4, e tem o valor 2 conforme especificado no <a href="https://github.com/bminor/glibc/blob/8f58e412b1e26d2c7e65c13a0ce758fbaf18d83f/bits/socket.h#L78">glibc</a></p>
</li>
<li>
<p><strong>type</strong>: representa o tipo de comunicação, que no caso vamos usar SOCK_STREAM que é sequencial, confiável, duplex e baseado em conexão. O valor <a href="https://github.com/bminor/glibc/blob/8f58e412b1e26d2c7e65c13a0ce758fbaf18d83f/bits/socket.h#L42">conforme glibc</a> é 1</p>
</li>
<li>
<p><strong>protocol</strong>: esta opção é usada no caso da utilização de um protocolo em específico. Neste caso, vamos deixar o valor como 0 que é o default para AF_INET e SOCK_STREAM, <em>indicando que se trata de um socket TCP</em></p>
</li>
</ul>
<blockquote>
<p>Lembrando que existem sockets da família UNIX que não funcionam na camada de rede IP. É possível combinar socket UNIX com SOCK_STREAM, mas neste caso estamos combinando a família AF_INET (IPv4) com o tipo SOCK_STREAM (segmento de bytes, duplex), e esta combinação faz este socket ser TCP. Para mais detalhes sobre sockets, sugiro a leitura de um artigo que escrevi sobre <a href="https://leandronsp.com/articles/building-a-web-server-in-bash-part-i-sockets-2n8b">UNIX Sockets</a></p>
</blockquote>
<p>Vamos confirmar com GDB?</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na linha &lt;syscall&gt;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 22</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Confirmando que os registradores estão com os valores corretos</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> antes da execução da syscall...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdi rsi rdx rax</span>
<span class="meta function-call shell"><span class="variable function shell">rdi</span></span><span class="meta function-call arguments shell">            0x2                 2</span>
<span class="meta function-call shell"><span class="variable function shell">rsi</span></span><span class="meta function-call arguments shell">            0x1                 1</span>
<span class="meta function-call shell"><span class="variable function shell">rdx</span></span><span class="meta function-call arguments shell">            0x0                 0</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x29                41</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Confirmando que `sockfd` continua com o valor zerado</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">sockfd</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>sockfd<span class="keyword operator assignment redirection shell">&gt;</span>:      0x00000000</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>
</span></code></pre>
<p>Após a execução da syscall, podemos ver que o <em>retorno da função</em>, que representa o descritor de arquivo conforme documentação, está armazenado no registrador RAX (de acordo com a convenção de chamada):</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">(gdb) i r rax
rax            <span class="constant numeric actionscript 2">0x3</span>                 <span class="constant numeric actionscript 2">3</span>

(gdb) <span class="support function actionscript 2">next</span>

(gdb) <span class="support function actionscript 2">x</span> <span class="keyword operator symbolic actionscript 2">&amp;</span>sockfd
<span class="constant numeric actionscript 2">0x402000</span> &lt;sockfd&gt;<span class="keyword operator symbolic actionscript 2">:</span>      <span class="constant numeric actionscript 2">0x00000003</span>
</span></code></pre>
<p>Ou seja, após a syscall, temos em <code>sockfd</code> o número do socket que acabou de ser criado.</p>
<p>Executando com <em>strace</em>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./live</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7ffca20187e0 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">exit</span></span><span class="meta function-call arguments shell">(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                 <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">+++</span></span><span class="meta function-call arguments shell"> exited with 0 +++</span>
</span></code></pre>
<p>Sem erros, <em>yay!</em></p>
<p>Vamos para a próxima syscall.</p>
<h3 id="fazendo-bind-no-socket">Fazendo bind no socket</h3>
<p>Agora, é o momento de atribuir um endereço e uma porta como endpoint de comunicação para este socket. É para isto que serve a syscall <em>bind</em>.</p>
<p>Analisando a função:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="punctuation terminator c">;</span> <span class="storage type c">int</span> <span class="meta function-call c"><span class="variable function c">bind</span><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function-call c"><span class="meta group c"><span class="storage type c">int</span> sockfd<span class="punctuation separator c">,</span> <span class="storage modifier c">const</span> <span class="storage type c">struct</span> sockaddr <span class="keyword operator c">*</span>addr<span class="punctuation separator c">,</span> socklen_t addrlen</span></span><span class="meta function-call c"><span class="meta group c"><span class="punctuation section group end c">)</span></span></span>
</span></code></pre>
<p>Podemos ver que um dos argumentos é um <em>ponteiro</em> para uma struct na memória. Vamos entender melhor cada argumento.</p>
<p><strong>sockfd</strong>
Em sockfd vai o inteiro que representa o descritor do socket criado</p>
<p>*<em>sockaddr <strong>addr</strong></em>
Representa o ponteiro para o endereço de memória que contém uma estrutura de dados que, de acordo com <a href="https://www.gta.ufrj.br/ensino/eel878/sockets/sockaddr_inman.html">este guia</a>, contempla: <em>family, port, ip_address, sin_zero</em>, onde sin_zero é apenas padding de preenchimento de bytes.</p>
<p>Para arquitetura x64, esta estrutura deve conter 16 bytes no total, onde:</p>
<ul>
<li>
<p>2 bytes são para a <em>família</em> de protocolo</p>
</li>
<li>
<p>2 bytes para a <em>porta</em></p>
</li>
<li>
<p>4 bytes para o <em>endereço de IP</em></p>
</li>
<li>
<p>8 bytes de padding para o <em>sin_zero</em>, ou seja, preencher os 8 bytes restantes com ZERO</p>
</li>
</ul>
<p><strong>addrlen</strong>: tamanho do sockaddr, e já sabemos que são 16 bytes</p>
<p>Uma vez entendidos os parâmetros da função, vamos montar a chamada.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_bind <span class="constant numeric actionscript 2">49</span>

; Data types <span class="support function actionscript 2">in</span> asm
; (db) byte <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">1</span> byte
; (dw) word <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">2</span> bytes
; (dd) doubleword <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">4</span> bytes
; (dq) quadword <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">8</span> bytes

section .<span class="support function actionscript 2">data</span>
sockaddr<span class="keyword operator symbolic actionscript 2">:</span> 
	family<span class="keyword operator symbolic actionscript 2">:</span> dw AF_INET   ; <span class="constant numeric actionscript 2">2</span> bytes
	port<span class="keyword operator symbolic actionscript 2">:</span> dw <span class="constant numeric actionscript 2">0x0BB8</span>      ; <span class="constant numeric actionscript 2">2</span> bytes (representa a porta <span class="constant numeric actionscript 2">3000</span>)
	ip_address<span class="keyword operator symbolic actionscript 2">:</span> dd <span class="constant numeric actionscript 2">0</span>     ; <span class="constant numeric actionscript 2">4</span> bytes
	sin_zero<span class="keyword operator symbolic actionscript 2">:</span> dq <span class="constant numeric actionscript 2">0</span>       ; <span class="constant numeric actionscript 2">8</span> bytes

.bind<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> bind(<span class="support function actionscript 2">int</span> sockfd, const struct sockaddr <span class="keyword operator symbolic actionscript 2">*</span>addr, socklen_t addrlen)
	mov rdi, [sockfd]
	mov rsi, sockaddr
	mov rdx, <span class="constant numeric actionscript 2">16</span>
	mov rax, SYS_bind
	syscall
</span></code></pre>
<p>Ao validar com GDB, podemos ver que o <code>sockaddr</code> está armazenando a estrutura necessária para ser enviada no parâmetro <code>sockaddr *addr</code> da syscall:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na syscall de bind</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 38</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">sockaddr</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>family<span class="keyword operator assignment redirection shell">&gt;</span>:      0xb80b0002</span>
</span></code></pre>
<p>Se buscarmos os 2 primeiros bytes, confirmamos que é o valor 2 (repare que está invertido pois é o padrão little-endian da aquitetura x86_64:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /2xb</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">sockaddr</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>family<span class="keyword operator assignment redirection shell">&gt;</span>:      0x02    0x00</span>
</span></code></pre>
<p>Quanto à porta, queremos que o server responda no número 3000. Portanto, verificamos que os próximos 2 bytes representam a porta:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Em hexadecimal, 3000 equivale a 0x0BB8, mas por causa do formato</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> little-endian da arquitetura x86_64, estamos visualizando 0xB80B</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /2xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">sockaddr+2</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>port<span class="keyword operator assignment redirection shell">&gt;</span>:        0xb8    0x0b</span>
</span></code></pre>
<p>Queremos também que o servidor responda no endereço de IP <code>0.0.0.0</code>, então os próximos 4 bytes estarão todos a zero:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /4xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">sockaddr+4</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402004</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>ip_address<span class="keyword operator assignment redirection shell">&gt;</span>:  0x00    0x00    0x00    0x00</span>
</span></code></pre>
<p>E, por fim, os 8 bytes restantes representando <em>sin_zero</em>, todos preenchidos com zero:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /8xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">sockaddr+8</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402008</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>sin_zero<span class="keyword operator assignment redirection shell">&gt;</span>:    0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00</span>
</span></code></pre>
<p>Vamos executar com <em>strace</em>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./live</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7ffd51ed4650 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(47115)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">exit</span></span><span class="meta function-call arguments shell">(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                 <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">+++</span></span><span class="meta function-call arguments shell"> exited with 0 +++</span>
</span></code></pre>
<p>Ouch! Apesar da função <em>bind</em> ter retornado 0 indicando que não houve erros, temos um pequeno problema. Repare que a <em>porta</em> não está sendo mapeada para o número <strong>3000</strong>, e sim para <strong>47115</strong>, conforme vemos em <em>htons(47115)</em>.</p>
<p><strong>Entendendo a implicação de endianess na syscall bind</strong>
<code>htons</code> é uma função de rede utilizada para converter a ordem dos bytes do programa antes de serem utilizados na rede. Como a internet utiliza big-endian, esta função converte a ordem utilizada na arquitetura (no caso da x86_64, little-endian) para o formato big-endian da rede.</p>
<p>Entretanto <em>htons(47115)</em> não é o valor que queremos. O que precisamos é que o mapeamendo seja <em>htons(3000)</em>. Por quê isto está acontecendo?</p>
<p>O valor que colocamos em hexadecimal representando <em>3000</em> é <em>0x0BB8</em>, mas se prestarmos atenção no GBD, o valor de fato armazenado está com os bytes invertidos para little-endian, que é <em>0xB80B</em>. Ocorre que <code>0xB80B</code> em decimal é <strong>47115</strong>!!!!!! Aí que está o problema!</p>
<p>Precisamos então inverter os bytes no programa, e assim sendo o valor que será passado para a função htons fica corrigido.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">....
section .<span class="support function actionscript 2">data</span>
sockaddr<span class="keyword operator symbolic actionscript 2">:</span> 
	family<span class="keyword operator symbolic actionscript 2">:</span> dw AF_INET   ; <span class="constant numeric actionscript 2">2</span> bytes
	port<span class="keyword operator symbolic actionscript 2">:</span> dw <span class="constant numeric actionscript 2">0xB80B</span>      ; <span class="constant numeric actionscript 2">2</span> bytes (aqui invertemos <span class="support function actionscript 2">os</span> bytes)
	ip_address<span class="keyword operator symbolic actionscript 2">:</span> dd <span class="constant numeric actionscript 2">0</span>     ; <span class="constant numeric actionscript 2">4</span> bytes
	sin_zero<span class="keyword operator symbolic actionscript 2">:</span> dq <span class="constant numeric actionscript 2">0</span>       ; <span class="constant numeric actionscript 2">8</span> bytes
....
</span></code></pre>
<p>E analisando novamente com GDB:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Agora sim, apesar de estar invertido, é exatamente este valor que</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> queremos que seja passado para htons: 0x0BB8 em decimal é 3000</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /2xb (void<span class="keyword operator regexp quantifier shell">*</span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">sockaddr+2</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>port<span class="keyword operator assignment redirection shell">&gt;</span>:        0x0b    0xb8</span>
</span></code></pre>
<p>Executando novamente com <em>strace</em>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./live</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7ffd51ed4650 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">exit</span></span><span class="meta function-call arguments shell">(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                 <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">+++</span></span><span class="meta function-call arguments shell"> exited with 0 +++</span>
</span></code></pre>
<p><em>Superb!</em> Podemos ver que a syscall <em>bind</em> foi executada com os parâmetros corretamente, inclusive o <code>htons(3000)</code>, então retornando <em>0</em>, que indica que não houve qualquer erro.</p>
<h3 id="preparando-para-receber-conexões">Preparando para receber conexões</h3>
<p>Próximo passo consiste em preparar o socket para receber conexões, que basicamente é chamar a função <code>listen</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_listen <span class="constant numeric actionscript 2">50</span>
<span class="keyword operator symbolic actionscript 2">%</span>define BACKLOG <span class="constant numeric actionscript 2">2</span>

.listen<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> listen(<span class="support function actionscript 2">int</span> sockfd, <span class="support function actionscript 2">int</span> backlog)
	mov rdi, [sockfd]
	mov rsi, BACKLOG
	mov rax, SYS_listen
	syscall
</span></code></pre>
<p>Onde <em>BACKLOG</em> significa a quantidade de conexões "pendentes" no socket. Executamos com <em>strace</em> e:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./live</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7ffe6b4eea30 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">listen</span></span><span class="meta function-call arguments shell">(3, 2</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                            <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">exit</span></span><span class="meta function-call arguments shell">(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                 <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">+++</span></span><span class="meta function-call arguments shell"> exited with 0 +++</span>
</span></code></pre>
<p><em>Que noite maravilhosa!</em> Listen funcionou lindamente, afinal, é uma função muito simples. Agora, hora de aceitar conexões de clientes no socket.</p>
<h3 id="chegou-o-momento-de-aceitar-clientes">Chegou o momento de aceitar clientes</h3>
<p>O grande momento chegou. Vamos montar as instruções da syscall <em>accept</em>, que de acordo com a função em libc, recebe um socket como primeiro argumento e os demais são opcionais.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_accept <span class="constant numeric actionscript 2">288</span>

.accept<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> accept(<span class="support function actionscript 2">int</span> sockfd, struct <span class="keyword operator symbolic actionscript 2">*</span>addr, <span class="support function actionscript 2">int</span> addrlen, <span class="support function actionscript 2">int</span> flags)
	mov rdi, [sockfd]
	mov rsi, <span class="constant numeric actionscript 2">0</span>              ; não precisa estabelecer um addr
	mov rdx, <span class="constant numeric actionscript 2">0</span>              ; não precisa <span class="keyword control actionscript 2">do</span> tamanho uma vez que não há addr
	mov r10, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_accept
	syscall
</span></code></pre>
<p>Se executarmos com GDB, podemos ver que o resultado da syscall fica bloqueado até que uma conexão seja feita:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na syscall de socket</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 55</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>
</span></code></pre>
<p>O programa está parado na syscall de socket, aguardando resposta do <strong>kernel</strong>. Para que o kernel responda e o programa continue a execução, é preciso realizar um pedido usando um HTTP client, e neste caso vamos usar o <em>curl</em>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> curl localhost:3000</span>
</span></code></pre>
<p>Repare que o programa continuou a execução. Vamos ver a resposta que está em RAX:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rax</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x4                 4</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Um número diferente do sockfd, que é o socket criado pelo server</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">sockfd</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402010</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>sockfd<span class="keyword operator assignment redirection shell">&gt;</span>:      0x00000003</span>

</span></code></pre>
<p>Podemos ver que é um número diferente (RAX contém 4 e sockfd contém 3). De acordo com a documentação, este é o número do descritor que representa um novo socket criado para comunicação entre <em>um cliente específico e o servidor</em>.</p>
<p>Vamos mover o valor de RAX para R8, apenas para preservar o socket, uma vez que RAX será usado novamente por outras syscalls de accept:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov r8, rax             ; client socket
</span></code></pre><h3 id="resposta-do-servidor-e-fechamento-da-conexão">Resposta do servidor e fechamento da conexão</h3>
<p>Uma outra coisa importante a se fazer é <strong>fechar a conexão</strong> com este socket do cliente depois de ter processado e respondido a requisição.</p>
<p>Vamos implementar a subrotina <code>.write</code>, que escreve a resposta na conexão (socket) do cliente:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>

<span class="keyword operator symbolic actionscript 2">%</span>define CR <span class="constant numeric actionscript 2">0xD</span>
<span class="keyword operator symbolic actionscript 2">%</span>define LF <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">data</span>
<span class="support function actionscript 2">response</span><span class="keyword operator symbolic actionscript 2">:</span> 
	headline<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>HTTP/1.1 200 OK<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	content_type<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Content-Type: text/html<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	content_length<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Content-Length: 22<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	crlf<span class="keyword operator symbolic actionscript 2">:</span> db CR, LF
	body<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>&lt;h1&gt;Hello, World!&lt;/h1&gt;<span class="punctuation definition string end actionscript 2">&quot;</span></span>
responseLen<span class="keyword operator symbolic actionscript 2">:</span> equ $ <span class="keyword operator symbolic actionscript 2">-</span> <span class="support function actionscript 2">response</span>

section .<span class="support function actionscript 2">text</span>
...
.write<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> write(<span class="support function actionscript 2">int</span> fd, buffer <span class="keyword operator symbolic actionscript 2">*</span>bf, <span class="support function actionscript 2">int</span> bfLen)
	mov rdi, r8
	mov rsi, <span class="support function actionscript 2">response</span>
	mov rdx, responseLen
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>No exemplo acima, assumimos que a string de resposta HTTP aponta para uma estrutura na memória, definida em <code>.data</code>.</p>
<blockquote>
<p>Atenção para CR (carriage return), LF (line feed) que são constantes que representam <code>\r\n </code> que são separadores de linhas definidos pelo protocolo HTTP</p>
</blockquote>
<p>Agora, definir a subrotina <code>.close</code>, que fecha a conexão com o cliente:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="keyword operator symbolic actionscript 2">%</span>define SYS_close <span class="constant numeric actionscript 2">3</span>

section .<span class="support function actionscript 2">text</span>
...
.<span class="support function actionscript 2">close</span><span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">close</span>(<span class="support function actionscript 2">int</span> fd)
	mov rdi, r8
	mov rax, SYS_close
	syscall
	ret
</span></code></pre>
<p>Ligando tudo no <em>accept</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">text</span>
....
.accept<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> accept(<span class="support function actionscript 2">int</span> sockfd, struct <span class="keyword operator symbolic actionscript 2">*</span>addr, <span class="support function actionscript 2">int</span> addrlen, <span class="support function actionscript 2">int</span> flags)
	mov rdi, [sockfd]
	mov rsi, <span class="constant numeric actionscript 2">0</span>              ; não precisa estabelecer um addr
	mov rdx, <span class="constant numeric actionscript 2">0</span>              ; não precisa <span class="keyword control actionscript 2">do</span> tamanho uma vez que não há addr
	mov r10, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_accept
	syscall
	mov r8, rax             ; client socket
	<span class="support function actionscript 2">call</span> .write             ; escreve no socket
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">close</span>             ; fecha o socket
	jmp .exit               ; termina o programa
</span></code></pre>
<p>E agora, vamos executar o programa com <em>strace</em>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./live</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7ffd811567c0 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">listen</span></span><span class="meta function-call arguments shell">(3, 2</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                            <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span>
</span></code></pre>
<ul>
<li>
<p>primeiro foi feita a syscall <em>socket</em></p>
</li>
<li>
<p>a seguir foi feito o <em>bind</em></p>
</li>
<li>
<p>depois o <em>listen</em></p>
</li>
<li>
<p>e por fim, o <em>accept</em> ficou bloqueado a espera de uma requisição</p>
</li>
</ul>
<p>Em outra janela, vamos fazer a requisição:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> curl localhost:3000</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>
</span></span></code></pre>
<p>E no servidor, a saída do strace no final ficou assim:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">close</span></span><span class="meta function-call arguments shell">(4</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">exit</span></span><span class="meta function-call arguments shell">(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                 <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">+++</span></span><span class="meta function-call arguments shell"> exited with 0 +++</span>
</span></code></pre>
<p>Escreveu a resposta com <code>write</code>, fechou a conexão com <code>close</code>, e depois terminou o programa com <code>exit</code>.</p>
<p><em>Como não ficar feliz?</em></p>
<h3 id="mas-o-servidor-deve-ficar-em-loop-não">Mas o servidor deve ficar em loop, não?</h3>
<p>Sim, o servidor deve ficar em loop, portanto ao invés de fazer o <code>jmp .exit</code>, fazemos <code>jmp .accept</code> na última linha da procedure:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">...
.accept<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> accept(<span class="support function actionscript 2">int</span> sockfd, struct <span class="keyword operator symbolic actionscript 2">*</span>addr, <span class="support function actionscript 2">int</span> addrlen, <span class="support function actionscript 2">int</span> flags)
	mov rdi, [sockfd]
	mov rsi, <span class="constant numeric actionscript 2">0</span>              ; não precisa estabelecer um addr
	mov rdx, <span class="constant numeric actionscript 2">0</span>              ; não precisa <span class="keyword control actionscript 2">do</span> tamanho uma vez que não há addr
	mov r10, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_accept
	syscall
	mov r8, rax             ; client socket
	<span class="support function actionscript 2">call</span> .write
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">close</span>
	jmp .accept             ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> MUDANÇA AQUI, mantém o <span class="support function actionscript 2">server</span> em loop infinito
</span></code></pre>
<p>Assim, o server nunca termina, e quando uma conexão com um cliente é fechada, voltamos no início do loop e ficamos a espera de nova conexão na syscall <em>accept</em>.</p>
<p>Código final do server:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_socket <span class="constant numeric actionscript 2">41</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_bind <span class="constant numeric actionscript 2">49</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_listen <span class="constant numeric actionscript 2">50</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_accept <span class="constant numeric actionscript 2">288</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_close <span class="constant numeric actionscript 2">3</span>

<span class="keyword operator symbolic actionscript 2">%</span>define AF_INET <span class="constant numeric actionscript 2">2</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SOCK_STREAM <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SOCK_PROTOCOL <span class="constant numeric actionscript 2">0</span>
<span class="keyword operator symbolic actionscript 2">%</span>define BACKLOG <span class="constant numeric actionscript 2">2</span>
<span class="keyword operator symbolic actionscript 2">%</span>define CR <span class="constant numeric actionscript 2">0xD</span>
<span class="keyword operator symbolic actionscript 2">%</span>define LF <span class="constant numeric actionscript 2">0xA</span>

; Data types <span class="support function actionscript 2">in</span> asm
; byte <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">1</span> byte
; word <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">2</span> bytes
; doubleword <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">4</span> bytes
; quadword <span class="keyword operator symbolic actionscript 2">=</span>&gt; <span class="constant numeric actionscript 2">8</span> bytes

section .<span class="support function actionscript 2">data</span>
sockaddr<span class="keyword operator symbolic actionscript 2">:</span> 
	family<span class="keyword operator symbolic actionscript 2">:</span> dw AF_INET   ; <span class="constant numeric actionscript 2">2</span> bytes
	port<span class="keyword operator symbolic actionscript 2">:</span> dw <span class="constant numeric actionscript 2">0xB80B</span>      ; <span class="constant numeric actionscript 2">2</span> bytes (<span class="constant numeric actionscript 2">47115</span> big endian becomes <span class="constant numeric actionscript 2">3000</span> little endian)
	ip_address<span class="keyword operator symbolic actionscript 2">:</span> dd <span class="constant numeric actionscript 2">0</span>     ; <span class="constant numeric actionscript 2">4</span> bytes
	sin_zero<span class="keyword operator symbolic actionscript 2">:</span> dq <span class="constant numeric actionscript 2">0</span>       ; <span class="constant numeric actionscript 2">8</span> bytes
sockaddrLen<span class="keyword operator symbolic actionscript 2">:</span> equ $ <span class="keyword operator symbolic actionscript 2">-</span> sockaddr
<span class="support function actionscript 2">response</span><span class="keyword operator symbolic actionscript 2">:</span> 
	headline<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>HTTP/1.1 200 OK<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	content_type<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Content-Type: text/html<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	content_length<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Content-Length: 22<span class="punctuation definition string end actionscript 2">&quot;</span></span>, CR, LF
	crlf<span class="keyword operator symbolic actionscript 2">:</span> db CR, LF
	body<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>&lt;h1&gt;Hello, World!&lt;/h1&gt;<span class="punctuation definition string end actionscript 2">&quot;</span></span>
responseLen<span class="keyword operator symbolic actionscript 2">:</span> equ $ <span class="keyword operator symbolic actionscript 2">-</span> <span class="support function actionscript 2">response</span>

section .bss
sockfd<span class="keyword operator symbolic actionscript 2">:</span> resb <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
.socket<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> socket(<span class="support function actionscript 2">int</span> <span class="support function actionscript 2">domain</span>, <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">type</span>, <span class="support function actionscript 2">int</span> protocol)
	mov rdi, AF_INET
	mov rsi, SOCK_STREAM
	mov rdx, SOCK_PROTOCOL
	mov rax, SYS_socket
	syscall
	mov [sockfd], rax 
.bind<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> bind(<span class="support function actionscript 2">int</span> sockfd, const struct sockaddr <span class="keyword operator symbolic actionscript 2">*</span>addr, socklen_t addrlen)
	mov rdi, [sockfd]
	mov rsi, sockaddr
	mov rdx, sockaddrLen
	mov rax, SYS_bind
	syscall
.listen<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> listen(<span class="support function actionscript 2">int</span> sockfd, <span class="support function actionscript 2">int</span> backlog)
	mov rdi, [sockfd]
	mov rsi, BACKLOG
	mov rax, SYS_listen
	syscall
.accept<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> accept(<span class="support function actionscript 2">int</span> sockfd, struct <span class="keyword operator symbolic actionscript 2">*</span>addr, <span class="support function actionscript 2">int</span> addrlen, <span class="support function actionscript 2">int</span> flags)
	mov rdi, [sockfd]
	mov rsi, <span class="constant numeric actionscript 2">0</span>              ; não precisa estabelecer um addr
	mov rdx, <span class="constant numeric actionscript 2">0</span>              ; não precisa <span class="keyword control actionscript 2">do</span> tamanho uma vez que não há addr
	mov r10, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_accept
	syscall
	mov r8, rax             ; client socket
	<span class="support function actionscript 2">call</span> .write
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">close</span>
	jmp .accept
.write<span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> write(<span class="support function actionscript 2">int</span> fd, buffer <span class="keyword operator symbolic actionscript 2">*</span>bf, <span class="support function actionscript 2">int</span> bfLen)
	mov rdi, r8
	mov rsi, <span class="support function actionscript 2">response</span>
	mov rdx, responseLen
	mov rax, SYS_write
	syscall
	ret
.<span class="support function actionscript 2">close</span><span class="keyword operator symbolic actionscript 2">:</span>
	; <span class="support function actionscript 2">int</span> <span class="support function actionscript 2">close</span>(<span class="support function actionscript 2">int</span> fd)
	mov rdi, r8
	mov rax, SYS_close
	syscall
	ret
</span></code></pre>
<p>Executando tudo com <em>strace</em> e temos:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./live</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./live<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7fff9fde7840 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">socket</span></span><span class="meta function-call arguments shell">(AF_INET, SOCK_STREAM, IPPROTO_IP</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">3</span></span>
<span class="meta function-call shell"><span class="variable function shell">bind</span></span><span class="meta function-call arguments shell">(3, <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>sa_family=AF_INET<span class="punctuation separator shell">,</span> sin_port=htons(3000)<span class="punctuation separator shell">,</span> sin_addr=inet_addr(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>0.0.0.0<span class="punctuation definition string end shell">&quot;</span></span>)<span class="punctuation section expansion brace end shell">}</span></span>, 16</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">listen</span></span><span class="meta function-call arguments shell">(3, 2</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                            <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">close</span></span><span class="meta function-call arguments shell">(4</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">close</span></span><span class="meta function-call arguments shell">(4</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>               <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(4, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>HTTP/1.1 200 OK\r\nContent-Type: t<span class="punctuation definition string end shell">&quot;</span></span>..., 86</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">86</span></span>
<span class="meta function-call shell"><span class="variable function shell">close</span></span><span class="meta function-call arguments shell">(4</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">accept4</span></span><span class="meta function-call arguments shell">(3, NULL, NULL, 0</span>
</span></code></pre>
<p>No lado do cliente:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> curl localhost:3000</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>
</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> curl localhost:3000</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>
</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> curl localhost:3000</span>
<span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="keyword operator assignment redirection shell">&lt;</span>h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>Hello, World!<span class="keyword operator assignment redirection shell">&lt;</span>/h<span class="constant numeric integer decimal file-descriptor shell">1</span><span class="keyword operator assignment redirection shell">&gt;</span>
</span></span></code></pre><h3 id="com-vocês-o-web-browser">Com vocês, o web browser</h3>
<p>Esta saga não teria nenhuma graça se não fosse pra ser executada em um <em>web browser</em>, afinal estamos falando de um <strong>web server</strong>, não?</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qm4v5vqi8jw5578sajjy.png" alt="final hello world" /></p>
<hr />
<h2 id="conclusão">Conclusão</h2>
<p>Incrivelmente chegamos no final da construção de um modesto web server. Aqui aprendemos conceitos sobre sockets, TCP e HTTP, com uma pitada leve de HTML.</p>
<blockquote>
<p>Fala aí, quem não já conhecia a tag H1 do HTML? kk</p>
</blockquote>
<p>Para além de termos visto sobre as syscalls de rede <em>socket, bind, listen e accept</em> em Assembly.</p>
<p>Ainda não chegamos ao fim da saga, pelo que no próximo artigo iremos abordar a criação de <strong>threads</strong> e aprender sobre alocação dinâmica de memória para as threads.</p>
<p>Stay tuned!</p>
<p><em>Agradecimentos a <a href="https://x.com/rodrigogbranco">Rodrigo Gonçalves de Branco</a> por ter revisado este artigo com o devido rigor</em></p>
<hr />
<h2 id="referências">Referências</h2><sub>
Building a web server in Bash
https://leandronsp.com/articles/tekton-ci-part-i-a-gentle-introduction-ilj
OSI Model
https://en.wikipedia.org/wiki/OSI_model
TCP
https://en.wikipedia.org/wiki/Transmission_Control_Protocol
Berkeley Sockets
https://en.wikipedia.org/wiki/Berkeley_sockets
HTTP
https://en.wikipedia.org/wiki/HTTP
struct sockaddr_in
https://www.gta.ufrj.br/ensino/eel878/sockets/sockaddr_inman.html
</sub>
]]></description>
<pubDate>2024-05-25</pubDate>
</item>
<item>
<title>Construindo um web server em Assembly x86, parte IV, um assembly modesto</title>
<link>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iv-um-assembly-modesto-oif.html</link>
<guid>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iv-um-assembly-modesto-oif.html</guid>
<description><![CDATA[<p>Uma vez que temos <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iii-codigo-de-maquina-bgk">uma compreensão</a> sobre sistema binário, hexadecimal, ASCII e código de máquina, chegou o grande momento de entrarmos no assunto principal desta saga: <strong>assembly</strong>.</p>
<p>Vamos iniciar transportando o "Hello, World" feito em código de máquina para assembly x86 e, posteriormente, abordar um exemplo de programa que recebe argumento da linha de comando.</p>
<p>Ao longo deste artigo vamos aprender a base de conceitos como rótulos, segmentos de memória, <em>muito gdb</em>, layout de memória, <strong>muita stack</strong>, procedures (subrotinas, ou <em>funções</em>), loops, condicionais, flags, tipos de registradores e etc</p>
<p>Aperte os cintos, pois este será um artigo bem extenso. Sugiro ao leitor, - que tem interesse em aprender na prática com esta saga -, que tenha o ambiente preparado e que execute cada exemplo seguindo os passos aqui descritos.</p>
<p>Sem mais delongas, vamos ao que importa.</p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#humanizar-%C3%A9-preciso">Humanizar é preciso</a></p>
<ul>
<li><a href="#mnemonics">Mnemonics</a></li>
</ul>
</li>
<li>
<p><a href="#assemblers">Assemblers</a></p>
</li>
<li>
<p><a href="#nosso-primeiro-programa">Nosso primeiro programa</a></p>
<ul>
<li><a href="#a-chamada-de-sistema-exit">A chamada de sistema exit</a></li>
<li><a href="#arquivos-objeto">Arquivos Objeto</a></li>
<li><a href="#linker">Linker</a></li>
</ul>
</li>
<li>
<p><a href="#depurando-o-programa">Depurando o programa</a></p>
<ul>
<li><a href="#o-utilit%C3%A1rio-size">O utilitário size</a></li>
<li><a href="#debugging-com-gdb">Debugging com gdb</a></li>
<li><a href="#rastreando-execu%C3%A7%C3%A3o-com-strace">Rastreando execução com strace</a></li>
</ul>
</li>
<li>
<p><a href="#evoluindo-nosso-primeiro-programa">Evoluindo nosso primeiro programa
</a></p>
<ul>
<li><a href="#alocando-bytes-para-hello-world">Alocando bytes para "Hello, World"</a></li>
<li><a href="#adicionando-a-chamada-de-sistema-write">Adicionando a chamada de sistema write</a></li>
<li><a href="#layout-de-mem%C3%B3ria">Layout de memória</a></li>
<li><a href="#definindo-constantes">Definindo constantes</a></li>
</ul>
</li>
<li>
<p><a href="#um-programa-mais-sofisticado">Um programa mais sofisticado</a></p>
<ul>
<li><a href="#definindo-labels">Definindo labels</a></li>
<li><a href="#desvio-de-fluxo-com-jump">Desvio de fluxo com jump</a></li>
<li><a href="#desvio-de-fluxo-com-call">Desvio de fluxo com call</a></li>
<li><a href="#brincando-com-pilhas">Brincando com pilhas</a></li>
<li><a href="#calculando-tamanho-dinamicamente-com-loop">Calculando tamanho dinamicamente com loop</a></li>
<li><a href="#rflags">RFLAGS</a></li>
<li><a href="#botando-mais-pilha-no-neg%C3%B3cio">Botando mais pilha no negócio</a></li>
<li><a href="#depurando-o-programa-final-com-strace">Depurando o programa final com strace</a></li>
</ul>
</li>
<li>
<p><a href="#falando-um-pouco-de-registradores">Falando um pouco de registradores</a></p>
<ul>
<li><a href="#prop%C3%B3sito-dos-registradores">Propósito dos registradores</a></li>
<li><a href="#registradores-de-prop%C3%B3sito-geral">Registradores de propósito geral</a></li>
<li><a href="#registradores-especiais">Registradores especiais</a></li>
<li><a href="#precisamos-sempre-utilizar-todos-os-64-bits">Precisamos sempre utilizar todos os 64 bits?</a></li>
</ul>
</li>
<li>
<p><a href="#uma-side-note-sobre-stack-frames">Uma side note sobre stack frames</a></p>
</li>
<li>
<p><a href="#conclus%C3%A3o">Conclusão</a></p>
</li>
<li>
<p><a href="#refer%C3%AAncias">Referências</a></p>
</li>
</ul>
<hr />
<blockquote>
<p>Antes de iniciar, quero novamente deixar uma menção especial ao excelente <a href="https://www.youtube.com/watch?v=Ej6U-qk0bdE&amp;list=PLXoSGejyuQGohd0arC7jRBqVdQqf5GqKJ">curso gratuito de Assembly x86</a> do <a href="https://www.youtube.com/@debxp">Blau Araújo</a>. É importante reforçar o quanto este material dele é necessário e foi crucial para que eu pudesse fundamentar diversos conceitos explorados ao longo desta saga</p>
</blockquote>
<h2 id="humanizar-é-preciso">Humanizar é preciso</h2>
<p>Como vimos no artigo anterior, CPU só entende código de máquina:</p>
<pre><code class="sourceCode"><span class="text plain">48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 0A  ; Hello, World

BF 01 00 00 00     ; RDI ⬅️ 1
48 BE 00 10 40     ; RSI ⬅️ 0x401000
BA 0D 00 00 00     ; RDX ⬅️ 13
B8 01 00 00 00     ; RAX ⬅️ 1
0F 05              ; SYSCALL
BF 00 00 00 00     ; RDI ⬅️ 0
B8 3C 00 00 00     ; RAX ⬅️ 60
0F 05              ; SYSCALL
</span></code></pre>
<p>Entretanto, para uma pessoa desenvolvedora manter um programa em código de máquina, é preciso ter muita paciência e atenção ao detalhe, pelo que também manter programas assim é muito propenso a bugs.</p>
<p>Precisamos de alguma forma, representar cada instrução em código de máquina em uma linguagem mais "human-friendly".</p>
<h3 id="mnemonics">Mnemonics</h3>
<p>É aí que entram os <strong>mnemonics</strong>, que são uma forma textual de representar informações visando facilitar a memorização para o cérebro humano.</p>
<p>Ao invés de trabalharmos com <code>BF 01 00 00 00</code>, podemos trocar por <code>MOV RDI, 1</code>, que significa:</p>
<blockquote>
<p>estou movendo o valor imediato 1 para o registrador RDI</p>
</blockquote>
<p>E assim vamos <em>montando</em> instrução por instrução, tal e qual faríamos com código de máquina, mas utilizando uma <em>linguagem</em> de fácil memorização.</p>
<p>Mas a CPU não entende essa "linguagem". Temos de construir um <em>programa</em> que faz a <em>tradução</em> de mnemonics para <em>código de máquina</em>, ou seja, de <code>MOV RSI, 1</code> para <code>BF 01 00 00 00</code>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m7zzy20fad71wg461cpt.png" alt="assembly" /></p>
<p>Estamos falando de <em>montadores</em>, ou simplesmente <strong>assemblers</strong>.</p>
<hr />
<h2 id="assemblers">Assemblers</h2>
<p>Ao longo do tempo, foram desenvolvidos diversos assemblers para diferentes arquiteturas.</p>
<p>Para arquitetura x86, há diversos assemblers já construídos, GNU Assembler (as), NASM, FASM, pra mencionar alguns.</p>
<p>Assemblers para esta arquitetura em específico podem seguir 2 tipos de sintaxe que são predominantes:</p>
<ul>
<li>
<p>AT&amp;T, desenvolvida pela AT&amp;T corporation</p>
</li>
<li>
<p>Intel, desenvolvida pela Intel</p>
</li>
</ul>
<p>Nesta saga, vamos focar no Assembler <strong>NASM</strong> para arquitetura X86 64-bits (x64), com <em>sintaxe Intel</em> e rodando em sistema GNU/Linux, como já mencionamos algumas vezes em artigos anteriores.</p>
<ul>
<li>
<p>Arquitetura x86_64 (x64)</p>
</li>
<li>
<p>Sistema Operacional GNU/Linux (Ubuntu)</p>
</li>
<li>
<p>Assembler NASM 2.16.01</p>
</li>
<li>
<p>GNU ld 2.38 (ligador, ou linker)</p>
</li>
<li>
<p>Debugger GNU gdb 12.1</p>
</li>
<li>
<p>strace 5.16 (tracing de syscalls)</p>
</li>
</ul>
<p>Uma vez que definimos as ferramentas utilizadas, vamos seguir traduzindo o "Hello, World" para asm x86 enquanto entendemos o uso de cada uma delas.</p>
<blockquote>
<p>A partir de agora, quando me referir a Assembly ou simplesmente "asm", leia-se <em>Assembly x86_64</em></p>
</blockquote>
<hr />
<h2 id="nosso-primeiro-programa">Nosso primeiro programa</h2>
<p>Em Assembly, todo programa deve ter um ponto de entrada, também chamado de <strong>entry point</strong>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

_start<span class="keyword operator symbolic actionscript 2">:</span>
	; código <span class="keyword control actionscript 2">do</span> programa vai aqui
</span></code></pre>
<p>E a primeira coisa que nosso programa vai fazer é sair:</p>
<blockquote>
<p>kkkkkkkkkk</p>
</blockquote>
<h3 id="a-chamada-de-sistema-exit">A chamada de sistema exit</h3>
<p>Brincadeiras à parte, a chamada de sistema que precisamos executar é a <code>exit</code>, definida da seguinte forma no <code>glibc</code>:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="storage type c">void</span> <span class="meta function c"><span class="entity name function c">_exit</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="storage type c">int</span> <span class="variable parameter c">status</span><span class="punctuation section group end c">)</span></span></span><span class="punctuation terminator c">;</span>
</span></code></pre>
<p>Com isto, temos de seguir a lógica para montar as instruções tal como fizemos com os opcodes, que seguindo  <a href="https://x64.syscall.sh/">a mesma tabela de syscalls</a>, é:</p>
<ul>
<li>
<p>nome da syscall vai em RAX</p>
</li>
<li>
<p>primeiro argumento (o status de erro) vai em RDI</p>
</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>   ; error <span class="support function actionscript 2">status</span>
	mov rax, <span class="constant numeric actionscript 2">60</span>  ; nome da syscall<span class="keyword operator symbolic actionscript 2">:</span> SYS_exit
	syscall       
</span></code></pre>
<p>Este programa simplesmente faz aquilo que mencionamos no artigo anterior: <em>que todo programa deve terminar</em>.</p>
<ul>
<li>
<p><code>mov rdi, 0</code> move o valor imediato 1 para o registrador RDI; vai representar o error code da syscall <strong>exit</strong>: 0 para término sem erros</p>
</li>
<li>
<p><code>mov rax, 60</code> move o valor imediato 60 para o registrador RAX; vai representar o nome da syscall em si, <strong>exit</strong></p>
</li>
<li>
<p><code>syscall</code> faz a chamada de sistema da syscall <strong>exit</strong>, definida em RAX</p>
</li>
</ul>
<p>Para que o programa seja compilado, precisamos primeiro fazer a "montagem" das instruções com NASM:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> nasm<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>f</span> elf64 hello.asm<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>o</span> hello.o</span>
</span></code></pre>
<ul>
<li>
<p><code>-f elf64</code>: arquitetura de destino, x64</p>
</li>
<li>
<p><code>hello.asm</code> input, ou seja, o arquivo que contém o código fonte</p>
</li>
<li>
<p><code>-o hello.o</code>: define saída para o arquivo <code>hello.o</code></p>
</li>
</ul>
<blockquote>
<p>Mas o quê é este arquivo <code>hello.o</code>?</p>
</blockquote>
<h3 id="arquivos-objeto">Arquivos objeto</h3>
<p>Arquivo objeto (<strong>Object File</strong>) é um arquivo que contém código de máquina gerado por um assembler ou compilador.</p>
<p>Porém este arquivo ainda não é um <em>executável</em> final, porque podemos querer combinar com outros arquivos objeto e bibliotecas nativas do SO.</p>
<p>A partir deste arquivo, que geralmente tem a extensão <code>.o</code>, podemos utilizar outro programa para "ligar" com outros arquivos, se necessário, no intuito de gerar um arquivo com código de máquina final e executável.</p>
<p>Este programa se chama <strong>linker</strong>, pelo que utilizaremos a versão padrão do <code>ld</code> que vem com o GNU no nosso sistema operacional GNU/Linux.</p>
<h3 id="linker">Linker</h3>
<p><em>Linker</em> é o programa responsável por, a partir de um ou mais arquivos objeto, gerar um arquivo final executável com o código de máquina.</p>
<p>Como já geramos anteriormente o arquivo objeto <code>hello.o</code> utilizando o assembler NASM, podemos concluir o processo de compilação do nosso programa fonte asm x86 com <code>ld</code></p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ld hello.o<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>o</span> hello</span>
</span></code></pre>
<p>E agora, vamos rodar o binário final executável <code>hello</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ./hello</span>
<span class="meta function-call shell"><span class="support function echo shell">echo</span></span><span class="meta function-call arguments shell"> <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable language shell">?</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0</span></span>
</span></code></pre>
<p><em>Hurray!</em> Nosso primeiro programa em Assembly concluído com sucesso!</p>
<p>Contudo, vamos lembrar de um ponto importante que vimos na parte II da saga: que o <em>programa e seus dados ficam na memória</em>. Queremos entender <strong>o que está acontecendo na memória</strong> com este simples programa.</p>
<hr />
<h2 id="depurando-o-programa">Depurando o programa</h2>
<p>Uma das etapas mais importantes, senão a mais  importante, em desenvolvimento de software, é a <em>depuração</em> (ou debugging, em inglês).</p>
<p>Depurar é o ato de conseguir interceptar a execução do programa, analisar o estado, alterar o estado, adicionar pontos de parada (breakpoints) entre outras técnicas.</p>
<p>O processo de depuração também consiste em analisar a saída do programa como um todo, seu tamanho e trace de chamadas no sistema operacional.</p>
<h3 id="o-utilitário-size">O utilitário size</h3>
<p>Vamos iniciar o processo de depuração do nosso programa analisando o tamanho, com o utilitário GNU <em>size</em>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> size hello</span>

   <span class="meta function-call shell"><span class="variable function shell">text</span></span><span class="meta function-call arguments shell">    data     bss     dec     hex filename</span>
     <span class="meta function-call shell"><span class="variable function shell">12</span></span><span class="meta function-call arguments shell">       0       0      12       c hello</span>
</span></code></pre>
<blockquote>
<p>Mas o quê significa "text, data, bss, etc"?</p>
</blockquote>
<p>Cada programa no sistema operacional é dividido em <em>seções</em>, que representam alguma característica para o sistema operacional.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lv9edus1e9nxw4b24cxq.png" alt="layout de memória" /></p>
<p><strong>text</strong>
Esta seção contém todo o código fonte do programa, e assim o SO sabe que precisa buscar esta seção na memória principal</p>
<p><strong>data</strong>
Seção de dados inicializados na memória</p>
<p><strong>bss</strong>
Seção de dados não-inicializados na memória</p>
<p>O comando <strong>size</strong> traz justamente o tamanho (em bytes) de cada seção.</p>
<blockquote>
<p><code>dec</code> e <code>hex</code> não são seções, são apenas a representação do valor total (em bytes) tanto em decimal quanto hexadecimal</p>
</blockquote>
<ul>
<li>
<p><code>text</code>: esta seção contém todo o código fonte do nosso programa, também chamado de "texto"</p>
</li>
<li>
<p><code>data</code>: seção de dados inicializados, logo a seguir neste artigos entramos em detalhe</p>
</li>
<li>
<p><code>bss</code>: seção de dados não-inicializados, logo a seguir também falaremos deste</p>
</li>
<li>
<p><code>dec</code>: o tamanho total em decimal</p>
</li>
<li>
<p><code>hex</code>: o tamanho total em hexadecimal</p>
</li>
</ul>
<p>Nosso programa por enquanto só tem a seção text, que é exatamente todo o código a partir do rótulo <code>_start</code>.</p>
<blockquote>
<p>Nossa, Leandro, nosso programa tem apenas 12 bytes?</p>
</blockquote>
<p>Aparentemente sim. Vamos confirmar:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ls<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>lh</span> hello</span>

<span class="meta function-call shell"><span class="variable function shell">......</span></span><span class="meta function-call arguments shell"> 4.6K ... hello</span>
</span></code></pre>
<blockquote>
<p>Como assim o arquivo tem 4,6Kb? O programa não ocupa 12 bytes apenas?</p>
</blockquote>
<p>Bom, isto ocorre por causa dos headers que são adicionados pelo linker, que contém informação relevante para que o sistema operacional possa admitir a execução do arquivo.</p>
<p>Vamos novamente utilizar o comando <code>size</code> mas desta vez:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> size<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> --</span>format</span> sysv<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> --</span>radix</span> 16 hello</span>

<span class="meta function-call shell"><span class="variable function shell">hello</span></span><span class="meta function-call arguments shell">  :</span>
<span class="meta function-call shell"><span class="variable function shell">section</span></span><span class="meta function-call arguments shell">   size       addr</span>
<span class="meta function-call shell"><span class="variable function shell">.text</span></span><span class="meta function-call arguments shell">    0xc   0x401000</span>
<span class="meta function-call shell"><span class="variable function shell">Total</span></span><span class="meta function-call arguments shell">    0xc</span>
</span></code></pre>
<p>A opção <code>--format</code> indica o formato <code>sysv</code> que traz também os símbolos. E a opção <code>--radix 16</code> permite visualizar o tamanho de cada seção em hexadecimal.</p>
<p>Na seção size, <code>0xc</code> representa o número 12 em decimal. Nada de novo aqui. Mas se repararmos na coluna <code>addr</code>, temos um valor hexadecimal para a seção text (0x401000).</p>
<p>Já vimos isto no artigo anterior, que <code>0x401000</code> se referia ao endereço em hexadecimal de memória virtual que indica o início do programa, lembra?</p>
<p>Hora de confirmar isto com uma análise mais profunda na depuração, chegou o momento de utilizarmos GNU <em>gdb</em>.</p>
<h3 id="debugging-com-gdb">Debugging com GDB</h3>
<p>GDB é um depurador (<em>debugger</em> em inglês) que permite ver o que está acontecendo dentro de um programa <em>em execução</em>.</p>
<p>Com um depurador, podemos analisar as informações estáticas contidas no binário do programa, estabelecer <em>breakpoints</em> (pontos de parada) em qualquer parte do código, executar e analisar mudanças de estado do programa durante sua execução.</p>
<p>Para habilitar o programa com <code>gdb</code>, precisamos montar o programa com a opção <code>-g</code>, que exporta símbolos necessários para depuração:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> nasm<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>g</span><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>f</span> elf64 hello.asm<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>o</span> hello.o</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ld hello.o<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>o</span> hello</span>
</span></code></pre>
<p>Podemos verificar os símbolos exportados no binário com o comando size novamente:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> size<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> --</span>format</span> sysv<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> --</span>radix</span> 16 hello</span>

<span class="meta function-call shell"><span class="variable function shell">hello</span></span><span class="meta function-call arguments shell">  :</span>
<span class="meta function-call shell"><span class="variable function shell">section</span></span><span class="meta function-call arguments shell">           size       addr</span>
<span class="meta function-call shell"><span class="variable function shell">.text</span></span><span class="meta function-call arguments shell">              0xc   0x401000</span>
<span class="meta function-call shell"><span class="variable function shell">.debug_aranges</span></span><span class="meta function-call arguments shell">    0x30        0x0</span>
<span class="meta function-call shell"><span class="variable function shell">.debug_info</span></span><span class="meta function-call arguments shell">       0x75        0x0</span>
<span class="meta function-call shell"><span class="variable function shell">.debug_abbrev</span></span><span class="meta function-call arguments shell">     0x1d        0x0</span>
<span class="meta function-call shell"><span class="variable function shell">.debug_line</span></span><span class="meta function-call arguments shell">       0x3d        0x0</span>
<span class="meta function-call shell"><span class="variable function shell">Total</span></span><span class="meta function-call arguments shell">            0x10b</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">#############</span><span class="comment line number-sign shell">
</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ls<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>lh</span> hello</span>
<span class="meta function-call shell"><span class="variable function shell">......</span></span><span class="meta function-call arguments shell"> 5.1K ... hello</span>
</span></code></pre>
<p>Como demonstrado acima, o binário agora contém seções adicionais de "debug" que serão utilizadas pelo <em>gdb</em>, e consequentemente o tamanho do programa teve um acréscimo de <del>500MB</del> 512 bytes!</p>
<p>Sem mais delongas, vamos entrar no <code>gdb</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> gdb<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> --</span>quiet</span></span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>E agora, dentro do shell gdb, podemos utilizar diversos comandos de depuração. O comando <code>help</code> traz a lista de <em>classes de comandos</em> disponíveis:</p>
<pre><code class="sourceCode"><span class="text plain">help

...
aliases -- User-defined aliases of other commands.
breakpoints -- Making program stop at certain points.
data -- Examining data.
files -- Specifying and examining files.
internals -- Maintenance commands.
obscure -- Obscure features.
running -- Running the program.
stack -- Examining the stack.
status -- Status inquiries.
support -- Support facilities.
text-user-interface -- TUI is the GDB text based interface.
tracepoints -- Tracing of program execution without stopping the program.
user-defined -- User-defined commands.
...
</span></code></pre>
<blockquote>
<p>Para o escopo deste artigo vamos utilizar apenas alguns comandos para depuração, mas a lista de comandos disponíveis é <a href="https://visualgdb.com/gdbreference/commands/">gigante</a>. Deixo o desafio ao leitor para se aventurar com o <code>help</code> do gdb e brincar de depurar qualquer binário executável</p>
</blockquote>
<p>Como queremos depurar o binário <em>hello</em>, podemos carregar os símbolos utilizando o comando <code>file</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> file hello</span>
<span class="meta function-call shell"><span class="variable function shell">Reading</span></span><span class="meta function-call arguments shell"> symbols from hello...</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>O comando <code>info files</code> traz alguns insights:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> info files</span>
<span class="meta function-call shell"><span class="variable function shell">Symbols</span></span><span class="meta function-call arguments shell"> from <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>/code/asm-x64/hello<span class="punctuation definition string end shell">&quot;</span></span>.</span>
<span class="meta function-call shell"><span class="variable function shell">Local</span></span><span class="meta function-call arguments shell"> exec file:</span>
        <span class="meta function-call shell"></span><span class="meta function-call arguments shell"><span class="meta group expansion command backticks shell"><span class="punctuation section group begin shell">`</span><span class="meta function-call shell"><span class="variable function shell">/code/asm-x64/hello<span class="string quoted single shell"><span class="punctuation definition string begin shell">&#39;</span>, file type elf64-x86-64.
        Entry point: 0x401000
        0x0000000000401000 - 0x000000000040100c is .text
(gdb)
</span></span></span></span></span></span></code></pre>
<p>Que interessante! O entry point do programa começa justamente em <code>0x401000</code>, que é o que está definido na seção <code>.text</code>.</p>
<p>Para visualizar o código fonte do programa, utilizamos o comando <code>list</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> list</span>
<span class="meta function-call shell"><span class="variable function shell">1</span></span><span class="meta function-call arguments shell">       global _start</span>
<span class="meta function-call shell"><span class="variable function shell">2</span></span>
<span class="meta function-call shell"><span class="variable function shell">3</span></span><span class="meta function-call arguments shell">       _start:</span>
<span class="meta function-call shell"><span class="variable function shell">4</span></span><span class="meta function-call arguments shell">               mov rdi, 0</span>   <span class="keyword operator logical continue shell">;</span> <span class="meta function-call shell"><span class="variable function shell">error</span></span><span class="meta function-call arguments shell"> code</span>
<span class="meta function-call shell"><span class="variable function shell">5</span></span><span class="meta function-call arguments shell">               mov rax, 60</span>  <span class="keyword operator logical continue shell">;</span> <span class="meta function-call shell"><span class="variable function shell">SYS_exit</span></span>
<span class="meta function-call shell"><span class="variable function shell">6</span></span><span class="meta function-call arguments shell">               syscall</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<blockquote>
<p>Lembrando que o programa ainda não está em execução, estamos apenas analisando o binário executável com o gdb</p>
</blockquote>
<p>Com o comando <code>x</code>, de <em>examine</em>, podemos examinar o rótulo <code>_start</code> que é o ponto de entrada do programa:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x _start</span>
<span class="meta function-call shell"><span class="variable function shell">0x401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>:      0x000000bf</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>Se quisermos executar o programa, podemos fazê-lo com o comando <code>run</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>
<span class="meta function-call shell"><span class="variable function shell">Starting</span></span><span class="meta function-call arguments shell"> program: /code/asm-x64/hello</span>
<span class="meta function-call shell"><span class="variable function shell">[Inferior</span></span><span class="meta function-call arguments shell"> 1 (process 7991</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="meta function-call shell"><span class="variable function shell">exited</span></span><span class="meta function-call arguments shell"> normally]</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>Entretanto, podemos definir breakpoints antes de executar, assim temos controle do estado do programa <strong>em execução</strong>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Aqui, definimos um ponto de parada no rótulo _start_</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break _start</span>
<span class="meta function-call shell"><span class="variable function shell">Breakpoint</span></span><span class="meta function-call arguments shell"> 1 at 0x401000: file hello.asm, line 4.</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Info sobre breakpoints</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> info breakpoints</span>
<span class="meta function-call shell"><span class="variable function shell">Num</span></span><span class="meta function-call arguments shell">     Type           Disp Enb Address            What</span>
<span class="meta function-call shell"><span class="variable function shell">1</span></span><span class="meta function-call arguments shell">       breakpoint     keep y   0x0000000000401000 hello.asm:4</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>Agora sim, vamos executar:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>
<span class="meta function-call shell"><span class="variable function shell">Starting</span></span><span class="meta function-call arguments shell"> program: /code/asm-x64/hello</span>

<span class="meta function-call shell"><span class="variable function shell">Breakpoint</span></span><span class="meta function-call arguments shell"> 1, _start (</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="meta function-call shell"><span class="variable function shell">at</span></span><span class="meta function-call arguments shell"> hello.asm:4</span>
<span class="meta function-call shell"><span class="variable function shell">4</span></span><span class="meta function-call arguments shell">               mov rdi, 0</span>   <span class="keyword operator logical continue shell">;</span> <span class="meta function-call shell"><span class="variable function shell">error</span></span><span class="meta function-call arguments shell"> code</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>O programa está parado na linha 4 como solicitado. Esta linha no código <strong>não foi avaliada</strong>, pelo que podemos analisar e alterar o estado do programa:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Neste momento o valor no registrador RDI está 0 (default)</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> info register rdi</span>
<span class="meta function-call shell"><span class="variable function shell">rdi</span></span><span class="meta function-call arguments shell">            0x0                 0</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Mudamos o valor do registrador para 42</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> set <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rdi</span></span> = 42</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Agora verificamos que foi modificado diretamente do GDB</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> info register rdi</span>
<span class="meta function-call shell"><span class="variable function shell">rdi</span></span><span class="meta function-call arguments shell">            0x2a                42</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>Para avaliar a linha atual, utilizamos o comando <code>next</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>
<span class="meta function-call shell"><span class="variable function shell">5</span></span><span class="meta function-call arguments shell">               mov rax, 60</span>  <span class="keyword operator logical continue shell">;</span> <span class="meta function-call shell"><span class="variable function shell">SYS_exit</span></span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> E podemos agora verificar que o valor de RDI foi modificado para 0, </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> conforme descrito no programa</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> info register rdi</span>
<span class="meta function-call shell"><span class="variable function shell">rdi</span></span><span class="meta function-call arguments shell">            0x0                 0</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>Poderíamos continuar indo linha a linha com <code>next</code>, ou então continuar a execução do programa com <code>continue</code> que pára no próximo ponto de parada ou executa todas as instruções que faltam até terminar o programa.</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Inicia execução e pára no primeiro breakpoint definido</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>
<span class="meta function-call shell"><span class="variable function shell">Starting</span></span><span class="meta function-call arguments shell"> program: /Users/leandronsp/Documents/code/asm-x64/hello</span>

<span class="meta function-call shell"><span class="variable function shell">Breakpoint</span></span><span class="meta function-call arguments shell"> 1, _start (</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="meta function-call shell"><span class="variable function shell">at</span></span><span class="meta function-call arguments shell"> hello.asm:4</span>
<span class="meta function-call shell"><span class="variable function shell">4</span></span><span class="meta function-call arguments shell">               mov rdi, 0</span>   <span class="keyword operator logical continue shell">;</span> <span class="meta function-call shell"><span class="variable function shell">error</span></span><span class="meta function-call arguments shell"> code</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Continua execução. Neste caso termina o programa pois</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> não há mais breakpoints a partir deste ponto</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>
<span class="meta function-call shell"><span class="variable function shell">Continuing.</span></span>
<span class="meta function-call shell"><span class="variable function shell">[Inferior</span></span><span class="meta function-call arguments shell"> 1 (process 8000</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="meta function-call shell"><span class="variable function shell">exited</span></span><span class="meta function-call arguments shell"> normally]</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>Pronto, terminamos a demonstração do primeiro programa com <code>gdb</code>. Para sair, utilizamos o comando <code>exit</code>.</p>
<h3 id="rastreando-execução-com-strace">Rastreando execução com strace</h3>
<p>O utilitário <code>strace</code> permite rastrear todas as chamadas de sistema e sinais que um programa faz. É bastante útil quando queremos saber o que pode ter acontecido com determinada <em>syscall</em>, quais parâmetros foram enviados e o que a syscall retornou.</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./hello</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./hello<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./hello<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7ffc504b5710 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">exit</span></span><span class="meta function-call arguments shell">(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                 <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">+++</span></span><span class="meta function-call arguments shell"> exited with 0 +++</span>
</span></code></pre>
<p>Vamos entender a saída do <strong>strace</strong> por partes.</p>
<p><em><em>execve("./hello", ["./hello"], 0x7ffc504b5710 /</em> 24 vars <em>/) = 0:</em></em></p>
<ul>
<li>
<p><code>execve</code> é uma chamada do Linux que executa um determinado programa</p>
</li>
<li>
<p><code>./hello</code> é o caminho para o programa que será executado</p>
</li>
<li>
<p><code>["./hello"]</code> é a lista de argumentos passados para o programa. Como só há o nome do programa (que entra na lista <em>ARGV</em>), indica que este programa não recebe argumentos extras na linha de comando</p>
</li>
<li>
<p><code>0x7ffc504b5710</code> é o endereço de memória onde as variáveis de ambiente do processo em execução estão armazenadas</p>
</li>
<li>
<p><code>/* 24 vars */</code> indica que há 24 variáveis de ambiente definidas no shell atual</p>
</li>
<li>
<p><code>=0</code> é o resultado da chamada <code>execve</code>, o que significa que foi bem-sucedido e executado com sucesso</p>
</li>
</ul>
<p><strong>exit(0) = ?:</strong></p>
<ul>
<li>
<p><code>exit</code> é a chamada de sistema (syscall) feita no sistema operacional, e geralmente é definida no <code>libc</code>, sendo no caso de sistema GNU, <code>glibc</code>. Foi o valor <em>60</em> passado para o registrador RAX, lembra?</p>
</li>
<li>
<p><code>(0)</code> é o parâmetro passado para a função, que neste caso foi o que determinamos no registrador RDI, indicando que nosso programa em execução vai terminar <em>sem erros</em></p>
</li>
<li>
<p><code>= ?</code> indica que o resultado da chamada de sistema não é conhecido, ou seja não houve um retorno <em>explícito</em> de valor da chamada de sistema</p>
</li>
</ul>
<p><strong>+++ exited with 0 +++:</strong></p>
<ul>
<li>
<p><code>+++</code> sinaliza o início de uma mensagem de saída do strace</p>
</li>
<li>
<p><code>exited with 0</code> indica que o programa terminou sem erros</p>
</li>
<li>
<p><code>+++</code> sinaliza o fim da mensagem de saída</p>
</li>
</ul>
<p>Uma vez que entendemos como depurar nosso programa, podemos evolui-lo para imprimir a mensagem "Hello, World" na saída do terminal.</p>
<hr />
<h2 id="evoluindo-nosso-primeiro-programa">Evoluindo nosso primeiro programa</h2>
<p>Vamos agora evoluir o programa anterior para que possamos imprimir a mensagem "Hello, World" na saída padrão <code>STDOUT</code>.</p>
<p>Para isto, conforme vimos na parte III da saga, "Código de Máquina", vamos por partes.</p>
<h3 id="alocando-bytes-para-hello-world">Alocando bytes para "Hello, World"</h3>
<p>Precisamos primeiro definir os bytes de cada caracter da string em <em>hexadecimal</em> de acordo com a tabela ASCII, que resulta em <code>48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 0A</code>.</p>
<blockquote>
<p>0x48 para "H", 0x65 para "e", 0x6C para "l" e assim por diante...</p>
</blockquote>
<p>Portanto, se quisermos evoluir o primeiro programa que contém apenas a syscall <code>exit</code>, podemos começar por definir a string utilizando a diretiva <code>db</code> que significa <em>define byte</em>, utilizando o endereço do primeiro byte em um rótulo que iremos chamar de <em>msg</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0x48</span>, <span class="constant numeric actionscript 2">0x65</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x6F</span>, \
		<span class="constant numeric actionscript 2">0x2C</span>, <span class="constant numeric actionscript 2">0x20</span>, <span class="constant numeric actionscript 2">0x57</span>, <span class="constant numeric actionscript 2">0x6F</span>, <span class="constant numeric actionscript 2">0x72</span>, \
		<span class="constant numeric actionscript 2">0x6C</span>, <span class="constant numeric actionscript 2">0x64</span>, <span class="constant numeric actionscript 2">0xA</span>

_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>   ; error code
	mov rax, <span class="constant numeric actionscript 2">60</span>  ; SYS_exit
	syscall       
</span></code></pre>
<p>Antes de sair adicionando mais código, vamos utilizar o <code>gdb</code> para analisar o que esta mudança provoca na memória:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Examinar o que há no rótulo msg</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x msg</span>
<span class="meta function-call shell"><span class="variable function shell">0x401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>msg<span class="keyword operator assignment redirection shell">&gt;</span>: 0x6c6c6548</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Examinar o que há no rótulo _start</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x _start</span>
<span class="meta function-call shell"><span class="variable function shell">0x40100d</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>:      0x000000bf</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p>Ora ora, o que temos aqui?</p>
<ul>
<li>
<p><code>msg</code> aponta para o endereço <code>0x401000</code> que era o endereço usado pelo <code>_start</code> no nosso programa anterior</p>
</li>
<li>
<p>e agora <code>_start</code> aponta para outro endereço, <code>0x40100d</code> que está <strong>13 bytes</strong> ("d" em hexa) acima de <code>msg</code>, exatamente os 13 bytes da string "Hello, World" adicionado com quebra de linha!!!!!1</p>
</li>
</ul>
<blockquote>
<p>Superb! Mas o que significa o valor <code>0x6c6c6548</code>?</p>
</blockquote>
<p>Se analisarmos com calma, dá pra perceber que se trata dos caracteres da string em ASCII segundo o que foi definido no programa. Mas eles estão <em>invertidos</em>, lembra de endianness que foi explicado no artigo anterior?</p>
<p>Então, esta arquitetura segue o padrão little-endian, onde os bytes são armazenados na ordem inversa, do menos relevante (expoentes menores da base 2) para o mais relevante (expoentes maiores).</p>
<p>Voltando ao gdb, podemos confirmar que todos os bytes da string estão alocados trabalhando com ponteiros de 4 em 4 bytes:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x msg</span>
<span class="meta function-call shell"><span class="variable function shell">0x401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>msg<span class="keyword operator assignment redirection shell">&gt;</span>: 0x6c6c6548</span> <span class="keyword operator logical continue shell">;</span> <span class="meta function-call shell"><span class="variable function shell">Hell</span></span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x msg+4</span>
<span class="meta function-call shell"><span class="variable function shell">0x401004:</span></span><span class="meta function-call arguments shell">       0x57202c6f</span> <span class="keyword operator logical continue shell">;</span> <span class="meta function-call shell"><span class="variable function shell">o,</span></span><span class="meta function-call arguments shell"> W</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x msg+8</span>
<span class="meta function-call shell"><span class="variable function shell">0x401008:</span></span><span class="meta function-call arguments shell">       0x646c726f</span> <span class="keyword operator logical continue shell">;</span> <span class="meta function-call shell"><span class="variable function shell">orld</span></span>
</span></code></pre>
<p>Ou então, o comando <code>x</code> permite passar uma quantidade junto com o formato de apresentação, por exemplo queremos que traga os primeiros <em>13 hexabytes</em> a partir do ponteiro <strong>msg</strong>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/13xb msg</span>
<span class="meta function-call shell"><span class="variable function shell">0x401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>msg<span class="keyword operator assignment redirection shell">&gt;</span>: 0x48    0x65    0x6c    0x6c    0x6f    0x2c    0x20    0x57</span>
<span class="meta function-call shell"><span class="variable function shell">0x401008:</span></span><span class="meta function-call arguments shell">       0x6f    0x72    0x6c    0x64    0x0a</span>
</span></code></pre>
<p>Exatamente os hexadecimais da string "Hello, World" com quebra de linha!</p>
<p>Mas em Assembly, não precisamos definir os bytes de uma string em hexadecimal. Podemos utilizar os <em>quotes literais</em>, assim o programa fica menos verboso e o assembler faz o processo de traduzir o caracter para o hexadecimal da tabela ASCII:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello, World<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>
</span></code></pre>
<blockquote>
<p>Não conseguimos representar a quebra de linha dentro de quotes literais, então vamos manter esta com 0xA</p>
</blockquote>
<h3 id="adicionando-a-chamada-de-sistema-write">Adicionando a chamada de sistema write</h3>
<p>Como já sabemos, o programa precisa utilizar a syscall <code>write</code> para escrever na saída, que está definida da seguinte forma no <code>glibc</code>:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="support type sys-types c">ssize_t</span> <span class="meta function c"><span class="entity name function c">write</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="storage type c">int</span> <span class="variable parameter c">fd</span><span class="punctuation separator c">,</span> <span class="storage modifier c">const</span> <span class="storage type c">void</span> <span class="variable parameter c">buf</span><span class="meta brackets c"><span class="punctuation section brackets begin c">[</span><span class="punctuation accessor c">.</span><span class="variable other member c">count</span><span class="punctuation section brackets end c">]</span></span><span class="punctuation separator c">,</span> <span class="support type sys-types c">size_t</span> <span class="variable parameter c">count</span><span class="punctuation section group end c">)</span></span></span><span class="punctuation terminator c">;</span>
</span></code></pre>
<ul>
<li>
<p>nome da syscall vai em RAX</p>
</li>
<li>
<p>primeiro argumento (file descriptor, no caso o <em>STDOUT</em>) vai em RDI</p>
</li>
<li>
<p>segundo argumento (ponteiro para o início do buffer) vai em RSI</p>
</li>
<li>
<p>terceiro argumento (quantidade de bytes a serem escritos) vai em RDX</p>
</li>
</ul>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello, World<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; Chamada de sistema
	; glibc <span class="keyword operator symbolic actionscript 2">-</span>&gt; ssize_t write(<span class="support function actionscript 2">int</span> fd, 
							 const <span class="support function actionscript 2">void</span> buf[.count], 
							 size_t count)
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	mov rdi, <span class="constant numeric actionscript 2">1</span>   ; STDOUT
	mov rsi, msg ; ponteiro para o início da string
	mov rdx, <span class="constant numeric actionscript 2">13</span>  ; quantidade de bytes a serem escritos
	mov rax, <span class="constant numeric actionscript 2">1</span>   ; nome da syscall<span class="keyword operator symbolic actionscript 2">:</span> SYS_write
	syscall      ; chamada de sistema

	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	; Chamada de sistema
	; glibc <span class="keyword operator symbolic actionscript 2">-</span>&gt; <span class="support function actionscript 2">void</span> _exit(<span class="support function actionscript 2">int</span> <span class="support function actionscript 2">status</span>)
	;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	mov rdi, <span class="constant numeric actionscript 2">0</span>   ; erro de saída
	mov rax, <span class="constant numeric actionscript 2">60</span>  ; nome da syscall<span class="keyword operator symbolic actionscript 2">:</span> SYS_exit
	syscall           
</span></code></pre>
<p>Ao compilar o programa com <code>nasm + ld</code>, seguindo a mesma lógica do primeiro programa, temos de fato a saída tão desejada:</p>
<pre><code class="sourceCode"><span class="text plain">$ ./hello
Hello, World
</span></code></pre>
<p><em>Yay! que dia maravilhoso!</em></p>
<p>Vamos ver como fica o trace disso tudo agora?</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./hello</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./hello<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./hello<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7fff139437f0 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(1, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Hello, World\n<span class="punctuation definition string end shell">&quot;</span></span>, 13Hello, World</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>          <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">13</span></span>
<span class="meta function-call shell"><span class="variable function shell">exit</span></span><span class="meta function-call arguments shell">(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                 <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">+++</span></span><span class="meta function-call arguments shell"> exited with 0 +++</span>
</span></code></pre>
<p>Wow, podemos ver que, agora, o programa executa primeiro a syscall <code>write</code>, que retorna o valor <code>13</code>, que é quantidade de bytes escritos <em>com sucesso</em>; e a seguir executa a syscall <code>exit</code>, também com sucesso, indicando que nosso programa imprime a string na saída e termina sem erros.</p>
<p>Como ficou o tamanho do programa agora?</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> size hello</span>

   <span class="meta function-call shell"><span class="variable function shell">text</span></span><span class="meta function-call arguments shell">    data     bss     dec     hex filename</span>
     <span class="meta function-call shell"><span class="variable function shell">52</span></span><span class="meta function-call arguments shell">       0       0      52      34 hello</span>
</span></code></pre>
<p>Hmm, parece que a seção <code>text</code> aumentou de tamanho, que é a adição da string "Hello, World" e das instruções para a syscall <code>write</code>. Mas por enquanto é a única seção existente:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> size<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> --</span>format</span> sysv<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> --</span>radix</span> 16 hello</span>

<span class="meta function-call shell"><span class="variable function shell">hello</span></span><span class="meta function-call arguments shell">  :</span>
<span class="meta function-call shell"><span class="variable function shell">section</span></span><span class="meta function-call arguments shell">           size       addr</span>
<span class="meta function-call shell"><span class="variable function shell">.text</span></span><span class="meta function-call arguments shell">             0x34   0x401000</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">omitindo</span></span><span class="meta function-call arguments shell"> seções de debug</span><span class="punctuation definition compound end shell">)</span>
<span class="meta function-call shell"><span class="variable function shell">Total</span></span><span class="meta function-call arguments shell">            0x139</span>

</span></code></pre>
<p>Podemos ver que a string definida no rótulo <code>msg</code>, que começa no endereço <code>0x401000</code> está contida na seção <code>.text</code>.</p>
<blockquote>
<p>Isto é um problema?</p>
</blockquote>
<p>Mais ou menos:</p>
<ol>
<li>O rótulo <code>msg</code> , que é um "dado", contendo a string, está definido num endereço de memória <strong>anterior</strong>, ou seja, em endereço de memória mais baixo em direção a 0</li>
<li>O rótulo <code>_start</code>, que é o início do programa, está definido num endereço <strong>posterior</strong>, ou seja, em endereço de memória mais alto com relação à string</li>
</ol>
<p>No sistema operacional, todo programa é encapsulado em um processo tal como vimos no artigo anterior. E sendo um processo, é submetido a um "layout" que deve seguir algumas regras.</p>
<h3 id="layout-de-memória">Layout de memória</h3>
<p>Fazendo paralelo com a saída do comando <code>size</code>, a memória do programa segue um layout, que basicamente contém as seguintes seções, ou <em>segmentos</em> de memória:</p>
<ul>
<li>
<p>text</p>
</li>
<li>
<p>data</p>
</li>
<li>
<p>bss</p>
</li>
</ul>
<p>Já falamos disto anteriormente neste artigo, mas basicamente na seção <code>text</code> fica todo o código, instruções do programa.</p>
<p>Na seção <code>data</code>, ficam dados inicializados (aqui deveria estar a nossa string). E na seção <code>bss</code> vão os dados não-inicializados, mas já com uma área pré-alocada na memória.</p>
<p>Em termos de <strong>espaço virtual de memória</strong> do programa, a seção <code>text</code> deve ficar nos endereços de memória mais baixos, próximos ao entry point <code>0x401000</code>.</p>
<p>Com isto, o programa deve crescer a partir da seção <code>text</code> em direção a <code>data</code> e <code>bss</code>, dos menores endereços de memória para os maiores (da esquerda pra direita):</p>
<pre><code class="sourceCode"><span class="text plain">text -&gt; data -&gt; bss
</span></code></pre>
<p>Ou então, analisando numa imagem em vertical, de baixo pra cima:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yy0iqqbaz3ox378srcw6.png" alt="layout de memoria 2" /></p>
<p>Existem mais seções no layout mas vamos adicioná-las à medida que avançamos no artigo. Por agora, como nosso programa está tratando dados (<code>msg</code>) como <code>text</code>, devemos colocar na seção correta, que é <code>data</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

; segmento de dados (endereços mais altos)
section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello, World<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>

; segmento de texto (endereços mais baixos)
section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">1</span>   ; STDOUT
	mov rsi, msg ; ponteiro para o início da string
	mov rdx, <span class="constant numeric actionscript 2">13</span>  ; quantidade de bytes a serem escritos
	mov rax, <span class="constant numeric actionscript 2">1</span>   ; nome da syscall<span class="keyword operator symbolic actionscript 2">:</span> SYS_write
	syscall      ; chamada de sistema

	mov rdi, <span class="constant numeric actionscript 2">0</span>   ; erro de saída
	mov rax, <span class="constant numeric actionscript 2">60</span>  ; nome da syscall<span class="keyword operator symbolic actionscript 2">:</span> SYS_exit
	syscall  
</span></code></pre>
<p>Com <code>gdb</code>, podemos conferir que agora estamos obedecendo o layout de memória estabelecido para o programa:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x _start</span>
<span class="meta function-call shell"><span class="variable function shell">0x401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>:      0x000000bf</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x</span> <span class="keyword operator logical job shell">&amp;</span><span class="meta function-call shell"><span class="variable function shell">msg</span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>msg<span class="keyword operator assignment redirection shell">&gt;</span>: 0x6c6c6548</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<blockquote>
<p>Note que para acessar <code>msg</code> no segmento de dados, precisamos examinar através da <em>referência</em>, com o operador <code>&amp;</code></p>
</blockquote>
<h3 id="definindo-constantes">Definindo constantes</h3>
<p>Em Assembly podemos definir constantes que podem ser reutilizadas em diversas partes do programa, evitando assim alguma redundância com repetição de código e valores.</p>
<p>A diretiva <code>%define</code> permite definir valores constantes tanto para string quanto números:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_STATUS <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define NEWLINE <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello, World<span class="punctuation definition string end actionscript 2">&quot;</span></span>, NEWLINE

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, msg 
	mov rdx, <span class="constant numeric actionscript 2">13</span>
	mov rax, SYS_write
	syscall      

	mov rdi, EXIT_STATUS
	mov rax, SYS_exit
	syscall  
</span></code></pre>
<p>Podemos também definir uma constante baseada em uma expressão aritmética. Por exemplo, ao invés de deixarmos o tamanho em bytes com valor fixo <em>13</em>, podemos fazer que isto seja calculado com base em aritmética de ponteiros na memória com a diretiva <code>equ</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">...
section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello, World<span class="punctuation definition string end actionscript 2">&quot;</span></span>, NEWLINE
msgLen<span class="keyword operator symbolic actionscript 2">:</span> equ $ <span class="keyword operator symbolic actionscript 2">-</span> msg
...
</span></code></pre>
<p>O operador <code>$</code> tem o ponteiro de memória para o último byte no programa, no caso o <code>NEWLINE</code> definido na linha anterior. Ao subtrair do ponteiro <code>msg</code> com a expressão <code>$ - msg</code>, temos o tamanho em bytes calculado e desta forma não precisa ser um valor fixo em RDX:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define EXIT_STATUS <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define NEWLINE <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">data</span>
msg<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hello, World<span class="punctuation definition string end actionscript 2">&quot;</span></span>, NEWLINE
msgLen<span class="keyword operator symbolic actionscript 2">:</span> equ $ <span class="keyword operator symbolic actionscript 2">-</span> msg

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, msg 
	mov rdx, msgLen
	mov rax, SYS_write
	syscall      

	mov rdi, EXIT_STATUS
	mov rax, SYS_exit
	syscall  
</span></code></pre>
<p><em>Wonderful! Nosso programa agora tá muito mais elegante!</em></p>
<p>Ufa, parece que terminamos o nosso primeiro programa e este por si só já foi uma jornada longa. Mas tenha um pouco mais de paciência, <strong>vem comigo</strong>, pois chegou o momento de escrevermos um programa um pouco mais sofisticado.</p>
<p>Hora de explorar mais funcionalidades no Assembly e entrar no mundo da <em>stack</em>.</p>
<hr />
<h2 id="um-programa-mais-sofisticado">Um programa mais sofisticado</h2>
<p>Vamos começar por um programa simples e evoluindo conforme depuramos e entendemos a memória. Ao fim, o programa deve ser capaz de receber um nome através dos argumentos da linha de comando e imprimir "Hi, <code>&lt;nome&gt;</code>".</p>
<p>Desejado:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ./greeting Leandro</span>
<span class="meta function-call shell"><span class="variable function shell">Hi,</span></span><span class="meta function-call arguments shell"> Leandro</span>
</span></code></pre><h3 id="definindo-labels">Definindo labels</h3>
<p>Já sabemos que o programa precisa imprimir "Hi, " alguma coisa. Então as instruções pra syscall <code>write</code> são necessárias, e já fazendo uso de constantes:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, greet
	mov rdx, <span class="constant numeric actionscript 2">3</span>
	mov rax, SYS_write
	syscall
	
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
</span></code></pre>
<p>Este programa imprime "Hi" apenas. Mas podemos melhorar a organização separando em blocos com algum valor <em>semântico</em>:</p>
<ul>
<li>
<p>separar o bloco de <code>exit</code></p>
</li>
<li>
<p>separar o bloco de <code>write</code></p>
</li>
</ul>
<p>Assembly emprega o conceito de <strong>labels</strong>, que são rótulos, mas que podem ser definidas em qualquer parte do código. Utilizando o caracter <em>ponto</em> (<code>.</code>), o programa fica bem mais expressivo:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, greet
	mov rdx, <span class="constant numeric actionscript 2">3</span>
	mov rax, SYS_write
	syscall
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
</span></code></pre>
<p>Assim como qualquer rótulo, o programa vai executando top-down. O que fizemos aqui foi apenas colocar rótulos em determinadas partes do programa, mas sem <em>alterar seu fluxo de execução</em>.</p>
<h3 id="desvio-de-fluxo-com-jump">Desvio de fluxo com jump</h3>
<p>Se quisermos alterar o fluxo de execução, podemos utilizar a instrução <code>JMP</code> que altera o fluxo do programa para outro ponto, continuando <em>a partir desde novo ponto</em>.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	; Faz o jump para a <span class="support function actionscript 2">label</span> .<span class="support function actionscript 2">print</span>, sem passar por .exit
	jmp .<span class="support function actionscript 2">print</span>
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, greet
	mov rdx, <span class="constant numeric actionscript 2">3</span>
	mov rax, SYS_write
	syscall
	
	; Faz o jump para a <span class="support function actionscript 2">label</span> .exit, caso contrário o programa não terminaria
	; da forma adequada (todo programa deve terminar)
	jmp .exit
</span></code></pre>
<p>Este foi um exemplo bastante simples com jump e desvio de fluxo. Mas é possível também desviar o fluxo, executar a lógica do novo fluxo, e <em>retornar</em> ao ponto anterior.</p>
<p>Entretanto, para que isto funcione, vamos imaginar uma possível solução:</p>
<ul>
<li>
<p>definir algum registrador "especial" que guarda sempre o ponteiro da próxima instrução</p>
</li>
<li>
<p>antes de desviar o fluxo, guardar o endereço de memória da próxima instrução do programa em alguma <em>estrutura de dados</em> para que possa ser resgatado quando a lógica do desvio terminar</p>
</li>
</ul>
<p>Sim, estamos falando do desvio com <code>call</code>, <code>ret</code>, registradores e pilha.</p>
<h3 id="desvio-de-fluxo-com-call">Desvio de fluxo com call</h3>
<p>Tendo o exemplo anterior, ao invés de fazer <code>jmp</code>, vamos utilizar a instrução <code>call</code> que faz o desvio para outra rotina:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>  ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> chamada da rotina
</span></code></pre>
<p>Além disso, a última linha da rotina <code>.print</code> deve "retornar" o fluxo desviado para o ponto anterior.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, greet
	mov rdx, <span class="constant numeric actionscript 2">3</span>
	mov rax, SYS_write
	syscall
	ret  ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> retorno da rotina
</span></code></pre>
<p>Antes de analisarmos com <code>gdb</code> passo a passo, precisamos entender um aspecto importante dos programas no sistema operacional.</p>
<p>Quando um programa é executado, ele é definido em uma estrutura chamada <strong>processo</strong> (já falamos disto no artigo anterior). Todo processo carrega o layout de memória definido no binário do programa, conforme vimos anteriormente:</p>
<pre><code class="sourceCode"><span class="text plain">text -&gt; data -&gt; bss
</span></code></pre>
<p>Nos endereços mais <em>altos</em> da memória virtual do processo (programa em execução), o sistema operacional também define uma outra estrutura de dados, chamada <strong>stack</strong>, que tem um formato de pilha (LIFO, Last In, First Out).</p>
<pre><code class="sourceCode"><span class="text plain">text -&gt; data -&gt; bss ---------&gt; &lt;-------- stack
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z7lyluh9a4hqkzl3yo7s.png" alt="layout de memória com stack" /></p>
<p>A stack fica nos endereços mais altos e carrega informações como argumentos do programa, lista de variáveis de ambiente definidas no <em>shell</em>, argumentos para funções entre qualquer informação pertinente para o programa. Stack sempre cresce <em>para baixo</em> em direção aos endereços menores.</p>
<p><strong>rsp</strong>
Em um programa Assembly x86, é preciso armazenar o ponteiro atual do topo da stack, e esta informação fica no registrador RSP, ou <em>stack pointer</em>.</p>
<p><strong>rip</strong>
Já o ponteiro da instrução atual fica no registrador RIP, ou <em>instruction pointer</em>.</p>
<p>Com estes dois registradores conseguimos demonstrar o uso de call e ret para desvio de fluxo. Voltando ao programa:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>     ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> desvio <span class="keyword control actionscript 2">do</span> fluxo
	
	; aqui neste ponto, já continua a execução normal em direção ao exit
	; para terminar o programa
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, greet
	mov rdx, <span class="constant numeric actionscript 2">3</span>
	mov rax, SYS_write
	syscall
	ret            ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> retorno ao ponto anterior
</span></code></pre>
<p>E agora demonstrando com <code>gdb</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> gdb greeting</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint em _start, início do programa</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break _start_</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RIP apontando para 0x401000 (_start), o entry point do programa</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> info register <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rip</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">rip</span></span><span class="meta function-call arguments shell">            0x401000            0x401000 <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>
</span>
<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RSP apontando para um endereço de memória</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Se formos examinar com x $rsp, temos</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> 0x7fffffffe450: 0x00000001, que é a quantidade de argumentos</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> passados, no caso 1 representa apenas o nome do programa, ou seja</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> não há argumentos na linha de comando</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">rsp</span></span><span class="meta function-call arguments shell">            0x7fffffffe450      0x7fffffffe450</span>
</span></code></pre>
<p>Até aqui okay, agora vamos andar um <code>step</code> para que o desvio de <code>call</code> seja avaliado e analisar o RIP:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> step</span>
<span class="meta function-call shell"><span class="variable function shell">18</span></span><span class="meta function-call arguments shell">              mov rdi, STDOUT</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O RIP andou conforme esperado</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rip</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">rip</span></span><span class="meta function-call arguments shell">            0x401011            0x401011 <span class="keyword operator assignment redirection shell">&lt;</span>_start.print<span class="keyword operator assignment redirection shell">&gt;</span>
</span>
<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RIP apontando para 0x000001bf, que é BF 01 00 00 </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Lembra? é o opcode pra MOV RDI, 1</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Exatamente onde paramos</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rip</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x401011</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start.print<span class="keyword operator assignment redirection shell">&gt;</span>:        0x000001bf</span>
</span></code></pre>
<p>E a stack (RSP) como ficou?</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> A pilha andou alguns bytes (no caso foi feito um &quot;push&quot;, o que a fez crescer para endereços de memórias menores)</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Lembra? Pilha &quot;cresce pra baixo&quot; na memória</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rsp</span>
<span class="meta function-call shell"><span class="variable function shell">rsp</span></span><span class="meta function-call arguments shell">            0x7fffffffe448      0x7fffffffe448</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Opaaa, o que temos aqui? 0x00401005</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> É alguma pista...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe448:</span></span><span class="meta function-call arguments shell"> 0x00401005</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Examinando o ponteiro do início do programa...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x _start</span>
<span class="meta function-call shell"><span class="variable function shell">0x401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>:      0x00000ce8</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Se andarmos alguns bytes, </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> temos exatamente o endereço da label .exit, 0x401005</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x _start + 5</span>
<span class="meta function-call shell"><span class="variable function shell">0x401005</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start.exit<span class="keyword operator assignment redirection shell">&gt;</span>: 0x000000bf</span>
</span></code></pre>
<p>Se você prestou atenção nos comentários do snippet acima...</p>
<blockquote>
<p>É muito importante prestar atenção em todos os comentários, se não estiver fazendo isso, volte o artigo do início e tente acompanhar <em>no terminal</em>, é extremamente importante para entender os conceitos</p>
</blockquote>
<p>...se prestarmos a devida atenção, este é o endereço que tá no topo da pilha agora, que foi adicionado pela instrução <code>call</code>.</p>
<blockquote>
<p>Ok Leandro, mas como fazemos então para voltar ao ponto anterior?</p>
</blockquote>
<p>Calma, jovem. Estamos parados no início da rotina <code>.print</code>. Vamos continuar a depuração com <code>gdb</code> até parar em <code>ret</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>
<span class="meta function-call shell"><span class="variable function shell">19</span></span><span class="meta function-call arguments shell">              mov rsi, greet</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>
<span class="meta function-call shell"><span class="variable function shell">20</span></span><span class="meta function-call arguments shell">              mov rdx, 3</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>
<span class="meta function-call shell"><span class="variable function shell">21</span></span><span class="meta function-call arguments shell">              mov rax, SYS_write</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>
<span class="meta function-call shell"><span class="variable function shell">22</span></span><span class="meta function-call arguments shell">              syscall</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>
<span class="meta function-call shell"><span class="variable function shell">Hi</span></span>
<span class="meta function shell"><span class="entity name function shell">_start.print</span> <span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> at greeting.asm:23
23              ret
<span class="punctuation section parens begin shell">(</span>gdb<span class="punctuation section parens end shell">)</span>
</span></span></code></pre>
<p>Nice, antes de avaliar a instrução <code>ret</code>, podemos ver que RIP andou mas RSP continua na mesma, com o endereço da próxima instrução antes do desvio:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RIP aponta para a instrução da linha &quot;ret&quot;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rip</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x40102c</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start.print+<span class="constant numeric integer decimal file-descriptor shell">27</span><span class="keyword operator assignment redirection shell">&gt;</span>:     0x000000c3</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RSP aponta para o endereço de memória que está a instrução .exit, que</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> vem a seguir ao desvio feito com &quot;call&quot; lá em cima</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe448:</span></span><span class="meta function-call arguments shell"> 0x00401005</span>
</span></code></pre>
<p>Vamos andar com <code>ret</code> e....</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RIP agora aponta para 0x401005, que é a instrução .exit</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rip</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x401005</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start.exit<span class="keyword operator assignment redirection shell">&gt;</span>: 0x000000bf</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Foi feito &quot;pop&quot; em RSP e agora este aponta para o topo da pilha</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> com o valor exato quando estava no início do programa</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe450:</span></span><span class="meta function-call arguments shell"> 0x00000001</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span>
</span></code></pre>
<p><em>OMG!! Acabamos de demonstrar manipulação de registradores e pilhas</em>.</p>
<h3 id="brincando-com-pilhas">Brincando com pilhas</h3>
<p><em>Pilhas é divertido.</em></p>
<blockquote>
<p>Mas prefiro filas, gosto de tratar as coisas de modo ordenado. Quem chega primeiro precisa ser atendido primeiro kkkkkkkk</p>
</blockquote>
<p>Mas com pilhas não é assim. Quem entra por último sai primeiro.</p>
<p>Com base nisto, como podemos manipular a stack do programa? Vamos alterar um pouco o código adicionando o ponteiro de <code>greet</code> na stack:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">push</span> greet    ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> adiciona o ponteiro de greet na stack
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, greet
	mov rdx, <span class="constant numeric actionscript 2">3</span>
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>No <code>gdb</code>, vamos colocar um breakpoint na linha da chamada <code>call</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na linha 13</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> b 13</span>
<span class="meta function-call shell"><span class="variable function shell">Breakpoint</span></span><span class="meta function-call arguments shell"> 1 at 0x401005: file greeting.asm, line 13.</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Run</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> r</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Examinando o topo da pilha</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe448:</span></span><span class="meta function-call arguments shell"> 0x00402000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Examinando o endereço de memória que tá no topo da pilha</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x 0x00402000</span>
<span class="meta function-call shell"><span class="variable function shell">0x402000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>greet<span class="keyword operator assignment redirection shell">&gt;</span>:       0x2c0a6948</span>
</span></code></pre>
<p><em>Cool</em>, temos <code>0x48 0x69 0x0A</code> (little-endian), exatamente a string "Hi" seguida de uma quebra de linha. Com esta rica informação, ao invés da rotina <code>.print</code> passar pro registrador RSI o ponteiro de <code>greet</code>, porque não passar o ponteiro do topo da pilha?</p>
<p>Algo nessa linha:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; ao invés disso (atual)
mov rsi, greet

; que tal mover o ponteiro que tá em rsp (topo da pilha) para rsi
mov rsi, rsp
</span></code></pre>
<p>Por enquanto, seguramos esta ideia no bolso. Ainda no <code>gdb</code>, vamos continuar analisando a pilha depois de entrar na rotina:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> step</span>
<span class="meta function shell"><span class="entity name function shell">_start.print</span> <span class="punctuation section parens begin shell">(</span><span class="punctuation section parens end shell">)</span> at greeting.asm:19

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Agora o topo da pilha foi modificado, &quot;call&quot; colocou o endereço de </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> memória da próxima instrução quando voltar do &quot;ret&quot;</span><span class="comment line number-sign shell">
</span><span class="punctuation section parens begin shell">(</span>gdb<span class="punctuation section parens end shell">)</span> x $rsp
0x7fffffffe440: 0x0040100a

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O endereço de memória aponta justamente pra próxima instrução quando voltar do &quot;ret&quot;, no caso a instrução que tá na label .exit do programa</span><span class="comment line number-sign shell">
</span><span class="punctuation section parens begin shell">(</span>gdb<span class="punctuation section parens end shell">)</span> x 0x0040100a
0x40100a &lt;_start.exit&gt;: 0x000000bf
</span></span></code></pre>
<p>Mas agora o topo da pilha estraga nossa ideia de fazer <code>mov rsi, rsp</code>, mas podemos fazer aritmética com ponteiros e mover o conteúdo resultante, e é muito fácil:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Topo da pilha apontando pra instrução guardada pelo &quot;call&quot;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe440:</span></span><span class="meta function-call arguments shell"> 0x0040100a</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Topo da pilha + 8 bytes apontando pro endereço onde tá a string &quot;Hi&quot;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span>+8</span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe448:</span></span><span class="meta function-call arguments shell"> 0x00402000</span>
</span></code></pre>
<blockquote>
<p>Nesta arquitetura, a pilha, assim como os registradores, armazenam por padrão até 8 bytes por cada informação</p>
</blockquote>
<p>Então teoricamente, tudo o que precisamos é <code>mov rsi, [rsp + 8]</code></p>
<blockquote>
<p>Note que é preciso usar <code>[rsp + 8]</code>, com square brackets é uma forma de fazermos aritmética de ponteiros e acessar o valor resultante da operação na memória, no caso o endereço apontando para a string "Hi"</p>
</blockquote>
<p>Para finalizar este primeiro exemplo, é muito importante fazermos "pop" da pilha. Todo <code>push</code> deve ter um <code>pop</code>, caso contrário podemos gastar a pilha desnecessariamente e talvez chegar a um stack overflow se exagerarmos bastante.</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">push</span> greet             ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> <span class="support function actionscript 2">push</span> na pilha
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>
	<span class="support function actionscript 2">pop</span> rbp                ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> <span class="support function actionscript 2">pop</span> da pilha, jogando o valor em rbp
	                       ; note que rbp é outro registrador de propósito geral,
	                       ; mas que é utilizado para manter a base da pilha
.exit<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]     ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> <span class="constant numeric actionscript 2">8</span> bytes depois <span class="keyword control actionscript 2">do</span> topo da pilha está o
	                       ; endereço de memória da string
	mov rdx, <span class="constant numeric actionscript 2">3</span>
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>Podemos reparar 2 coisas:</p>
<ul>
<li>
<p>A rotina <code>.print</code> está ficando bastante genérica, ou seja ela não sabe o que está na pilha, simplesmente move para o registrador RSI e faz a syscall <code>write</code></p>
</li>
<li>
<p>A rotina  <code>.print</code> ainda usa o tamanho em bytes como valor fixo, no caso 3 bytes. Deveria ser dinâmico também se quisermos fazer com que esta rotina seja bem genérica</p>
</li>
</ul>
<p>Colocamos o tamanho também na pilha? <em>Nah</em>, seria mais interessante ainda se calculássemos dinamicamente o que vem da pilha. Para fazer este cálculo, teríamos que "iterar", em forma de <em>loop</em>, por cada byte que queremos imprimir, incrementar em um registrador e utilizar isto na syscall.</p>
<p>Vamos entrar no mundo dos <strong>loops</strong> e <strong>condicionais</strong>.</p>
<h3 id="calculando-tamanho-dinamicamente-com-loop">Calculando tamanho dinamicamente com loop</h3>
<p>Combinando labels e jumps, podemos criar um <em>loop</em> em assembly, como neste pequeno exemplo a seguir:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; Um loop infinito sem condição de parada
; Não façam isso

<span class="support function actionscript 2">global</span> _start

_start<span class="keyword operator symbolic actionscript 2">:</span>
.loop
	jmp .loop
</span></code></pre>
<p>Entretanto para adicionarmos uma <em>condição de parada</em> do loop, é necessário utilizar uma instrução de <strong>comparação</strong> e outra que <strong>muda algum estado</strong>.</p>
<p>No nosso exemplo, vamos introduzir um <em>loop</em> que calcula o tamanho da string <em>antes de fazer a syscall</em>. Entendendo a necessidade:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; Pseudo<span class="keyword operator symbolic actionscript 2">-</span>code

.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]   ; string em RSI     
	                       
	mov rdx, <span class="keyword operator symbolic actionscript 2">?</span>           ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> aqui devemos introduzir um loop que vai
	                     ; modificando o valor de RDX, lendo byte a byte
	                     ; o conteúdo da string
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>Para resolver isto, podemos criar uma <strong>label</strong> chamada <code>.calculate_size</code> que contém um <code>jmp</code> para ela mesma:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]       ; string em RSI 
	mov rdx, <span class="constant numeric actionscript 2">0</span>               ; RDX começa em <span class="constant numeric actionscript 2">0</span>
.calculate_size<span class="keyword operator symbolic actionscript 2">:</span>             ; <span class="support function actionscript 2">label</span>
	jmp .calculate_size      ; jmp <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>recursivo<span class="punctuation definition string end actionscript 2">&quot;</span></span>
.done<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>Ao rodarmos o programa, <em>obviamente</em> caímos em loop infinito. Precisamos definir uma condição de parada, que consiste em:</p>
<ul>
<li>
<p>mudar o estado de alguma variável condicional</p>
</li>
<li>
<p>desviar o fluxo para outra <em>label</em> quando a condição for verdadeira</p>
</li>
</ul>
<p>Em Assembly, podemos fazer a mudança de estado utilizando a instrução <code>inc</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]     
	mov rdx, <span class="constant numeric actionscript 2">0</span>             ; RDX (contador) começa em <span class="constant numeric actionscript 2">0</span>
.calculate_size<span class="keyword operator symbolic actionscript 2">:</span>
	inc rdx                ; incrementa o valor que está em RDX (linha <span class="constant numeric actionscript 2">23</span>)
	jmp .calculate_size
.done<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>Com gdb, verificamos que o valor de RDX está sempre sendo incrementado:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Adicionar breakpoint na linha 23 (&lt;&lt;inc rdx&gt;&gt;)</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 23</span>
<span class="meta function-call shell"><span class="variable function shell">Breakpoint</span></span><span class="meta function-call arguments shell"> 1 at 0x401021: file live.asm, line 23.</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Executar o programa, que vai no primeiro breakpoint</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>
<span class="meta function-call shell"><span class="variable function shell">Breakpoint</span></span><span class="meta function-call arguments shell"> 1, _start.calculate_size (</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="meta function-call shell"><span class="variable function shell">at</span></span><span class="meta function-call arguments shell"> live.asm:23</span>
<span class="meta function-call shell"><span class="variable function shell">23</span></span><span class="meta function-call arguments shell">              inc rdx</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Continuar execução até o próximo breakpoint ou fim do programa.</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Mas como estamos em loop, o programa vai parar de novo nesta linha</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Atalho para &quot;info register rdx&quot;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdx</span>
<span class="meta function-call shell"><span class="variable function shell">rdx</span></span><span class="meta function-call arguments shell">            0x1                 1</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Próxima iteração...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdx</span>
<span class="meta function-call shell"><span class="variable function shell">rdx</span></span><span class="meta function-call arguments shell">            0x2                 2</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> E assim infinitamente pois não temos ainda a segunda premissa da condição de parada, que é a condicional</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdx</span>
<span class="meta function-call shell"><span class="variable function shell">rdx</span></span><span class="meta function-call arguments shell">            0x19                25</span>
</span></code></pre>
<p>Como podemos elaborar esta condicional, uma vez que o valor em RDX pode ser infinito, logo ter <em>todas as possibilidades</em>?</p>
<p>Uma ideia é irmos <strong>consumindo</strong> byte a byte da string até chegar a <em>zero</em>. Para isto, podemos definir o fim da string com <code>0x0</code> e fazer <em>aritmética binária</em> na própria string, consumindo os bytes até chegar a <code>0x0</code>!</p>
<p>Eis o exemplo com um pseudo-código:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">; <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0</span> 
; que em hexabyte fica <span class="constant numeric actionscript 2">0x49</span>, <span class="constant numeric actionscript 2">0x69</span>, <span class="constant numeric actionscript 2">0x00</span>

INCREMENT
<span class="constant numeric actionscript 2">0x69</span> <span class="constant numeric actionscript 2">0x00</span>   ; consumiu o byte mais à esquerda <span class="constant numeric actionscript 2">0x49</span>

INCREMENT   ; consumiu o byte mais à esquerda <span class="constant numeric actionscript 2">0x69</span>
<span class="constant numeric actionscript 2">0x00</span> <span class="constant numeric actionscript 2">0x</span>...
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3v83k677xw88fg49dn86.png" alt="increment em endereço de memória" /></p>
<blockquote>
<p>Nossa Leandro, que fantástico! Podemos então fazer <code>inc</code> em um registrador que contém a string, nesse caso o próprio RSI?</p>
</blockquote>
<p><em>Isso mesmo!</em></p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.....
section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0xA</span>, <span class="constant numeric actionscript 2">0</span>      ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> adicionamos o <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>zero<span class="punctuation definition string end actionscript 2">&quot;</span></span> para identificar o 
                            ; fim da string

.....

.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]     
	mov rdx, <span class="constant numeric actionscript 2">0</span>
.calculate_size<span class="keyword operator symbolic actionscript 2">:</span>
	inc rdx                 ; incrementa o valor inteiro em RDX (contador)
	inc rsi                 ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> além de incrementar o RDX, incrementamos
	                        ; também o RSI, que contém o endereço de
	                        ; memória para a string. Aritmética em hexabytes
	                        ; vai fazer o efeito de <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>consumir os bytes até zero
	jmp .calculate_size
.done:
	mov rdi, STDOUT
	mov rax, SYS_write
	syscall
	ret

</span></span></code></pre>
<p>Agora, com <code>gdb</code>, vamos verificar o que está acontecendo com nosso programa:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na linha &lt;jmp .calculate_size&gt;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 25</span>
<span class="meta function-call shell"><span class="variable function shell">Breakpoint</span></span><span class="meta function-call arguments shell"> 1 at 0x401027: file live.asm, line 25.</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Cool, o contador RDX foi incrementado</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdx</span>
<span class="meta function-call shell"><span class="variable function shell">rdx</span></span><span class="meta function-call arguments shell">            0x1                 1</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Em RSI, temos outro endereço de memória.</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Anteriormente era o início da string, 0x402000, mas agora está</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> apontando para 0x402001</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rsi</span>
<span class="meta function-call shell"><span class="variable function shell">rsi</span></span><span class="meta function-call arguments shell">            0x402001            4202497</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Wow! Temos os bytes da string &quot;i&quot;, seguido de &quot;\n&quot;, e depois o 0x00</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Parece que o inc RSI funcionou como esperávamos?</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell">x /4xb 0x402001</span>
<span class="meta function-call shell"><span class="variable function shell">0x402001:</span></span><span class="meta function-call arguments shell">       0x69    0x0a    0x00    0x2c</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> A vida continua...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Caminho mais curto</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> E parece que RSI andou mais ainda, agora apontando para o byte &quot;\n&quot;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsi</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002:</span></span><span class="meta function-call arguments shell">       0x0a</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> A vida continua...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O nosso grande momento! Agora RSI aponta para 0x00</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsi</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402003:</span></span><span class="meta function-call arguments shell">       0x00</span>
</span></code></pre>
<p>Tudo o que precisamos fazer, neste momento, é comparar <strong>o valor que está em RSI</strong> com <em>zero</em>. Se chegou a zero, significa que podemos <em>parar o loop</em>. Vamos verificar o que está no contador RDX (esperamos que seja 3):</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdx</span>
<span class="meta function-call shell"><span class="variable function shell">rdx</span></span><span class="meta function-call arguments shell">            0x3                 3</span>
</span></code></pre>
<p><em>Yay! Que grande momento!</em></p>
<p>Mas como verificar em Assembly se chegou ou não no valor? Existe "IF" e "ELSE" em Assembly?</p>
<blockquote>
<p>Hell no!</p>
</blockquote>
<p>Não. Não tem "IF" e "ELSE" em Assembly.</p>
<p>Uma possível solução seria:</p>
<ul>
<li>
<p>utilizar uma instrução que compare o valor de um registrador ou em algum endereço de memória com <strong>qualquer outro valor</strong></p>
</li>
<li>
<p>esta instrução iria guardar o resultado da comparação em outro registrador "especial"</p>
</li>
<li>
<p>utilizar outra instrução para fazer <em>desvio do fluxo</em> de acordo com o valor que estive neste registrador especial</p>
</li>
</ul>
<p>Sim, é aí que entramos no tal do registrador <strong>RFLAGS</strong>.</p>
<h3 id="rflags">RFLAGS</h3>
<p>O registrador de <em>flags</em> é um registrador de status que mantém sempre o estado atual da CPU, neste caso estamos referindo a uma CPU x86_64, pelo que chamamos este registrador de <strong>RFLAGS</strong>.</p>
<p>Este registrador guarda <em>opcodes condicionais</em>, que são resultado de diversas operações lógicas e aritméticas que afetam o estado da CPU.</p>
<p>Voltando ao nosso exemplo, podemos comparar o registrador RSI com o valor 0, e então verificar o que está acontecendo com o registrador <code>eflags</code>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]     
	mov rdx, <span class="constant numeric actionscript 2">0</span>
.calculate_size<span class="keyword operator symbolic actionscript 2">:</span>
	inc rdx
	inc rsi
	cmp byte [rsi], <span class="constant numeric actionscript 2">0x00</span>   ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> aqui comparamos (em byte) o valor que está
	                       ; em RSI com o byte <span class="constant numeric actionscript 2">0x00</span>
	jmp .calculate_size
.done<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>E com isto podemos conferir com <code>gdb</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na linha &lt;cmp byte [rsi], 0x00&gt;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 25</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O que temos no primeiro byte de RSI? &quot;i&quot;, pois o &quot;H&quot; já foi</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> consumido no &lt;inc rsi&gt;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /1xb <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsi</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002:</span></span><span class="meta function-call arguments shell">       0x69</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> E no eflags?</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Nossa, temos o IF que estávamos precisando!!!!!11</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r eflags</span>
<span class="meta function-call shell"><span class="variable function shell">eflags</span></span><span class="meta function-call arguments shell">         0x202               <span class="keyword control regexp set begin shell">[</span> IF <span class="keyword control regexp set end shell">]</span></span>
</span></code></pre>
<blockquote>
<p>Calma jovem, <code>IF</code> não é o que você está pensando!</p>
</blockquote>
<p><code>IF</code> é uma flag chamada <em>interrupt flag</em>, que está sempre presente no programa em execução. Ela determina se o programa pode ou não sofrer interrupções de hardware. No nosso caso, está sempre habilitada por padrão, e é por este motivo que podemos fazer chamadas de sistema (syscalls).</p>
<p>Continuando no gdb...</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O que temos em RSI? &quot;\n&quot;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /1xb <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsi</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402002:</span></span><span class="meta function-call arguments shell">       0x0a</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Executar a instrução &lt;cmp byte [rsi], 0x00&gt;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Ok, segunda iteração continua na mesma, sem flags adicionais</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r eflags</span>
<span class="meta function-call shell"><span class="variable function shell">eflags</span></span><span class="meta function-call arguments shell">         0x202               <span class="keyword control regexp set begin shell">[</span> IF <span class="keyword control regexp set end shell">]</span></span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">####### Próxima iteração ##########</span><span class="comment line number-sign shell">
</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> O que temos em RSI? 0x00, cool.</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /1xb <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsi</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402003:</span></span><span class="meta function-call arguments shell">       0x00</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Executar a instrução &lt;cmp byte [rsi], 0x00&gt;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Outras flags foram adicionadas ao estado: PF e ZF</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r eflags</span>
<span class="meta function-call shell"><span class="variable function shell">eflags</span></span><span class="meta function-call arguments shell">         0x246               <span class="keyword control regexp set begin shell">[</span> PF ZF IF <span class="keyword control regexp set end shell">]</span></span>
</span></code></pre>
<p><code>PF</code> é a <em>parity flag</em>, que é adicionada quando uma operação aritmética em qualquer registrador resulta em paridade ímpar.</p>
<blockquote>
<p>Não é do escopo deste artigo entrar em detalhes sobre PF, sugiro a leitura <a href="https://en.wikipedia.org/wiki/Parity_flag">sobre o assunto</a></p>
</blockquote>
<p>Já a <code>ZF</code> é chamada <strong>zero flag</strong>, adicionada quando uma operação aritmética resulta em zero, que é exatamente o que estamos buscando aqui.</p>
<p>Agora o que precisamos é desviar o fluxo (lembra do <code>jmp</code>) quando a <em>flag zero está presente</em>. Para isto, temos a disposição diversas instruções de jump baseadas em flags:</p>
<ul>
<li>
<p>jz (jump if zero)</p>
</li>
<li>
<p>jnz(jump if not zero)</p>
</li>
<li>
<p>je (jump if equal)</p>
</li>
<li>
<p>jne (jump if not equal)</p>
</li>
</ul>
<blockquote>
<p>Isto pra mencionar apenas algumas, existem muitas outras que podem ser consultadas <a href="https://en.wikibooks.org/wiki/X86_Assembly/Control_Flow">aqui</a></p>
</blockquote>
<p>Com isto, a instrução que precisamos é a <code>jz</code>, que verifica se a flag <code>ZF</code> está presente:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]     
	mov rdx, <span class="constant numeric actionscript 2">0</span>
.calculate_size<span class="keyword operator symbolic actionscript 2">:</span>
	inc rdx
	inc rsi
	cmp byte [rsi], <span class="constant numeric actionscript 2">0x00</span>     ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> compara RSI com <span class="constant numeric actionscript 2">0x00</span>. Adiciona a flag ZF                                  ; quando chegar a zero
	jz .done                 ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> desvia fluxo para a <span class="support function actionscript 2">label</span> <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>.done<span class="punctuation definition string end actionscript 2">&quot;</span></span> caso a
	                         ; flag ZF esteja presente
	jmp .calculate_size
.done<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>Com <code>gdb</code>, colocamos o breakpoint na linha <code>mov rdi, STDOUT</code> que é depois do loop. Caso o programa fique parado nesta linha, significa que o loop foi concluído com sucesso e os bytes da string devidamente calculados:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na linha &lt;mov rdi, STDOUT&gt;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 29</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Olha o que temos aqui</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rdx rsi</span>
<span class="meta function-call shell"><span class="variable function shell">rdx</span></span><span class="meta function-call arguments shell">            0x3                 3</span>
<span class="meta function-call shell"><span class="variable function shell">rsi</span></span><span class="meta function-call arguments shell">            0x402003            4202499</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> E se formos examinar a string (com x/s) em RSI, temos isto:</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x/s <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsi</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x402003:</span></span><span class="meta function-call arguments shell">       <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span><span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<ul>
<li>
<p>Em RDX, temos o contador, que está em 3, que é a quantidade de bytes que será passada como terceiro argumento da syscall write. Okay, aqui ficou tudo certo.</p>
</li>
<li>
<p>Em RSI, temos <code>0x402003</code>, e o valor está vazio, ou <code>0x00</code>. Isto é um problema</p>
</li>
</ul>
<p>O problema reside no fato de que RSI precisa ter o ponteiro para a string em si, e as operações de <code>inc rsi</code> <strong>modificaram o registrador</strong>, pelo que não queremos que isto aconteça.</p>
<p>Podemos então inicialmente mover o valor que está em RSI para outro registrador temporário, que pode ser um daqueles registradores de <em>rascunho</em>, chamados de <em>draft registers</em>:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]     
	mov r9, rsi          ; aqui preservamos RSI, movendo o valor para R9
	mov rdx, <span class="constant numeric actionscript 2">0</span>
.calculate_size<span class="keyword operator symbolic actionscript 2">:</span>
	inc rdx
	inc r9               ; incrementar o valor em R9, preservando assim RSI
	cmp byte [r9], <span class="constant numeric actionscript 2">0x00</span>  ; comparar <span class="constant numeric actionscript 2">0x00</span> com R9, e não mais RSI
	jz .done
	jmp .calculate_size
.done<span class="keyword operator symbolic actionscript 2">:</span>
	mov rdi, STDOUT       
	mov rax, SYS_write
	syscall              ; no momento da syscall, RSI está intacto, contendo
	                     ; o ponteiro para o endereço de memória onde está
	                     ; localizada a nossa queridíssima string <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi<span class="punctuation definition string end actionscript 2">&quot;</span></span>
	ret
</span></code></pre>
<p>Após estas alterações, vamos executar o programa completo:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">./greeting</span></span>
<span class="meta function-call shell"><span class="variable function shell">Hi</span></span>
</span></code></pre>
<p><em>Que dia maravilhoso!</em> Nosso programa imprime a string "Hi" calculando dinamicamente o tamanho dos bytes da string!</p>
<blockquote>
<p>Entretanto, queremos implementar a proposta inicial, não é, Leandro? O programa não tem que ler o nome da linha de comando e imprimir "Hi, Leandro"?</p>
</blockquote>
<h3 id="botando-mais-pilha-no-negócio">Botando mais pilha no negócio</h3>
<p>Nosso objetivo é chamar <code>./greeting</code> com argumento e assim o programa deve imprimir <code>Hi, </code> com o argumento enviado:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Objetivo, isto ainda não funciona</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">./greeting</span></span><span class="meta function-call arguments shell"> Leandro</span>
<span class="meta function-call shell"><span class="variable function shell">Hi,</span></span><span class="meta function-call arguments shell"> Leandro</span>
</span></code></pre>
<p>Se pensarmos um pouco, podemos inferir que qualquer argumento pode ser armazenado na <em>stack</em> do processo, que é quando o programa está em execução.</p>
<p>Com <code>gdb</code>, podemos confirmar isto:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint na primeira linha do programa, depois do _start</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 12</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Executa o programa com o argumento &quot;Leandro&quot;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run Leandro</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Onde estará Leandro? Na pilha? (rsp)</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">      -&gt; x de examine</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell">      -&gt; /8xb os primeiros 8 hexa bytes</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /8xb <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe450:</span></span><span class="meta function-call arguments shell"> 0x02    0x00    0x00    0x00    0x00    0x00    0x00    0x00</span>
</span></code></pre>
<p>Mas o quê significa esse número 2? Vamos examinar a stack e a ordem das informações contidas nela.</p>
<p>Voltando ao <code>gdb</code>, e se lermos os próximos 8 bytes na stack?</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /8xb <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span> + 8</span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe458:</span></span><span class="meta function-call arguments shell"> 0xb1    0xe6    0xff    0xff    0xff    0x7f    0x00    0x00</span>
</span></code></pre>
<blockquote>
<p>Lembrando que os bytes são escritos na stack em formato little-endian, ou seja estão invertidos</p>
</blockquote>
<p>Com isto, temos um hexadecimal <code>0x7fffffffe6b1</code>. Parece um endereço de memória, não?</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Examinando o endereço de memória no formato de string (/s)</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /s 0x7fffffffe6b1</span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe6b1:</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>/Users/..../code/asm-x64/live<span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<p>Wow, temos o primeiro argumento, também chamado de <em>ARG0</em> que é o nome do programa com o caminho absoluto no sistema operacional.</p>
<p>Andando mais 8 bytes...</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Endereço de memória...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /8xb <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span> + 16</span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe460:</span></span><span class="meta function-call arguments shell"> 0xdf    0xe6    0xff    0xff    0xff    0x7f    0x00    0x00</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Examinando o valor que está no endereço</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x /s 0x7fffffffe6df</span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe6df:</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Leandro<span class="punctuation definition string end shell">&quot;</span></span></span>
</span></code></pre>
<p><em>Yay!</em> Temos o nosso argumento, armazenado na stack. É o primeiro argumento, também chamado de <em>ARG1</em>.</p>
<blockquote>
<p>Se continuarmos andando na stack de 8 em 8 bytes, vamos passar por todos os argumentos (no nosso caso não há mais), e a seguir vamos chegar no vetor ambiente, que contém todas as variáveis de ambiente contidas no shell que está executando o nosso programa</p>
</blockquote>
<p>Com isto, sabemos que o primeiro argumento está localizado em <code>rsp + 16</code>:</p>
<ul>
<li>
<p><code>rsp</code>: quantidade de argumentos</p>
</li>
<li>
<p><code>rsp + 8</code>: ARG0, nome do programa</p>
</li>
<li>
<p><code>rsp + 16</code>: ARG1, primeiro argumento (se existir)</p>
</li>
<li>
<p><code>rsp + 24</code>: ARG2, segundo argumento (se existir)</p>
</li>
<li>
<p>e assim sucessivamente...até chegar no vetor de variáveis de ambiente (vetor ambiente)</p>
</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zs0kmzgwigotv9drklh9.png" alt="layout de memória com stack" /></p>
<p>Sabendo que nossa <em>sub-rotina</em> <code>.print</code> já recebe uma string da stack e calcula dinamicamente o tamanho da string que foi passada, podemos passar pro topo da stack o nosso argumento (que por acaso também está na stack), e em seguida chamada a rotina <code>.print</code> novamente:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi, <span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0</span>

_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">push</span> greet      
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>     
	<span class="support function actionscript 2">pop</span> rbp     

	; aqui fazemos <span class="support function actionscript 2">push</span> pro topo da stack o valor que está em RSP <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">16</span> (ARG1)
	; utilizamos o tipo <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>qword<span class="punctuation definition string end actionscript 2">&quot;</span></span> que significa <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>quadword<span class="punctuation definition string end actionscript 2">&quot;</span></span>
	<span class="support function actionscript 2">push</span> qword [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">16</span>]
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>
	<span class="support function actionscript 2">pop</span> rbp
...
</span></code></pre>
<p>O quê significa <strong>quadword</strong>? Em assembly podemos definir <em>tipos de bytes</em>, que basicamente são grupos de bytes, podendo ou não caber em um registrador ou stack dependendo da arquitetura da CPU.</p>
<ul>
<li>
<p><strong>byte</strong>: especifica 1 byte (8-bit)</p>
</li>
<li>
<p><strong>word</strong>: 2 bytes (16-bit)</p>
</li>
<li>
<p><strong>dword</strong>: 4 bytes (32-bit)</p>
</li>
<li>
<p><strong>qword</strong>: 8 bytes (64-bit)</p>
</li>
<li>
<p><strong>tbyte</strong>: 10 bytes</p>
</li>
</ul>
<p>Na arquitetura x86_64, precisamos especificar que o tipo de byte adicionado na stack, quando não vier de um registrador mas sim de um lugar arbitrário na memória ou stack, tem um determinado <em>tamanho</em> em bytes.</p>
<p>Neste caso, estamos utilizando <em>qword</em> que é justamente 8 bytes (ou 64-bit) que representa a arquitetura em questão.</p>
<p>Precisamos adicionar mais um caracter, que é o <em>newline</em>, ou <code>\n</code>, no fim da mensagem. Para isto, podemos definir um dado inicializado e chamar a rotina <code>.print</code> , que já está bem "crescidinha", não?</p>
<p>Programa completo, com comentários:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi, <span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0</span>
<span class="support function actionscript 2">newline</span><span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0xA</span>, <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">push</span> greet             ; adiciona <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi, <span class="punctuation definition string end actionscript 2">&quot;</span></span> na stack para <span class="support function actionscript 2">print</span>
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>     
	<span class="support function actionscript 2">pop</span> rbp         

	<span class="support function actionscript 2">push</span> qword [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">16</span>]  ; adiciona ARG1 na stack para <span class="support function actionscript 2">print</span>
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>
	<span class="support function actionscript 2">pop</span> rbp

	<span class="support function actionscript 2">push</span> <span class="support function actionscript 2">newline</span>           ; adiciona <span class="support function actionscript 2">newline</span> na stack para <span class="support function actionscript 2">print</span>
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>
	<span class="support function actionscript 2">pop</span> rbp
.exit<span class="keyword operator symbolic actionscript 2">:</span>                     ; <span class="support function actionscript 2">label</span> de término <span class="keyword control actionscript 2">do</span> programa
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall
.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>                    ; rotina de <span class="support function actionscript 2">print</span> no STDOUT
	mov rsi, [rsp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">8</span>]     
	mov r9, rsi
	mov rdx, <span class="constant numeric actionscript 2">0</span>
.calculate_size<span class="keyword operator symbolic actionscript 2">:</span>           ; loop para calcular tamanho da string
	inc rdx
	inc r9
	cmp byte [r9], <span class="constant numeric actionscript 2">0x00</span>
	jz .done
	jmp .calculate_size
.done<span class="keyword operator symbolic actionscript 2">:</span>                     ; <span class="support function actionscript 2">label</span> para finalizar a rotina <span class="support function actionscript 2">print</span> e retornar
	mov rdi, STDOUT
	mov rax, SYS_write
	syscall
	ret
</span></code></pre>
<p>Rodamos o programa e:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">./greeting</span></span><span class="meta function-call arguments shell"> Leandro</span>
<span class="meta function-call shell"><span class="variable function shell">Hi,</span></span><span class="meta function-call arguments shell"> Leandro</span>
</span></code></pre>
<p><em>OMG! Eu não estou acreditando no que estou vendo!!!!!11</em></p>
<h3 id="depurando-o-programa-final-com-strace">Depurando o programa final com strace</h3>
<p>Com <em>strace</em>, podemos fazer o trace de syscalls do programa final. Olha que maravilha isto:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> strace ./greeting Leandro</span>

<span class="meta function-call shell"><span class="variable function shell">execve</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./greeting<span class="punctuation definition string end shell">&quot;</span></span>, <span class="keyword control regexp set begin shell">[</span><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>./greeting<span class="punctuation definition string end shell">&quot;</span></span>, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Leandro<span class="punctuation definition string end shell">&quot;</span></span><span class="keyword control regexp set end shell">]</span>, 0x7ffc30f75368 /<span class="keyword operator regexp quantifier shell">*</span> 24 vars <span class="keyword operator regexp quantifier shell">*</span>/</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">0</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(1, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Hi, <span class="punctuation definition string end shell">&quot;</span></span>, 4Hi, </span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                     <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">4</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(1, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Leandro<span class="punctuation definition string end shell">&quot;</span></span>, 7Leandro</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                  <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">7</span></span>
<span class="meta function-call shell"><span class="variable function shell">write</span></span><span class="meta function-call arguments shell">(1, <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>\n<span class="punctuation definition string end shell">&quot;</span></span>, 1</span>
<span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                       <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">1</span></span>
<span class="meta function-call shell"><span class="variable function shell">exit</span></span><span class="meta function-call arguments shell">(0</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>                                 <span class="keyword operator assignment shell">=</span> <span class="meta function-call shell"><span class="variable function shell">?</span></span>
<span class="meta function-call shell"><span class="variable function shell">+++</span></span><span class="meta function-call arguments shell"> exited with 0 +++</span>
</span></code></pre>
<p>Foram feitas 4 chamadas de sistema, sendo:</p>
<ul>
<li>
<p>1 write, "Hi, "</p>
</li>
<li>
<p>1 write "Leandro"</p>
</li>
<li>
<p>1 write "\n"</p>
</li>
<li>
<p>1 exit</p>
</li>
</ul>
<hr />
<h2 id="falando-um-pouco-de-registradores">Falando um pouco de registradores</h2>
<p>Até o momento, vimos durante este artigo a utilização de alguns registradores que foram muito úteis para o desenvolvimento do programa, dentre eles <em>RSI</em>, <em>RAX</em>, <em>RDX</em>, <em>RSP</em>, <em>RIP</em>, <em>RFLAGS</em> e assim por diante.</p>
<p>Mas qual o <strong>propósito de cada registrador</strong>? Posso usar qualquer registrador para qualquer operação, de forma aleatória?</p>
<blockquote>
<p>De forma prática, sim. Mas nem sempre convém.</p>
</blockquote>
<p>Nada impede que o teu programa coloque qualquer valor em um registrador arbitrário. Por exemplo, com <code>gdb</code> vamos alterar alguns registradores e ver como o programa se comporta:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint &amp; run</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 13</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run Leandro</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Vamos alterar alguns registradores arbitrários</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> set <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rax</span></span> = 42</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> set <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rdx</span></span> = 33</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Confirmando que foram modificados</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rax rdx</span>
<span class="meta function-call shell"><span class="variable function shell">rax</span></span><span class="meta function-call arguments shell">            0x2a                42</span>
<span class="meta function-call shell"><span class="variable function shell">rdx</span></span><span class="meta function-call arguments shell">            0x21                33</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Continuando...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>
<span class="meta function-call shell"><span class="variable function shell">Continuing.</span></span>
<span class="meta function-call shell"><span class="variable function shell">Hi,</span></span><span class="meta function-call arguments shell"> Leandro</span>
<span class="meta function-call shell"><span class="variable function shell">[Inferior</span></span><span class="meta function-call arguments shell"> 1 (process 19231</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span> <span class="meta function-call shell"><span class="variable function shell">exited</span></span><span class="meta function-call arguments shell"> normally]</span>
</span></code></pre>
<p>Okay, podemos ver que ter mudado estes registradores para <em>qualquer valor</em> não impactou o programa. No meio do programa, provavelmente eles são sobrescritos novamente e utilizados de acordo com <em>determinada lógica</em>.</p>
<p>Mas e se alterarmos, por exemplo, um registrador como o <code>rip</code>, que é o <em>ponteiro da próxima instrução</em>?</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint &amp; run</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 13</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run Leandro</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Antes de alterar o RIP, podemos ver qual o valor ele carrega,</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> que é o ponteiro da próxima instrução</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rip</span>
<span class="meta function-call shell"><span class="variable function shell">rip</span></span><span class="meta function-call arguments shell">            0x401000            0x401000 <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>
</span>
<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Vamos alterar o registrador RIP</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> set <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rip</span></span> = 42</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Confirmando que foi alterando</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> i r rip</span>
<span class="meta function-call shell"><span class="variable function shell">rip</span></span><span class="meta function-call arguments shell">            0x2a                0x2a</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Continuando...</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> continue</span>
<span class="meta function-call shell"><span class="variable function shell">Continuing.</span></span>
<span class="meta function-call shell"><span class="variable function shell">Program</span></span><span class="meta function-call arguments shell"> received signal SIGSEGV, Segmentation fault.</span>
<span class="meta function-call shell"><span class="variable function shell">0x000000000000002a</span></span><span class="meta function-call arguments shell"> in <span class="keyword operator regexp quantifier shell">?</span><span class="keyword operator regexp quantifier shell">?</span> (</span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>
</span></code></pre>
<p><em>Ouch!</em> Agora o programa não pôde ser finalizado com sucesso. Confirmamos então que nem sempre convém mudar os registradores sem <em>haver algum critério</em>.</p>
<h3 id="propósito-dos-registradores">Propósito dos registradores</h3>
<p>Os registradores, e falando especificamente da arquitetura x86, seguem um <strong>propósito original</strong> para o qual foram designados. Mas também podem ser utilizados em convenções de <strong>chamadas de sistema</strong> tal como vimos na montagem das syscalls <code>write</code> e <code>exit</code>, e neste caso a utilização correta importa bastante.</p>
<p>E além disso, alguns registradores contém dados importantes para a execução do programa, tais como o <code>rip</code> e <code>eflags</code>.</p>
<ul>
<li>
<p>Propósito original</p>
</li>
<li>
<p>Convenções de chamadas</p>
</li>
<li>
<p>Funcionamento crítico do programa</p>
</li>
</ul>
<p>Apesar destas características importantes de uso dos registradores, podem haver situações em que utilizar um registrador de propósito geral é o que faz mais sentido para o programa. Vamos a seguir destacar alguns registradores e seus <em>propósitos originais</em>.</p>
<h3 id="registradores-de-propósito-geral">Registradores de propósito geral</h3>
<p>Podemos categorizar os registradores de uso geral em 2 partes: manipulação de <em>dados diretos</em> ou <em>endereços de memória</em>.</p>
<p><strong>Dados</strong>
Registradores podem manipular dados, que chamamos de <em>valor imediato</em>, e nesta categoria podemos utilizar RAX, RBX, RCX, RDX e os registradores de rascunho que vão de R8 a R15.</p>
<ul>
<li>
<p><strong>RAX</strong>: operações aritméticas e armazenamento de resultados; também usado para o nome de chamadas de sistema em convenções de chamada (syscalls)</p>
</li>
<li>
<p><strong>RBX</strong>: ponteiro de base, utilizado para o endereço de algumas informações na memória</p>
</li>
<li>
<p><strong>RCX</strong>: geralmente usado como contador, para armazenar a quantidade de vezes que uma instrução deve ser executada</p>
</li>
<li>
<p><strong>RDX</strong>: usado para algumas operações de multiplicação e divisão, muito utilizado para armazenar o resto de operações</p>
</li>
<li>
<p><strong>R8 a R15</strong>: registradores de <em>rascunho</em> utilizados para propósito geral</p>
</li>
</ul>
<p><strong>Endereços de memória</strong>
Registradores também permitem manipular endereços de memória. Nesta categoria temos RSI, RDI, RBP e RSP.</p>
<ul>
<li>
<p><strong>RSI</strong>: utilizado como um ponteiro de origem em operações de transferências de dados, frequentemente usado em loops para iterar sobre arrays ou buffers de dados</p>
</li>
<li>
<p><strong>RDI</strong>: utilizado como ponteiro de destino em operações de transferências de dados, frequentemente usado junto com RSI</p>
</li>
<li>
<p><strong>RBP</strong>: frequentemente usado como ponteiro base em operações de memória, para referenciar variáveis locais e parâmetros de função na stack</p>
</li>
<li>
<p><strong>RSP</strong>: ponteiro para o topo da pilha (stack) do programa em execução</p>
</li>
</ul>
<h3 id="registradores-especiais">Registradores especiais</h3>
<p>Vamos destacar apenas 2 dos registradores considerados "especiais":</p>
<ul>
<li>
<p><strong>RFLAGS</strong>: utilizado para armazenar o estado da CPU, frequentemente modificado por instruções aritméticas e controle de paridade binária</p>
</li>
<li>
<p><strong>RIP</strong>: ponteiro de instrução, que sempre contém o endereço da próxima instrução a ser executada. Por exemplo, a instrução <code>ret</code> busca o endereço do topo da pilha e modifica o <code>rip</code> para que o programa continue a partir daquele ponto</p>
</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z3ospgiir3a2nv78nm96.png" alt="tipos de registradores" /></p>
<h3 id="precisamos-sempre-utilizar-todos-os-64-bits">Precisamos sempre utilizar todos os 64 bits?</h3>
<p>Sabemos que registradores nesta arquitetura <strong>ocupam 64 bits de memória</strong>. Mas e quando o dado que estamos manipulando não precisa dos 64 bits? Conseguimos otimizar o uso de memória?</p>
<blockquote>
<p>A ideia seria algo do tipo "por favor me dê uma fatia dos 64 bits, não preciso de tudo"</p>
</blockquote>
<p>Historicamente, como vimos na parte II desta saga, as CPU's x86 não começaram com 64 bits. Evoluíram de 8 bits, para 16, então 32 até chegar em 64 bits.</p>
<p>Para manter compatibilidade, os registradores "legados" podem ser utilizados na arquitetura x64, e assim quando não houver necessidade de utilizar todos os bits do registrador, podemos utilizar uma <em>fatia menor</em>.</p>
<p>Por exemplo, o registrador RAX de 64-bits tem o seu equivalente de 32-bits que é o EAX, que <strong>ocupa os 32 bits mais baixos</strong>.</p>
<p>O registrador EAX, por sua vez, tem o equivalente AX de 8-bits. Dentro deste AX, podemos utilizar ainda a parte <strong>maior</strong> que se chama AH ou a parte <strong>menor</strong> que se chama AL.</p>
<blockquote>
<p>O "H" em AH vem de "high", e consequentemente "L" de AL significa "low". Óbvio, não? :P</p>
</blockquote>
<p>Sendo assim, há situações em que ao invés de:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov rax, <span class="constant numeric actionscript 2">7</span>  ; <span class="constant numeric actionscript 2">1</span> byte mas ocupa <span class="constant numeric actionscript 2">8</span> bytes (<span class="constant numeric actionscript 2">64</span> bits)
</span></code></pre>
<p>E sabendo que 42 não ocupa 64 bits, podemos mudar para:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov eax, <span class="constant numeric actionscript 2">7</span>  ; <span class="constant numeric actionscript 2">1</span> byte mas ocupa <span class="constant numeric actionscript 2">4</span> bytes (<span class="constant numeric actionscript 2">16</span> bits)
</span></code></pre>
<p>Ou então:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">mov ax, <span class="constant numeric actionscript 2">7</span>   ; <span class="constant numeric actionscript 2">1</span> byte ocupando exatamente <span class="constant numeric actionscript 2">1</span> byte (<span class="constant numeric actionscript 2">8</span> bits)
</span></code></pre>
<p>Assim o programa final passa a ocupar menos memória em sua totalidade.</p>
<p>Seguindo esta lógica, podemos aplicar para todos os registradores, trazendo alguns como exemplo:</p>
<ul>
<li>
<p><strong>RAX</strong>: <code>EAX -&gt; AX -&gt; AH -&gt; AL</code></p>
</li>
<li>
<p><strong>RBX</strong>: <code>EBX -&gt; BX -&gt; BH -&gt; BL</code></p>
</li>
<li>
<p><strong>RDX</strong>: <code>RDX -&gt; DX -&gt; DH -&gt; DL</code></p>
</li>
<li>
<p><strong>R8</strong>: <code>R8W -&gt; R8B</code></p>
</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtp88ythfnm7yj2rhefw.png" alt="fatias de registradores" /></p>
<p>E assim por diante.</p>
<hr />
<h2 id="uma-side-note-sobre-stack-frames">Uma side note sobre stack frames</h2>
<p>Depois de publicar o artigo, o <a href="https://twitter.com/rodrigogbranco">Rodrigo Gonçalves de Branco</a> decidiu dar um <a href="https://docs.google.com/document/d/10xr0Qm6jatko2dRyQYqXuToXp5DShxl6dhmBnPPUAb4/edit">feedback ultra detalhado</a> executando todos os exemplos aqui demonstrados, e um dos insights foi sobre a utilização de stack frames.</p>
<blockquote>
<p>Foi um trabalho fenomenal, meus agradecimentos ao Rodrigo</p>
</blockquote>
<p>Voltando ao exemplo dos <strong>argumentos na pilha</strong>, dentro da rotina <code>_start</code>, temos a pilha do programa com o seguinte layout:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uaiuvwiltzhlzj5bxner.png" alt="rsp antes" /></p>
<p>Quando fazemos a chamada:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">...
	<span class="support function actionscript 2">push</span> greet    ; adiciona <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi, <span class="punctuation definition string end actionscript 2">&quot;</span></span> na stack para <span class="support function actionscript 2">print</span>
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>     
...
</span></code></pre>
<p>Estamos basicamente <em>manipulando a pilha original</em> do programa. O <code>push</code> vai colocar no topo da pilha (RSP) o endereço de <code>greet</code>, como demonstrado a seguir no GDB:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> Breakpoint no &lt;push greet&gt;</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> break 13   </span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> run</span>
<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> next</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe448:</span></span><span class="meta function-call arguments shell"> 0x00402000</span>
</span></code></pre>
<p>Agora a pilha ficou assim:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3tqkty8gtj5olc876qtd.png" alt="layout com pilha e data" /></p>
<p>Se fizermos <code>step</code> no GDB, podemos ver que o RSP foi modificado novamente, desta vez adicionando o endereço da próxima instrução por conta da chamada <code>call</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> step</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe440:</span></span><span class="meta function-call arguments shell"> 0x0040100a</span>
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7kis57u2auas91bcebog.png" alt="layout com data e text" /></p>
<p><em>Isso é o que acontece com a pilha em uma simples chamada de rotina com argumentos!</em></p>
<p>Bom, sabendo disso, vemos que o argumento que precisamos está em <code>rsp + 8</code>, exatamente como no nosso programa original. <em>So far, so good</em>.</p>
<p>O problema é que podemos reparar que o RSP é modificado durante as chamadas de funções no programa. Não temos controle sobre isso.</p>
<p>E podem acontecer <em>comportamentos inesperados</em> (bugs?) quando isso ocorre, pelo simples fato de estarmos <strong>apontando dados na pilha</strong> e eles já estarem em posições que não esperávamos.</p>
<p>Para mitigar este potencial problema, podemos preservar a <strong>base da pilha</strong> em algum registrador sempre no início de cada função, desta forma cada rotina/função pode ter sua própria "versão" da pilha sem correr riscos de apontar para o dado errado.</p>
<p>Esta técnica é chamada de <strong>stack frame</strong>.</p>
<p>E é pra isso que usamos o <strong>registrador RBP</strong>! No <em>prólogo</em> de cada rotina, adicionamos o <code>rbp</code> na pilha e em seguida colocamos o ponteiro de <code>rsp</code> dentro do registrador <code>rbp</code>, igualando assim ambos registradores:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">_start<span class="keyword operator symbolic actionscript 2">:</span>
    <span class="support function actionscript 2">push</span> rbp
    mov rbp, rsp
....
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/si286ldan8b9swswr9q0.png" alt="rsp e rbp" /></p>
<p>Repare que esta técnica consiste em <em>igualar</em> RSP com RBP, assim pode-se de forma segura manipular o <em>ponteiro em RBP</em>, pois mesmo RSP sendo modificado pelo programa, RBP continua intacto.</p>
<p>Continuando com o programa:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">push</span> rbp
mov rbp, rsp
....
<span class="support function actionscript 2">push</span> greet
<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>
....
</span></code></pre>
<p>Constatamos no GDB que a stack foi alterada, portanto RSP foi modificado para apontar para o endereço da próxima instrução, ao passo que RBP continua apontando pro valor anterior:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RBP </span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rbp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe448:</span></span><span class="meta function-call arguments shell"> 0x00000000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RSP aponta para o endereço da próxima instrução </span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> antes da chamada da rotina</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe438:</span></span><span class="meta function-call arguments shell"> 0x0040100e</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RSP + 8 aponta para o primeiro argumento da rotina</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span> + 8</span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe440:</span></span><span class="meta function-call arguments shell"> 0x00402000</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> RSP + 16 aponta para o mesmo valor de RBP (base da pilha),</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> ou seja, `RBP = RSP + 16` neste caso porque houve um PUSH</span><span class="comment line number-sign shell">
</span><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> explícito do argumento e também outro push feito pelo CALL</span><span class="comment line number-sign shell">
</span><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span> + 16</span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe448:</span></span><span class="meta function-call arguments shell"> 0x00000000</span>
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a3fjvaxlpm4g8c41jnl8.png" alt="rbp  = rsp + 16" /></p>
<p>E modificando a rotina <code>.print</code> para também ter seu próprio stack frame, como fica a pilha depois de executar:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>
    <span class="support function actionscript 2">push</span> rbp
    mov rbp, rsp
....
</span></code></pre>
<p>Analisando com GDB:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rbp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe430:</span></span><span class="meta function-call arguments shell"> 0xffffe448</span>

<span class="punctuation definition compound begin shell">(</span><span class="meta function-call shell"><span class="variable function shell">gdb</span></span><span class="punctuation definition compound end shell">)</span><span class="meta function-call arguments shell"> x <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">rsp</span></span></span>
<span class="meta function-call shell"><span class="variable function shell">0x7fffffffe430:</span></span><span class="meta function-call arguments shell"> 0xffffe448</span>
</span></code></pre>
<p>RSP e RBP ficaram igualados novamente, dando uma característica de stack frame, preservando a pilha como podemos ver na imagem a seguir:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oyrhiaqltlra50b8fi2w.png" alt="stack frame" /></p>
<p>Portanto, o argumento da rotina, ao invés de ser <code>rsp + 8</code>, passa a ser <code>rbp + 16</code> por conta da stack frame, ficando da seguinte forma:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>                  
	<span class="support function actionscript 2">push</span> rbp
	mov rbp, rsp

	mov rsi, [rbp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">16</span>]     
	mov r9, rsi
	mov rdx, <span class="constant numeric actionscript 2">0</span>
</span></code></pre>
<p><em>Uma coisa importante</em>: ao final de cada rotina, antes do <em>retorno</em>, devemos fazer <code>pop</code> do topo da pilha para voltar ao estado original antes do <code>push rbp</code> feito no início da rotina:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">push</span> rbp
mov rbp, rsp
....
<span class="support function actionscript 2">pop</span> rbp
ret
</span></code></pre>
<p>Desta forma, ao fazer o <code>pop rbp</code>, o que está em RSP é justamente o endereço de retorno antes da chamada da função:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kbrojascqyspoa4lhjl.png" alt="pop do rbp antes do retorno" /></p>
<p>Ao continuar com o programa, a instrução <code>ret</code> (já falamos sobre ela anteriormente) faz <em>pop</em> do topo da pilha (RSP) e continua a execução do programa na próxima instrução:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2">_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">push</span> rbp
	mov rbp, rsp     ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> iguala RSP e RBP

	<span class="support function actionscript 2">push</span> greet       ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> adiciona &lt;greet&gt; na pilha
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>      ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> adiciona ponteiro da próxima 
                         ; instrução na pilha
	<span class="support function actionscript 2">pop</span> rax          ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> faz <span class="support function actionscript 2">pop</span> de &lt;greet&gt; da pilha      

............
.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>                 
	<span class="support function actionscript 2">push</span> rbp         
	mov rbp, rsp     ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> iguala RSP e RBP

	mov rsi, [rbp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">16</span>]     
        .............
	syscall
	<span class="support function actionscript 2">pop</span> rbp          ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> remove frame RBP da pilha
	ret              ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> faz <span class="support function actionscript 2">pop</span> <span class="keyword control actionscript 2">do</span> pointeiro da 
                         ; próxima instrução e atualiza RIP
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nrhswxyhluvlc9yvlyem.png" alt="layout depois do ret" /></p>
<p>Quando o fluxo volta para quem chamou a rotina, a próxima instrução deve ser sempre o <code>pop</code> dos argumentos que entraram na pilha.</p>
<p>Neste caso no exemplo anterior estamos fazendo <em>pop</em> do argumento e descartando o valor em RAX com <code>pop rax</code>, deixando assim a pilha em seu estado anterior à chamada da rotina:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxp5nup5nzqs19hx3nwb.png" alt="final" /></p>
<p>Ao fim do programa (rotina <code>_start</code>), devemos também fazer <code>pop rbp</code>, assim a pilha volta ao estado original de quando foi iniciado o programa.</p>
<p>Código completo:</p>
<pre><code class="sourceCode language-as"><span class="source actionscript 2"><span class="support function actionscript 2">global</span> _start

<span class="keyword operator symbolic actionscript 2">%</span>define SYS_write <span class="constant numeric actionscript 2">1</span>
<span class="keyword operator symbolic actionscript 2">%</span>define SYS_exit <span class="constant numeric actionscript 2">60</span>
<span class="keyword operator symbolic actionscript 2">%</span>define STDOUT <span class="constant numeric actionscript 2">1</span>

section .<span class="support function actionscript 2">data</span>
greet<span class="keyword operator symbolic actionscript 2">:</span> db <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi, <span class="punctuation definition string end actionscript 2">&quot;</span></span>, <span class="constant numeric actionscript 2">0</span>
<span class="support function actionscript 2">newline</span><span class="keyword operator symbolic actionscript 2">:</span> db <span class="constant numeric actionscript 2">0xA</span>, <span class="constant numeric actionscript 2">0</span>

section .<span class="support function actionscript 2">text</span>
_start<span class="keyword operator symbolic actionscript 2">:</span>
	<span class="support function actionscript 2">push</span> rbp               ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> cria um stack frame
	mov rbp, rsp           ; para preservar a pilha

	<span class="support function actionscript 2">push</span> greet             ; adiciona <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi, <span class="punctuation definition string end actionscript 2">&quot;</span></span> na pilha
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>            ; chama sub<span class="keyword operator symbolic actionscript 2">-</span>rotina
	<span class="support function actionscript 2">pop</span> rax                ; remove <span class="string quoted double actionscript 2"><span class="punctuation definition string begin actionscript 2">&quot;</span>Hi, <span class="punctuation definition string end actionscript 2">&quot;</span></span> da pilha

	<span class="support function actionscript 2">push</span> qword [rbp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">24</span>]  ; adiciona argumento na pilha
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>            ; chama sub<span class="keyword operator symbolic actionscript 2">-</span>rotina
	<span class="support function actionscript 2">pop</span> rax                ; remove argumento da pilhha

	<span class="support function actionscript 2">push</span> <span class="support function actionscript 2">newline</span>           ; adiciona <span class="support function actionscript 2">newline</span> na pilha
	<span class="support function actionscript 2">call</span> .<span class="support function actionscript 2">print</span>            ; chama<span class="keyword operator symbolic actionscript 2">-</span>subrotina
	<span class="support function actionscript 2">pop</span> rax                ; remove <span class="support function actionscript 2">newline</span> da pilha

	<span class="support function actionscript 2">pop</span> rbp                ; remove RBP da pilha, 
                               ; retornando ao estado original
.exit<span class="keyword operator symbolic actionscript 2">:</span>               
	mov rdi, <span class="constant numeric actionscript 2">0</span>
	mov rax, SYS_exit
	syscall                ; termina o programa
.<span class="support function actionscript 2">print</span><span class="keyword operator symbolic actionscript 2">:</span>                   
	<span class="support function actionscript 2">push</span> rbp               ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> cria um stack frame
	mov rbp, rsp           ; para preservar a pilha

	mov rsi, [rbp <span class="keyword operator symbolic actionscript 2">+</span> <span class="constant numeric actionscript 2">16</span>]     
	mov r9, rsi
	mov rdx, <span class="constant numeric actionscript 2">0</span>
.calculate_size<span class="keyword operator symbolic actionscript 2">:</span>               ; loop para calcular tamanho
	inc rdx
	inc r9
	cmp byte [r9], <span class="constant numeric actionscript 2">0x00</span>
	jz .done
	jmp .calculate_size
.done<span class="keyword operator symbolic actionscript 2">:</span>                     
	mov rdi, STDOUT
	mov rax, SYS_write
	syscall

	<span class="support function actionscript 2">pop</span> rbp                ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> remove RBP da pilha, 
                               ; retornando ao estado anterior

	ret                    ; &lt;<span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span><span class="keyword operator symbolic actionscript 2">-</span> retorna fluxo para o
                               ; estado anterior
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zqxli9xe88yxloe21ht.png" alt="voltando ao estado original da pilha" /></p>
<p>É isto. Esta seção foi apenas uma demonstração de como utilizar boas práticas de manipulação da pilha quando utilizamos argumentos em funções, através da técnica de <em>criar um frame</em> como <strong>base da pilha</strong> com o registrador RBP.</p>
<hr />
<h2 id="conclusão">Conclusão</h2>
<p>É isto, pessoal. Esta parte da saga foi bastante densa. Passamos pela criação de um programa simples em Assembly, ao passo em que íamos depurando o programa com ferramentas como <em>strace</em>, <em>size</em> e <strong>muito gdb</strong>.</p>
<p>Também aprendemos sobre labels, tipos de registradores, desvio de fluxo com jmp, call, ret, <strong>muita stack</strong>, depurando tudo e mais um pouco, loops, FLAGS e aritmética de ponteiro.</p>
<p>Apesar de ter sido muito denso, os tópicos aqui abordados servirão de base para entendermos o próximo artigo que já começa pesado com syscalls de rede, para iniciarmos o nosso tão esperado web server.</p>
<p>Nos vemos no próximo artigo!</p>
<hr />
<h2 id="referências">Referências</h2><sub>
Mnemonics
https://en.wikipedia.org/wiki/Mnemonic
Comparison of Assemblers
https://en.wikipedia.org/wiki/Comparison_of_assemblers
Linker (computing)
https://en.wikipedia.org/wiki/Linker_(computing)
Assembly x86 tutorial
https://www.tutorialspoint.com/assembly_programming/index.htm
Data segment
https://en.wikipedia.org/wiki/Data_segment
FLAGS register
https://en.wikipedia.org/wiki/FLAGS_register
Debugging with GDB
https://ncona.com/2019/12/debugging-assembly-with-gdb/
GDB command reference
https://visualgdb.com/gdbreference/commands/
GDB cheatsheet
https://cs.brown.edu/courses/cs033/docs/guides/gdb.pdf
[Vídeo] Introdução ao GNU Debugger - Blau Araújo
https://www.youtube.com/watch?v=t9OKpBKbJ4Q
</sub>
]]></description>
<pubDate>2024-05-13</pubDate>
</item>
<item>
<title>Construindo um web server em Assembly x86, parte III, código de máquina</title>
<link>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iii-codigo-de-maquina-bgk.html</link>
<guid>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-iii-codigo-de-maquina-bgk.html</guid>
<description><![CDATA[<p>Agora que já temos uma <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-ii-historia-e-arquitetura-2jb9">base de entendimento</a> sobre hierarquia de memória, arquitetura de CPU e registradores, vamos aplicar estes conceitos em exemplos práticos: construindo programas de computador.</p>
<p><em>Mas o que é um programa de computador?</em></p>
<p>Teremos a resposta para esta pergunta ao longo deste artigo. Vamos abordar muitos conceitos, desde código de máquina (o mais importante na minha opinião), a sistemas de numeração binário, decimal e hexadecimal.</p>
<p>Iremos também compreender opcodes, chamadas de sistema, modo kernel, libc, ASCII, standard streams; e alterar arquivos binários em hexadecimal.</p>
<p>Ao final deste artigo vamos estar em um patamar de entendimento mais holístico de como um programa é interpretado na CPU.</p>
<p>Ainda não entraremos em Assembly. Foi escolhido desta forma pois o intuito com esta saga é detalhar ao máximo como as peças de encaixam, e acredito que trazer Assembly sem explicar outros conceitos primordiais pode confundir bastante.</p>
<p>Também não é esperado que você escreva os códigos de máquina deste artigo, pois aqui <a href="https://github.com/leandronsp/monica/blob/main/example">neste link</a> providencio o binário já pronto para que você possa acompanhar com as ferramentas que irei utilizar. Basta apenas baixar o arquivo binário no link fornecido e atribuir permissão de execução com <code>chmod +x</code>, se necessário.</p>
<blockquote>
<p>Lembrando que é importante que esteja em um ambiente Linux, caso contrário não irá funcionar. Se estiver em outro ambiente e não puder virtualizar, poderá acompanhar esta saga apenas lendo, pois a ideia é também trazer muitos conceitos fundamentais de baixo-nível</p>
</blockquote>
<p>Ainda não será o código do web server, o programa proposto neste post é bastante simples, mas estamos quase lá. Vamos focar em conceitos fundamentais para que futuros artigos, que cobrem o desenvolvimento do web server, possam ser melhor compreendidos.</p>
<p>Sem mais delongas, prepare-se para a partir de agora entrar numa espiral de código de máquina e manipulação de memória.</p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#o-que-%C3%A9-um-programa-de-computador">O que é um programa de computador</a></p>
<ul>
<li><a href="#sistemas-operacionais-e-processos">Sistemas Operacionais e Processos</a></li>
<li><a href="#um-programa-deve-sempre-terminar">Um programa deve sempre terminar</a></li>
</ul>
</li>
<li>
<p><a href="#nosso-primeiro-programa">Nosso primeiro programa</a></p>
<ul>
<li><a href="#a-linguagem-das-cpus-o-sistema-bin%C3%A1rio">A linguagem das CPU's, o sistema binário</a></li>
<li><a href="#o-famoso-sistema-decimal">O famoso sistema decimal</a></li>
<li><a href="#hexadecimal-o-queridinho-dos-computadores">Hexadecimal, o queridinho dos computadores</a></li>
<li><a href="#opcodes">Opcodes</a></li>
<li><a href="#endianness">Endianness</a></li>
</ul>
</li>
<li>
<p><a href="#nosso-segundo-programa">Nosso segundo programa</a></p>
<ul>
<li><a href="#alocando-dados-na-mem%C3%B3ria-do-programa">Alocando dados na memória do programa</a></li>
<li><a href="#ascii">ASCII</a></li>
<li><a href="#syscalls">Syscalls</a></li>
<li><a href="#montando-a-syscall-write">Montando a syscall write</a></li>
<li><a href="#montando-a-syscall-exit">Montando a syscall exit</a></li>
</ul>
</li>
<li>
<p><a href="#manipulando-o-nosso-programa">Manipulando o nosso programa</a></p>
</li>
<li>
<p><a href="#a-vida-de-quem-programa-%C3%A9-assim">A vida de quem programa é assim?</a></p>
</li>
<li>
<p><a href="#conclus%C3%A3o">Conclusão</a></p>
</li>
<li>
<p><a href="#refer%C3%AAncias">Referências</a></p>
</li>
</ul>
<hr />
<h2 id="o-que-é-um-programa-de-computador">O que é um programa de computador</h2>
<p>Como já vimos na parte II, a função primordial de uma CPU é ler uma instrução da memória, decodificar, executar e armazenar o resultado de volta na memória.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/74pip1fwevxzhlgtskrq.png" alt="CPU decodifica instrução" /></p>
<p>Então a grosso modo, um programa de computador é um conjunto de instruções pra a CPU processar. Em um cenário típico, teríamos diversos programas diferentes <strong>lendo e escrevendo</strong> da mesma memória do computador:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v04zatlsnnkesdegjknq.png" alt="programas e memória" /></p>
<p>Mas um potencial problema, é que neste cenário poderíamos ter dois diferentes programas acessando ou modificando o mesmo endereço de memória:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rcdxz981arzq3d9h5e1b.png" alt="conflito em memória" /></p>
<p>Pra resolver isto, precisamos agrupar as instruções de um programa de modo a "isolar" de outros programas que também estão rodando no computador.</p>
<p>É aí que entra um dos papéis do <strong>sistema operacional</strong> com o conceito de <em>processos</em>.</p>
<blockquote>
<p>Lembrando que nesta saga, vamos focar apenas em sistemas UNIX-like, mais precisamente distruibuições GNU/Linux</p>
</blockquote>
<h3 id="sistemas-operacionais-e-processos">🔵 Sistemas Operacionais e Processos</h3>
<p>Cada programa executado no SO é encapsulado em uma estrutura chamada <em>processo</em>, que vai ter uma área virtual na memória principal.</p>
<p>Na prática, cada programa vai ter seu próprio "0x10000", isolado dos demais.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ra2p8vkdu9pu3tgthvsk.png" alt="sistemas operacionais e processos" /></p>
<h3 id="um-programa-deve-sempre-terminar">🔵 Um programa deve sempre terminar</h3>
<p>Como o SO aloca recursos de memória (dentre outros) para o processo, nosso programa precisa indicar quando termina.</p>
<p>Desta forma aquele espaço reservado de memória fica livre para ser utilizado por outro processo. Isto evita problemas como vazamento de memória entre outros.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bh2z34wvdqii8nz7w3bm.png" alt="program exit" /></p>
<p>Caso isto não seja feito, o SO vai lançar uma exceção e o programa não pode ser admitido como processo.</p>
<hr />
<h2 id="nosso-primeiro-programa">Nosso primeiro programa</h2>
<p>Vamos trabalhar inicialmente com um exemplo bastante simples. Um programa que <em>não faz nada</em>.</p>
<blockquote>
<p>Nossa Leandro, como assim um programa que não faz nada?</p>
</blockquote>
<p>Sim, parece estranho para linguagens de mais alto nível. Mas pensando em CPU isto já é alguma coisa, pelo que precisamos de ao menos algumas instruções para um programa que "não faz nada": <strong>o programa precisa terminar</strong>, lembra?.</p>
<h3 id="a-linguagem-das-cpus-o-sistema-binário">🔵 A linguagem das CPU's, o sistema binário</h3>
<p>Pensando na CPU como um dispositivo eletrônico, esta só entende pulso elétrico. Mas conseguimos abstrair tais pulsos como 0 ou 1.</p>
<p>Consequentemente, quando falamos em código de máquina para uma CPU estamos falando em instruções que utilizam <em>sistema binário</em>, composto de 0 ou 1.</p>
<p>Nosso programa que não faz nada além de "terminar" pode ser representado então pelo seguinte conjunto de instruções:</p>
<blockquote>
<p>Não se preocupe em escrever o programa. Por enquanto são só exemplos de código de máquina para que possamos entender bem os conceitos</p>
</blockquote>
<pre><code class="sourceCode"><span class="text plain">10111111 00000001 00000000 00000000 00000000   
10111000 00111100 00000000 00000000 00000000  
00001111 00000101                            
</span></code></pre>
<p>No sistema binário, cada símbolo é chamado de <strong>bit</strong>. Este simples programa tem 12 conjuntos de 8 bits cada. <em>Conte você mesmo para confirmar!</em></p>
<p>O <strong>sistema binário</strong> tem esse nome porque só fornece dois tipos de símbolos para representar números. Vamos contar:</p>
<pre><code class="sourceCode"><span class="text plain">0
1
</span></code></pre>
<p>Acabou. Com 1 dígito podemos ter 2 combinações apenas. Mas e se quisermos representar mais números? Aí nos resta ficar combinando com mais dígitos.</p>
<p>Para 2 dígitos, conseguimos aumentar para 4 combinações:</p>
<pre><code class="sourceCode"><span class="text plain">00
01
10
11
</span></code></pre>
<p>Se quisermos continuar, temos que entrar com 3 dígitos, sempre começando com o mais à esquerda possível, o que nos dá 8 combinações:</p>
<pre><code class="sourceCode"><span class="text plain">000 
001 
010 
100
100 
101 
110 
111
</span></code></pre>
<p>Com isto, temos um padrão:</p>
<ul>
<li>
<p>1 dígito: 2 combinações</p>
</li>
<li>
<p>2 dígitos: 4 combinações</p>
</li>
<li>
<p>3 dígitos: 8 combinações</p>
</li>
</ul>
<p>Repare no padrão de exponenciação. Estamos pegando o número 2 como base e aplicando o número do dígito como expoente:</p>
<p><em>numero de símbolos ^ número de dígitos</em></p>
<ul>
<li>
<p>2^1 = 2</p>
</li>
<li>
<p>2^2 = 4</p>
</li>
<li>
<p>2^3 = 8</p>
</li>
</ul>
<p>Extrapolando para 4 ou mais dígitos, podemos chegar na seguinte conclusão:</p>
<ul>
<li>
<p>2^4 = 16 combinações</p>
</li>
<li>
<p>2^5 = 32 combinações</p>
</li>
<li>
<p>2^6 = 64 combinações</p>
</li>
<li>
<p>2^7 = 128 combinações</p>
</li>
<li>
<p>2^8 = 256 combinações</p>
</li>
</ul>
<p>E assim por diante...</p>
<blockquote>
<p>Você tá brincando com minha cara, né Leandro? Vim aqui pra ficar escovando bit?</p>
</blockquote>
<p>Não exatamente. No programa, cada conjunto ali de 8 bits (chamado de <strong>byte</strong>) tem um significado para a CPU, o que faz nosso programa ter 12 bytes.</p>
<p>E como não somos uma CPU, estamos nada preocupados em representar instruções em bits, vamos então converter para o sistema decimal para conseguirmos representar nosso <strong>mesmo programa</strong> de forma mais simples e intuitiva.</p>
<h3 id="o-famoso-sistema-decimal">🔵 O famoso sistema decimal</h3>
<p>Já estamos habituados com o sistema decimal. Muitos números no nosso dia-dia são representados através do sistema decimal.</p>
<p>Falamos de números como "dez", "cento e quinze", "quarenta e dois" sem qualquer problema, pois foi o que aprendemos desde a primeira infância. Nosso cérebro já fixou o aprendizado tão intrinsicamente, que sequer pensamos que se trata de um sistema de numeração como qualquer outro.</p>
<p>Vamos por um momento <em>esquecer</em> que sabemos sistema decimal e aplicar as mesmas regras que aplicamos para o sistema binário.</p>
<p>Repetindo mais uma vez, no sistema binário temos à disposição apenas dois símbolos: 0 e 1.</p>
<blockquote>
<p>E no decimal?</p>
</blockquote>
<p>Temos <strong>dez</strong> símbolos à disposição, que são:</p>
<pre><code class="sourceCode"><span class="text plain">0 1 2 3 4 5 6 7 8 9
</span></code></pre>
<p>Tal como no sistema binário, com 1 dígito apenas temos essas 10 possibilidades acima.</p>
<p>Já chegou no nove? Acabaram as combinações? Não tem problema, vamos subir pra <em>dois dígitos</em> sempre começando pelo dígito mais à equerda possível:</p>
<pre><code class="sourceCode"><span class="text plain">00 01 02 03 04 05 06 07 08 09
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
...
...........................99
</span></code></pre>
<p>Olha só, com apenas dois dígitos no sistema decimal, podemos combinar 100 números diferentes!</p>
<p>O padrão é o mesmo no sistema binário, podemos logo aplicar exponenciação da base, sendo:</p>
<p><em>numero de símbolos ^ número de dígitos</em></p>
<p>Portanto:</p>
<ul>
<li>
<p>10^2 = 100 combinações</p>
</li>
<li>
<p>10^3 = 1000 combinações</p>
</li>
<li>
<p>10^4 = 10000 combinações</p>
</li>
<li>
<p>etc etc etc</p>
</li>
</ul>
<h3 id="convertendo-binário-em-decimal">Convertendo binário em decimal</h3>
<p>Uma vez que entendendo sistemas de numeração binário e decimal, podemos "compactar" nosso programa inicial de binário para decimal de modo a termos uma leitura mais intuitiva, não?</p>
<p>Aplicando a regra de exponenciação, não fica difícil fazer a conversão:</p>
<ul>
<li>
<p>0 é sempre 0, pois este símbolo está presente em ambos sistemas de numeração</p>
</li>
<li>
<p>Mesmo vale para 1, pois está presente em ambos</p>
</li>
</ul>
<p>Se quisermos então converter <code>10</code> (que é o próximo número depois de 1 em binário) de binário pra decimal, vamos aplicar a seguinte regra:</p>
<p><em>dígito x 2^posição do dígito</em></p>
<p>...<em>somando o resultado</em> de cada operação em dígito, onde a posição <strong>mais à direita possível</strong> começa com <em>zero</em>, pois de acordo com a senhora matemática, qualquer número elevado a <em>zero</em> é <em>UM</em>*.</p>
<p>Com isto:</p>
<ul>
<li>10 = <em>(1 x 2^1) + (0 x 2^0)</em> = 2 + 0 = <strong>2</strong></li>
</ul>
<p>Vamos extrapolar um pouquinho?</p>
<ul>
<li>
<p>11 = <em>(1 x 2^1) + (1 x 2^0)</em> = 2 + 1 = <strong>3</strong></p>
</li>
<li>
<p>100 = <em>(1 x 2^2) + (0 x 2^1) + (0 x 2^0)</em> = 2 + 0 + 0 = <strong>4</strong></p>
</li>
</ul>
<p>Yay! <em>Nice, uh?</em></p>
<p>Agora vamos converter <em>byte a byte</em> do nosso programa:</p>
<pre><code class="sourceCode"><span class="text plain">10111111 00000001 00000000 00000000 00000000   
10111000 00111100 00000000 00000000 00000000  
00001111 00000101                            
</span></code></pre>
<ul>
<li>
<p>10111111 = <em>(1 x 2^7) + (0 x 2^6) ...</em> = <strong>191</strong></p>
</li>
<li>
<p>00000001 = <em>(0 x 2^7) + (0 x 2^6) ... + (1 + 2^0)</em> = <strong>1</strong></p>
</li>
<li>
<p>etc etc etc até chegar ao 12º byte</p>
</li>
</ul>
<p>Temos então um programa convertido para decimal da seguinte forma:</p>
<pre><code class="sourceCode"><span class="text plain">191 1 0 0 0
184 60 0 0 0
15 5
</span></code></pre>
<p>Entretanto, não é comum representar sistema decimal para instruções de CPU, pois cada byte (8 bits) não seria dividido em partes iguais no sistema decimal, o que poderia causar um <em>desalinhamento</em>, criando buracos desnecessários na memória.</p>
<blockquote>
<p>Uma forma de ver este problema é que o sistema decimal composto de 10 símbolos não é divisível por 8 (resto 2), que é a quantidade de bits em um byte</p>
</blockquote>
<p>E se tivéssemos um sistema de numeração com uma <em>quantidade de dígitos</em> que fosse divisível por 8?</p>
<p>Sabendo que 16 é divisível por 8 (resto 0) e não causaria desalinhamento entre bits pra representar um programa, será que existe um sistema de numeração de 16 símbolos para podermos <strong>compactar ainda mais</strong> a representação textual do nosso programa?</p>
<p>Sim, estamos falando do <strong>sistema hexadecimal</strong>.</p>
<h3 id="hexadecimal-o-queridinho-dos-computadores">🔵 Hexadecimal, o queridinho dos computadores</h3>
<p>Certamente você já ouviu falar, viu ou até praticou hexadecimal. Similar ao que fizemos com sistema decimal, vamos esquecer tudo o que sabemos sobre hexadecimal e aplicar algumas regras.</p>
<p>Quantos símbolos temos à disposição? 16.</p>
<blockquote>
<p>Daí o nome: <strong>hexa</strong>, representando 6, e <strong>decimal</strong> representando 10. DEZ + SEIS!!!!!111</p>
</blockquote>
<p>Os primeiros 10 símbolos são exatamente como no decimal:</p>
<pre><code class="sourceCode"><span class="text plain">0 1 2 3 4 5 6 7 8 9
</span></code></pre>
<p>E quanto aos 6 <strong>símbolos</strong> restantes? Poderíamos representar emojis, gifs animados ou derivados de batata, mas seria muito mais simples representarmos as primeiras 6 letras do alfabeto, não?</p>
<pre><code class="sourceCode"><span class="text plain">0 1 2 3 4 5 6 7 8 9 A B C D E F
</span></code></pre>
<p>As regras pra combinar são as mesmas, sempre do mais à esquerda possível:</p>
<pre><code class="sourceCode"><span class="text plain">0 1 2 3 4 5 6 7 8 9 A B C D E F
10 11 12 13 14 15 16 17 18 19 ?
</span></code></pre>
<p>Qual seria o próximo? 20?</p>
<blockquote>
<p>Não, jovem, vamos combinar com as letras restantes</p>
</blockquote>
<pre><code class="sourceCode"><span class="text plain">...
19
1A
1B
1C
1D
1E
1F
</span></code></pre>
<p>Agora sim, as combinações com o dígito 2:</p>
<pre><code class="sourceCode"><span class="text plain">20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 
30 31 32 33 34 ............................. 3F 
...........................99................9F
100
</span></code></pre>
<p>Com apenas 2 dígitos no sistema hexadecimal, podemos ter 256 combinações de números diferentes!</p>
<ul>
<li>
<p>em binário, 2 dígitos = 4 combinações</p>
</li>
<li>
<p>em decimal, 2 dígitos = 100 combinações</p>
</li>
<li>
<p>em hexa, 2 dígitos = 256 combinações</p>
</li>
</ul>
<p>Por exemplo, para termos 256 combinações com 2 símbolos <code>FF</code>, precisaríamos de 8 símbolos <code>1111 1111</code> no sistema binário, <strong>obviamente ocupando mais espaço</strong> pra representar e visualizar programas.</p>
<p><em>O céu é o limite 🚀</em></p>
<p>Aplicando regra de exponenciação para convertermos pra decimal, vamos ter o seguinte:</p>
<ul>
<li>
<p>do 0 ao 9 é tudo igual</p>
</li>
<li>
<p>A = 10, B = 11, C = 12, D = 13, E = 14, F = 15</p>
</li>
</ul>
<p>Onde:</p>
<p><em>dígito do sistema * 16^posição do dígito</em></p>
<p>Com isto, convertendo <code>1A</code> e <code>FF</code> para decimal, ficaria:</p>
<ul>
<li>
<p>1A = <em>(1 * 16^1) + (10 * 16^0)</em> = 16 + 10 = <strong>26</strong></p>
</li>
<li>
<p>FF = <em>(15 * 16^1) + (15 * 16^0)</em> = 240 + 15 = <strong>255</strong></p>
</li>
</ul>
<blockquote>
<p>Ok, mas precisamos converter de binário para hexa</p>
</blockquote>
<p>Com razão, como podemos converter o byte <strong>11111111</strong> para hexadecimal? Dá pra fazer por dedução da conversão decimal, por exemplo:</p>
<ul>
<li>
<p>sabendo que o byte <strong>11111111</strong> representa 255 em decimal, e sabendo que <code>FF</code> em decimal é 255,  portanto concluímos que <code>11111111 = FF</code></p>
</li>
<li>
<p>se dividirmos o byte em 2 partes, podemos calcular que <code>1111 = F</code>, portanto chegamos no mesmo resultado</p>
</li>
</ul>
<p>Geralmente empregamos a técnica de dividir o byte em 2 partes de 4 bits cada. Assim fica mais fácil visualizar.</p>
<p>O simples programa original escrito em binário, fica então convertido em hexadecimal da seguinte forma:</p>
<pre><code class="sourceCode"><span class="text plain">BF 01 00 00 00 
B8 3C 00 00 00 
0F 05          
</span></code></pre>
<p>Opa! Já conseguimos ter uma leitura mais intuitiva, certo? Mas que raios significa <code>BF 01</code>, <code>B8 3C</code> ou <code>0F 05</code> na CPU?</p>
<h3 id="opcodes">🔵 Opcodes</h3>
<p>Cada CPU possui uma arquitetura específica. Falando de x64 (ou x86_64), esta traz um conjunto de <strong>opcodes</strong> no manual que representam as instruções disponíveis, registradores entre outras operações de CPU.</p>
<p>De acordo com o <a href="http://ref.x86asm.net/coder64.html">manual</a>:</p>
<ul>
<li>
<p>o opcode <code>BF</code> move um valor imediato para o registrador RDI</p>
</li>
<li>
<p><code>01 00 00 00</code>: valor imediato hexa que representa <code>1</code> em decimal, mas na ordem inversa no formato <strong>little-endian</strong> (vamos falar de endianness mais a seguir)</p>
</li>
<li>
<p>o opcode <code>B8</code> move um valor imediato para o registrador RAX</p>
</li>
<li>
<p><code>3C 00 00 00</code>: valor imediato hexa que representa <code>60</code> em decimal, mas na ordem inversa no formato <strong>little-endian</strong></p>
</li>
<li>
<p>o opcode <code>0F 05</code> entra no modo "kernel" do SO e aguarda a resposta de uma chamada de sistema (syscall)</p>
</li>
</ul>
<p>Mas por quê os bytes são representados na ordem inversa nesta arquitetura de CPU?</p>
<h3 id="endianness">🔵 Endianness</h3>
<p>O conceito de <strong>endianness</strong> está relacionado com a forma que CPU's lêem e processam bytes na memória.</p>
<p>Vamos trazer o exemplo de um byte em binário, <code>10000001</code>, que sabemos que é <code>129</code> em decimal. Prestando atenção nos expoentes:</p>
<p><em>2^7 + 2^6 + 2^5 + 2^4 + 2^3 + 2^2 + 2^1 + 2^0</em></p>
<ul>
<li>
<p>o bit mais à esquerda, <em>1 x 2^7</em> = 128</p>
</li>
<li>
<p>somado com o bit mais à direita, <em>1 x 2^0</em> = 1</p>
</li>
<li>
<p>o restante dos bits está tudo a zero, não precisam entrar pra soma</p>
</li>
</ul>
<p>Podemos inferir que os bits mais à direita <em>não têm tanto peso</em> no valor final, por isso são chamados <strong>bits menos significativos</strong>.</p>
<blockquote>
<p>O bit da direita incorporou apenas o valor <strong>1</strong> pro resultado final</p>
</blockquote>
<p>Da mesma forma, os bits mais à esquerda <em>têm mais peso</em> no valor final, por isso são chamados de <strong>bits mais significativos</strong>.</p>
<blockquote>
<p>O bit da esquerda incorporou <strong>128</strong> pro resultado final, trazendo mais significância</p>
</blockquote>
<p>Esta propriedade de definir significância de bits é chamada de <em>endianness</em>. Diferentes arquiteturas de CPU podem decidir ler do mais significativo ao menos significativo (padrão intuitivo de leitura, big-endian) ou do menos significativo ao mais significativo (little-endian).</p>
<p>A decisão passa por fatores históricos ou por facilitar manipulação de ponteiros. Diferentes sistemas podem decidir por inverter a leitura/escrita ou não dos bytes.</p>
<p>Na CPU x86_64, o formato é <strong>little-endian</strong>, portanto em hexa o valor de 4 bytes <code>00 0D 00 3C</code> passa a ser <code>3C 00 0D 00</code> no formato little-endian.</p>
<p>Concluindo, vamos adicionar comentários ao nosso pseudo-programa:</p>
<pre><code class="sourceCode"><span class="text plain">BF 01 00 00 00  ; MOVE 1 PARA RDI
B8 3C 00 00 00  ; MOVE 60 PARA RAX
0F 05           ; CHAMADA DE SISTEMA (SYSCALL)
</span></code></pre>
<p>Como a CPU sabe qual syscall deve executar? Por padrão, o número da syscall fica no registrador <code>RAX</code>. E como saber qual o número da syscall?</p>
<p>Neste <a href="https://x64.syscall.sh/">link</a>, temos uma lista completa de todas as syscalls da arquitetura x64, e ali podemos conferir que a syscall <code>exit</code> do kernel representa o número 60 decimal, ou <em>3C</em> hexa. É exatamente o que a instrução <code>B8 3C</code> está fazendo!</p>
<p>Mais a seguir neste artigo vamos aprofundar no mundo das syscalls e chamadas do kernel.</p>
<hr />
<h2 id="nosso-segundo-programa">Nosso segundo programa</h2>
<p>Até agora vimos apenas o código de máquina de um programa que não faz nada (apenas termina), mas foi bastante útil para entendermos sistema binário, hexadecimal e outros conceitos.</p>
<blockquote>
<p>Continuaremos ainda explorando código de máquina. Não precisa escrever nada, mas pode acompanhar com o <a href="https://github.com/leandronsp/monica/blob/main/example">código que disponibilizei</a> no início do artigo e rodar os comandos em Linux</p>
</blockquote>
<p>Vamos agora elaborar um hipotético programa que imprime "Hello, World" na saída (STDOUT). Para isto, devemos:</p>
<ul>
<li>alocar memória para a string "Hello, World"</li>
</ul>
<blockquote>
<p>Sim, dados ficam na memória junto com o programa, lembra?</p>
</blockquote>
<ul>
<li>escrever a string na saída STDOUT, que é a saída padrão do programa (em outras palavras, a "tela")</li>
</ul>
<blockquote>
<p>Se quiser mais detalhes do que é STDOUT, standard streams e redirecionamento de streams, sugiro ler <a href="https://leandronsp.com/articles/entendendo-unix-pipes-3k56">outros artigos</a> que escrevi sobre UNIX pipes</p>
</blockquote>
<ul>
<li>terminar o programa</li>
</ul>
<p><em>Alocar, imprimir, terminar</em>. Escrever no STDOUT é uma chamada de sistema, e terminar o programa é <strong>outra</strong> chamada de sistema. Portanto, temos:</p>
<ul>
<li>
<p>uma alocação de dados na memória do programa</p>
</li>
<li>
<p>2 chamadas de sistema</p>
</li>
</ul>
<h3 id="alocando-dados-na-memória-do-programa">🔵 Alocando dados na memória do programa</h3>
<p>Em linguagem de máquina, fazemos alocação byte a byte, e sabendo que queremos alocar "Hello, World" <em>literalmente</em>, como representar cada letra, o caracter <em>vírgula</em> e o caracter <em>espaço</em> na memória?</p>
<p>Precisamos de uma tradução dos caracteres para representação decimal ou hexadecimal. É isso mesmo que você está lendo, vamos entrar em <strong>ASCII</strong>.</p>
<h3 id="ascii">🔵 ASCII</h3>
<p>ASCII (American Standard Code for Information Interchange), é um padrão para codificação de caracteres em comunicação eletrônica, criado nos anos 60.</p>
<p>O padrão ASCII estabeleceu inicialmente 7 bits para cada caracter e foi concebido para suportar caracteres presentes somente na língua inglesa. Por conta desta limitação, tem suporte para um máximo de 128 caracteres (2^7) que abordam os dígitos decimais, caracteres especais e letras do alfabeto, maiúsculas e minúsculas.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t80bwvjweywmtmghmnvt.png" alt="tabela ASCII" /></p>
<p>Mais tarde veio uma extensão da tabela com um bit a mais portanto suportando mais caracteres como acentuações, porém ainda com limitações para suportar outros idiomas e caracteres especiais.</p>
<p>Tempos depois surgiu o padrão <strong>Unicode</strong>, que adiciona a capacidade de codificação de tamanho variável, permitindo assim uma multitude de caracteres e alfabetos de diversos idiomas.</p>
<blockquote>
<p>Unicode também contempla a mesma tabela ASCII nos primeiros 128 caracteres por questões de retrocompatibilidade em sistemas. Portanto, apesar de sistemas modernos utilizarem esquemas de codificação Unicode tais como UTF-8, neste artigo focaremos na terminologia ASCII por ser suficiente nos nossos exemplos</p>
</blockquote>
<p>Podemos verificar na tabela ASCII que os códigos hexa de cada caractere da nossa string são:</p>
<pre><code class="sourceCode"><span class="text plain">H: 0x48     
e: 0x65     
l: 0x6C     
l: 0x6C     
o: 0x6F
,: 0x2C
[space]: 0x20
W: 0x57
o: 0x6F
r: 0x72
l: 0x6C
d: 0x64
[newLine]: 0xA
</span></code></pre>
<blockquote>
<p><strong>0x</strong> é uma notação, um prefixo para determinar que o número depois de <em>x</em> é um hexadecimal</p>
</blockquote>
<p>Com isto podemos então escrever os primeiros bytes hexa do nosso programa:</p>
<pre><code class="sourceCode"><span class="text plain">48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 0A
</span></code></pre>
<p>Nice, agora vamos "montar" as instruções para a syscall que <em>escreve no STDOUT</em>. Como o kernel faz isso?</p>
<h3 id="syscalls">🔵 Syscalls</h3>
<p>Syscalls são <strong>chamadas de sistema</strong> onde o programa sai do modo "user" e entra no modo "kernel". Basicamente, o programa fica à espera que o kernel do sistema operacional execute a função que foi solicitada.</p>
<p>Apesar de <a href="https://x64.syscall.sh/">neste link</a> estar tudo compilado, temos que entender um fator muito importante sobre o kernel que estamos trabalhando, e se trata do <strong>kernel Linux</strong>.</p>
<p>O <a href="https://en.wikipedia.org/wiki/Linux_kernel">kernel Linux</a> foi escrito em C na virada da década de 80 para 90, e por ser escrito em C, todas as chamadas de sistema são declaradas em C.</p>
<p>Por exemplo, no <a href="https://man7.org/linux/man-pages/index.html">manual de system calls</a> do kernel podemos pesquisar sobre qualquer chamada de sistema ou comando utilitário.</p>
<p>A chamada que queremos utilizar pra escrever no STDOUT se chama <a href="https://man7.org/linux/man-pages/man2/write.2.html">write</a>, e é definida pela função:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="support type sys-types c">ssize_t</span> <span class="meta function c"><span class="entity name function c">write</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="storage type c">int</span> <span class="variable parameter c">fd</span><span class="punctuation separator c">,</span> <span class="storage modifier c">const</span> <span class="storage type c">void</span> <span class="variable parameter c">buf</span><span class="meta brackets c"><span class="punctuation section brackets begin c">[</span><span class="punctuation accessor c">.</span><span class="variable other member c">count</span><span class="punctuation section brackets end c">]</span></span><span class="punctuation separator c">,</span> <span class="support type sys-types c">size_t</span> <span class="variable parameter c">count</span><span class="punctuation section group end c">)</span></span></span><span class="punctuation terminator c">;</span>
</span></code></pre>
<p>...que está presente na biblioteca padrão C (libc), que o kernel incorpora.</p>
<p>Para distribuições GNU, que é o meu caso utilizando Ubuntu, há um repositório mirror do <code>glibc</code> que é a biblioteca padrão em C para sistemas GNU/Linux.</p>
<p>Repara que a função <code>write</code> espera 3 argumentos:</p>
<ul>
<li><code>fd</code>, ou file descriptor, que no nosso caso é o STDOUT, representado pelo valor 1</li>
</ul>
<blockquote>
<p>💡 <strong>STDIN</strong> representa 0 e <strong>STDERR</strong> representa 2. Tá lá no nosso outro artigo sobre Bash e UNIX pipes, corre dar uma olhada</p>
</blockquote>
<ul>
<li>
<p><code>buf</code>, ou buffer, que é o ponteiro para o início do buffer de dados. No caso de escrever "Hello, World" com quebra de linha, o buf apontaria para o início da string "Hello, World\n" na memória.</p>
</li>
<li>
<p><code>count</code>, que é o tamanho do buffer de dados a ser escrito. Para a string "Hello, World\n", o count seria 13, pois isso inclui os 12 caracteres da string mais 1 byte para a quebra de linha.</p>
</li>
</ul>
<h3 id="montando-a-syscall-write">🔵 Montando a syscall write</h3>
<p>Para montar uma chamada de sistema, é necessário seguir uma <em>interface</em> que determina como um programa deve comunicar com o sistema operacional.</p>
<p>Quem determina isto é a ABI (Application Binary Interface), que define como estruturas de dados ou funções computacionais conversam entre si.</p>
<p>Como precisamos chamar uma função do kernel Linux, vamos utilizar as <a href="https://en.wikipedia.org/wiki/X86_calling_conventions">convenções determinadas</a> por este sistema operacional e a arquitetura da CPU em questão.</p>
<p>Com isto, podemos montar as instruções utilizando registradores para a syscall <code>write</code>. Novamente seguindo <a href="https://x64.syscall.sh/">esta tabela</a> (que ajuda muito), vamos fazer instrução por instrução:</p>
<p>👉 <strong>ARG0</strong>
O primeiro argumento da função vai no registrador RDI, e aqui vamos colocar o valor <code>1</code> que representa o <em>file descriptor</em> STDOUT. Em hexa, o <a href="http://ref.x86asm.net/coder64.html">manual x86</a> diz que o opcode hexa é <code>BF</code>, seguido do hexa <code>00 00 00 01</code> em formato little-endian:</p>
<pre><code class="sourceCode"><span class="text plain">BF 01 00 00 00
</span></code></pre>
<p>👉 <strong>ARG1</strong>
O segundo argumento é o ponteiro para o buffer onde começa a string na memória, movido para o registrador RSI.</p>
<p>Como a string fica no começo do programa, geralmente este endereço fica em <code>0x401000</code>. Portanto, o opcode para o <code>move</code> no registrador é <code>48 BE</code> e o valor do endereço de memoria no formato little-endian em hexa, <code>00 10 40</code></p>
<pre><code class="sourceCode"><span class="text plain">48 BE 00 10 40 
</span></code></pre>
<p>👉 <strong>ARG2</strong>
Já o terceiro argumento da função vai para o registrador RDX, que representa o tamanho do buffer em bytes a ser escrito no file descriptor definido no registrador RDI (ARG0).</p>
<p>O opcode é o <code>BA</code> e o valor é <code>13</code> em hexa, que é <code>00 00 00 0D</code> só que no formato little-endian:</p>
<pre><code class="sourceCode"><span class="text plain">BA 0D 00 00 00
</span></code></pre>
<p>Agora, vamos colocar no registrador RAX o número da syscall <strong>write</strong>, que de acordo com <a href="https://x64.syscall.sh/">esta tabela</a> (sempre esta tabela, habitue-se a ela), é o número 1, mas em hexa e little-endian:</p>
<pre><code class="sourceCode"><span class="text plain">B8 01 00 00 00
</span></code></pre>
<blockquote>
<p>Falei bastante desta tabela, de syscalls e little-endian aqui, nos próximos artigos vou falar cada vez menos. A ideia é focar em outras coisas e estes detalhes estarem já bem fundamentados</p>
</blockquote>
<p>Por último, vamos montar a instrução da syscall em si, que é o opcode:</p>
<pre><code class="sourceCode"><span class="text plain">0F 05
</span></code></pre>
<p>Trecho final da syscall write:</p>
<pre><code class="sourceCode"><span class="text plain">48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 0A ; &quot;Hello, World&quot;

BF 01 00 00 00                 ; MOV 1 para RDI
48 BE 00 10 40                 ; MOV 0x401000 para RSI
BA 0D 00 00 00                 ; MOV 13 para RDX
B8 01 00 00 00                 ; MOV 1 para RAX (write)
0F 05                          ; SYSCALL
</span></code></pre>
<p>A syscall <code>write</code> já tá montada, agora falta terminar o programa.</p>
<h3 id="montando-a-syscall-exit">🔵 Montando a syscall exit</h3>
<p>A API da chamada de sistema <strong>exit</strong> pode ser consultada no <a href="https://man7.org/linux/man-pages/man2/_exit.2.html">manual</a>, e tem a seguinte assinatura no <code>glibc</code>:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="storage type c">void</span> <span class="meta function c"><span class="entity name function c">_exit</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="storage type c">int</span> <span class="variable parameter c">status</span><span class="punctuation section group end c">)</span></span></span><span class="punctuation terminator c">;</span>
</span></code></pre>
<p>👉 <strong>ARG0</strong>
O primeiro argumento é o status de término, que de acordo com a especificação <a href="https://en.wikipedia.org/wiki/POSIX">POSIX</a>, pode ser qualquer inteiro de 0 a 255 mas sendo o 0 indicando que o progama terminou sem erros.</p>
<pre><code class="sourceCode"><span class="text plain">BF 00 00 00 00
</span></code></pre>
<p>Agora, vamos ao trecho final da syscall <em>exit</em>:</p>
<pre><code class="sourceCode"><span class="text plain">BF 00 00 00 00          ; MOV 0 para RDI
B8 3C 00 00 00          ; MOV 60 para RAX (exit)
0F 05                   ; SYSCALL
</span></code></pre>
<p>Programa completo:</p>
<pre><code class="sourceCode"><span class="text plain">48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 0A
BF 01 00 00 00 
48 BE 00 10 40
BA 0D 00 00 00 
B8 01 00 00 00 
0F 05          
BF 00 00 00 00 
B8 3C 00 00 00 
0F 05          
</span></code></pre>
<p>Tomando como exemplo o <a href="https://github.com/leandronsp/monica/blob/main/example">binário que disponibilizei</a>, ele tem mais bytes por conta de headers necessários para o próprio sistema operacional admitir o programa.</p>
<p>Vamos executar o binário:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ./example</span>

<span class="meta function-call shell"><span class="variable function shell">Hello,</span></span><span class="meta function-call arguments shell"> world</span>
</span></code></pre>
<p><em>Yay! Que dia, hein?</em></p>
<hr />
<h2 id="manipulando-o-nosso-programa">Manipulando o nosso programa</h2>
<p>Com o arquivo binário em mãos, e sugiro baixar do <a href="https://github.com/leandronsp/monica/blob/main/example">repositório</a>, vamos utilizar o utilitário <code>xxd</code> que faz um dump de hexa de qualquer binário, e com ele podemos reparar que o binário vai ter, a partir do byte <em>4096</em>, a mesma quantidade de bytes que escrevemos aqui neste artigo:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">xxd</span></span><span class="meta function-call arguments shell"><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>s</span> 4096<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>g1</span><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>c8</span><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>l52</span> example</span>

<span class="meta function-call shell"><span class="variable function shell">00001000:</span></span><span class="meta function-call arguments shell"> 48 65 6c 6c 6f 2c 20 57  Hello, W</span>
<span class="meta function-call shell"><span class="variable function shell">00001008:</span></span><span class="meta function-call arguments shell"> 6f 72 6c 64 0a bf 01 00  orld....</span>
<span class="meta function-call shell"><span class="variable function shell">00001010:</span></span><span class="meta function-call arguments shell"> 00 00 48 be 00 10 40 00  ..H...@.</span>
<span class="meta function-call shell"><span class="variable function shell">00001018:</span></span><span class="meta function-call arguments shell"> 00 00 00 00 ba 0d 00 00  ........</span>
<span class="meta function-call shell"><span class="variable function shell">00001020:</span></span><span class="meta function-call arguments shell"> 00 b8 01 00 00 00 0f 05  ........</span>
<span class="meta function-call shell"><span class="variable function shell">00001028:</span></span><span class="meta function-call arguments shell"> bf 00 00 00 00 b8 3c 00  ......<span class="keyword operator assignment redirection shell">&lt;</span>.</span>
<span class="meta function-call shell"><span class="variable function shell">00001030:</span></span><span class="meta function-call arguments shell"> 00 00 0f 05              ....</span>
</span></code></pre>
<p><em>Maravilhoso, não?</em></p>
<p>E por fim, antes de concluir este artigo que por si só dá quase uma saga, vamos alterar o binário direto em código de máquina utilizando o utilitário <code>hexedit</code>.</p>
<blockquote>
<p>Esta dica peguei em <a href="https://www.youtube.com/@debxp">vídeos do Blau Araújo</a>. Ele é realmente fantástico e traz conteúdo de primeira. Pra mim é a melhor referência para conteúdo de baixo nível em pt-BR</p>
</blockquote>
<p>Para mudar o binário, rodamos o comando:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">hexedit</span></span><span class="meta function-call arguments shell"><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> --</span>color</span> example</span>
</span></code></pre>
<p>Que vai abrir um editor bastante específico. Com <code>/</code>, podemos buscar por um hexa, por exemplo "48", que vai levar para o início da string.</p>
<p>Vamos trocar o "W" maiúsculo por "w" minúsculo, diretamente em código de máquina, que significa trocar o byte <strong>57</strong> da tabela ASCII por <strong>77</strong>:</p>
<p>Então:</p>
<pre><code class="sourceCode"><span class="text plain">48 65 6C 6C  6F 2C 20 57  6F 72 6C 64  0A 
</span></code></pre>
<p>Passa a ser:</p>
<pre><code class="sourceCode"><span class="text plain">48 65 6C 6C  6F 2C 20 77  6F 72 6C 64  0A 
</span></code></pre>
<p>Gravar o arquivo com <strong>ctrl+s</strong> e depois <strong>ctrl+c</strong> para sair. Executar novamente e:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ./example</span>

<span class="meta function-call shell"><span class="variable function shell">Hello,</span></span><span class="meta function-call arguments shell"> world</span>
</span></code></pre>
<p><em>MEO DEOS, impressionante!!!!111</em></p>
<hr />
<h2 id="a-vida-de-quem-programa-é-assim">A vida de quem programa é assim?</h2>
<p>Leitores mais atentos devem estar se perguntando:</p>
<blockquote>
<p>É sempre assim a vida de quem programa? Ficar escovando bits e mudar diretamente código de máquina em hexadecimal?</p>
</blockquote>
<p>Para a maioria esmagadora dos casos, não.</p>
<p>E se a gente criasse um programa tradutor que nos permitisse <em>montar as instruções</em> em uma linguagem mais <em>human-friendly</em> e traduzisse para o código de máquina tal o que vimos aqui neste artigo?</p>
<p>Estamos falando de <strong>assemblers</strong>, que são montadores que permitem escrever em uma linguagem de montagem específica de uma arquitetura (um assembly) e converter para os opcodes, as instruções de CPU.</p>
<p>Reforçando, nesta saga vamos focar no montador NASM para a linguagem Assembly x86 de 64-bits em sistemas GNU/Linux.</p>
<hr />
<h2 id="conclusão">Conclusão</h2>
<p>Jornada longa essa, hein? Este artigo cobriu diversos conceitos fundamentais, tais como sistema binário, hexadecimal, opcodes, syscalls, libc, ASCII...</p>
<p>Estes conceitos fundamentam o entendimento para escrever código Assembly, que será o tema principal dos próximos artigos.</p>
<p>No próximo artigo, vamos abordar conceitos básicos de Assembly, buscando converter o simples programa que fizemos neste artigo em um <strong>asm</strong> (atalho pra dizer "assembly") bem organizadinho.</p>
<p>Em seguida, iremos entrar nas syscalls de socket, bind e accept justamente para montarmos o código do nosso web server. Vamos também manipular buffer de arquivos, alocar dados dinamicamente na memória, trabalhar com threads, locks, criar fila na mão, enfim, ainda há muita coisa por vir. Isto aqui é apenas <em>a ponta do iceberg</em>.</p>
<p>Não será um tutorial, mas vamos falar de mnemonics, endereçamento de memória, segmentos de memória, layout de memória de um programa, debugging com <strong>gdb</strong> entre outras coisas.</p>
<p>Fiquem ligades!</p>
<hr />
<h2 id="referências">Referências</h2><sub>
Blau Araújo, material de curso de Assembly
https://codeberg.org/blau_araujo/assembly-nasm-x86_64/raw/branch/main/pdf/aula01.pdf
Felix Cloutier, "x86 instruction reference"
https://www.felixcloutier.com/x86/
ASCII Table
https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/ASCII-Table-wide.svg/2560px-ASCII-Table-wide.svg.png
POSIX, Wikipedia
https://en.wikipedia.org/wiki/POSIX
ASM x86 Manual
http://ref.x86asm.net/coder64.html
Syscalls table
https://x64.syscall.sh/
Linux Kernel, Wikipedia
https://en.wikipedia.org/wiki/Linux_kernel
ABI, Wikipedia
https://en.wikipedia.org/wiki/Application_binary_interface
x86 calling conventions
https://en.wikipedia.org/wiki/X86_calling_conventions
</sub>
]]></description>
<pubDate>2024-04-23</pubDate>
</item>
<item>
<title>Construindo um web server em Assembly x86, parte II, história e arquitetura</title>
<link>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-ii-historia-e-arquitetura-2jb9.html</link>
<guid>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-ii-historia-e-arquitetura-2jb9.html</guid>
<description><![CDATA[<p>No <a href="https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-i-introducao-14p5">artigo anterior</a> demos uma introdução não-técnica sobre o que será esta saga de Assembly x86 conforme avançamos na construção de um web server.</p>
<p>Agora, chegou o momento de começarmos a de fato falar sobre coisas técnicas.</p>
<p>Como de costume, não gosto de esgormitar termos complexos sem a devida explicação. Portanto, vamos iniciar a saga trazendo um pouco de contexto histórico, motivações e porque estamos aqui quando o assunto é <strong>computadores</strong>.</p>
<blockquote>
<p>Okay, agora fui filósofo demais. Mas o que mais importa é que o verdadeiro Assembly são os amigos que fazemos no caminho</p>
</blockquote>
<p>Sem mais delongas, vamos ao que interessa.</p>
<hr />
<h2 id="agenda">Agenda</h2>
<ul>
<li>
<p><a href="#um-pouco-de-hist%C3%B3ria">Um pouco de história</a></p>
</li>
<li>
<p><a href="#computar-informa%C3%A7%C3%B5es">Computar informações</a></p>
<ul>
<li><a href="#m%C3%A1quina-de-turing">Máquina de Turing</a></li>
<li><a href="#arquitetura-de-von-neumann">Arquitetura de von Neumann</a></li>
<li><a href="#o-gargalo-de-von-neumann">O gargalo de von Neumann</a></li>
</ul>
</li>
<li>
<p><a href="#hierarquia-de-mem%C3%B3ria">Hierarquia de memória</a></p>
<ul>
<li><a href="#como-a-cpu-executa-instru%C3%A7%C3%B5es">Como a CPU executa instruções</a></li>
<li><a href="#registradores-de-cpu">Registradores de CPU</a></li>
</ul>
</li>
<li>
<p><a href="#isa">ISA</a></p>
<ul>
<li><a href="#cisc">CISC</a></li>
<li><a href="#risc">RISC</a></li>
</ul>
</li>
<li>
<p><a href="#por-qu%C3%AA-x86">Por quê x86?</a></p>
</li>
<li>
<p><a href="#conclus%C3%A3o">Conclusão</a></p>
</li>
<li>
<p><a href="#refer%C3%AAncias">Referências</a></p>
</li>
</ul>
<hr />
<h2 id="um-pouco-de-história">Um pouco de história</h2>
<p>Ainda muitos milhares de anos a.C, o ser humano precisava realizar cálculos. Um dos instrumentos mais primitivos para esta tarefa era o Ábaco, e certamente você já deve ter visto um:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4rnhwceutwrg1kxc1amx.jpeg" alt="abaco" /></p>
<p>Não vou entrar em detalhes em como um Ábaco funciona, sugiro que compre um e experimente. É divertido. Eu usei quando estava no ensino primário (cria dos anos 90, cof cof).</p>
<h3 id="computadores-mecânicos">Computadores mecânicos</h3>
<p>Ainda nesta "pré-história" dos computadores e já avançando para uma Europa iluminista (circa século XVII), podemos ver a seguir invenções mecânicas e projetos como a máquina de calcular de Blaise Pascal, depois a máquina analítica de Charles Babbage e então a máquina de tabulação de Herman Hollerith.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/96zo1kt2of9iohmx3f02.jpeg" alt="babbage machine" /></p>
<blockquote>
<p>💡 É da máquina de tabulação de Herman Hollerith que vem o nome do seu comprovante de pagamento "holerite"</p>
</blockquote>
<p>Estas máquinas eram mecânicas e tinham muitas limitações como não ter uma memória própria para as "instruções", mas foram muito importantes para a evolução, possibilitando mais tarde que Ada Lovelace pudesse escrever o primeiro possível algoritmo para o projeto da máquina de Babbage.</p>
<blockquote>
<p>Pra quem quiser uma explicação excelente e mais completa sobre a história dos computadores e como estes funcionam, sugiro o vídeo <a href="https://www.youtube.com/watch?v=BbnDmeNojFA">como reinventar um computador do zero</a> do canal Infinitamente.</p>
</blockquote>
<hr />
<h2 id="computar-informações">Computar informações</h2>
<p>Na era moderna dos computadores, que se dá início no século XX, é quando acontece a revolução eletrônica através das válvulas e dos transistores.</p>
<p>Mas não apenas na área da eletrônica. Foi no século XX que vimos a revolução computacional através de um modelo abstrato que abriu portas para muito do que conhecemos hoje em termos de computadores.</p>
<p>Estamos falando da <strong>máquina de Turing</strong>.</p>
<h3 id="máquina-de-turing">Máquina de Turing</h3>
<p>Nos anos 30, o matemático Alan Turing desenvolveu o conceito abstrato de uma máquina que possuía uma fita infinita, dividida em células, e um cabeçote de <strong>leitura/escrita</strong> que movia para frente e para trás na fita, possiblitando modificar o estado atual na máquina.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8hpp285hmrzc0txur45m.png" alt="turing machine" /></p>
<p>Basicamente, este modelo de máquina permitiria que certas classes de problemas pudessem ser resolvidas com operações simples.</p>
<p>Extrapolando, nesta fita, que pode representar um tipo de "memória", é possível armazenar o estado mas também outra máquina, ou seja, temos aqui o conceito de uma máquina de Turing universal, que é capaz de simular outra máquina de Turing.</p>
<p>De forma resumida, podemos colocar na fita tanto o estado (dados) quanto as próprias instruções do programa, mitigando assim o problema de limitação que os computadores primitivos tinham, que era resolver problemas complexos de forma mais simples.</p>
<p>Entretanto, a máquina de Turing era apenas uma abstração. Este conceito de instruções e estado na mesma memória precisava ser concretizado.</p>
<p><em>É aí que entra von Neumann</em>.</p>
<h3 id="arquitetura-de-von-neumann">Arquitetura de von Neumann</h3>
<p>Von Neumman foi um polímata que propôs um modelo computacional que é utilizado por muitos computadores modernos e dispositivos que usamos hoje em dia.</p>
<p>Neste modelo, temos uma unidade de processamento central, ou CPU, que é responsável por realizar cálculos aritméticos e executar instruções.</p>
<p>Conectada a esta CPU, temos o conceito de <em>memória</em> compartilhada, que vai ser usada para armazenar todas as instruções e estado de um programa de computador.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0f759rhez1y6kinc7bf.png" alt="von neumann 1" /></p>
<p>Esta arquitetura possibilitou que computadores como ENIAC e EDVAC pudessem ser desenvolvidos. O EDVAC, por sua vez, foi um dos precursores na implementação do modelo de von Neumann, com uma CPU que era conectada a uma memória compartilhada e sequencial.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmlzomad54zpeapwc2jv.jpeg" alt="edvac" /></p>
<p>À medida que os componentes computacionais foram ficando mais modernos, os computadores foram ficando menores, mais potentes, versáteis e com utilização de propósito mais geral.</p>
<p>Então, a arquitetura de von Neumann pode ainda contar com dispositivos de entrada e saída de dados (impressora, teclado, mouse, placa de rede, monitor, etc), também conhecidos como dispositivos I/O:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fer0xexjvwrt4ooiwbjh.png" alt="von neumann 2" /></p>
<p>Podemos assumir, então, que quando escrevemos um programa de computador, estamos basicamente manipulando uma memória finita (que tem fim) e dispositivos de entrada e saída de dados, através de instruções que são executadas pela CPU.</p>
<p>Tudo graças ao modelo concreto de von Neumann.</p>
<blockquote>
<p>Vale destacar que há arquiteturas computacionais que não seguem este modelo, mas aqui neste guia estamos focando em computadores de propósito geral</p>
</blockquote>
<h3 id="o-gargalo-de-von-neumann">O gargalo de von Neumann</h3>
<p>Esta arquitetura entretanto traz uma limitação. Como o barramento (caminho) entre a CPU e memória é único, tanto instruções quanto dados trafegam pelo mesmo local, levando a um cenário onde a CPU pode ficar limitada em processamento até que todos os dados sejam lidos do barramento.</p>
<p>Uma forma de mitigar este problema é definir diferentes "níveis" de memória, para que a CPU possa ter uma taxa de processamento maior.</p>
<p>Você acertou, vamos falar agora sobre a <em>hierarquia de memória</em>.</p>
<hr />
<h2 id="hierarquia-de-memória">Hierarquia de memória</h2>
<p>Nosso programa manipula memória.</p>
<blockquote>
<p>Com que frequência?</p>
</blockquote>
<p>Todo tempo.</p>
<p>Para mitigar o problema do gargalo de von Neumann, podemos definir uma hierarquia de memória, assim não só a memória principal (RAM) é "enxergada pela CPU" como memória, mas também outros dispositivos de armazenamento no sistema computacional.</p>
<p>Adicionado a isso, com a modernização de computadores no século XX, foi criada a necessidade de orquestrar e controlar todas as interfaces com o hardware. Temos então a concepção de <strong>sistemas operacionais</strong> para esta tarefa, que começam a surgir em meados dos anos 60/70, dentre eles o UNIX.</p>
<p>Ao tratarmos tudo como memória, podemos introduzir tal <strong>hierarquia</strong>. Portanto, num sistema computacional tratamos tudo (ou quase tudo) como memória e assim o sistema operacional (SO) pode abstrair de um determinado programa onde aquilo na hierarquia se encontra de fato sendo utilizado, deixando então nosso programa "livre" deste detalhe de implementação física.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i09gvyk1ext127w3u1mm.png" alt="hierarquia memoria" /></p>
<p>Quanto mais pro topo da hierarquia, menor a capacidade de armazenamento e mais caro. Por exemplo, registradores de  CPU são memórias voláteis que estão no topo.</p>
<blockquote>
<p>Vamos falar sobre registradores mais a seguir na saga</p>
</blockquote>
<p>E quanto mais pra base da hierarquia, maior a capacidade e consequentemente mais barato. Exemplo na base são as unidades de armazenamento durável não-voláteis (HD, SSD etc).</p>
<p>No meio temos a memória principal e volátil, tendo como principal exemplo a memória RAM.</p>
<p>A hierarquia de memória desempenha, então, um papel crucial na forma como a CPU gerencia e acessa memória.</p>
<h3 id="como-a-cpu-executa-instruções">Como a CPU executa instruções</h3>
<p>Para que uma CPU execute determinada instrução, é necessário ao menos um ciclo de clock, também chamado popularmente como "giro de CPU", ou <em>ciclo de CPU</em>.</p>
<p>Vamos imaginar uma coisa que fica "girando" indefinidamente igual um relógio. De forma simples, é assim que podemos imaginar o clock de uma CPU, como um giro de relógio.</p>
<p>Alguns tipos de instruções podem gastar mais de um ciclo, e determinar quais instruções vão gastar mais ou menos ciclos é algo que é projetado diretamente na <strong>construção da CPU</strong>.</p>
<p>E onde as instruções ficam armazenadas?</p>
<blockquote>
<p>Isso mesmo, na memória.</p>
</blockquote>
<p>Portanto, a CPU precisa buscar a instrução na memória, decodificar, executar e armazenar o resultado de volta na memória.</p>
<p>Tudo isto faz gastar imensos ciclos de CPU. Ao gastarmos ciclos, a CPU pode bater num limite e não conseguir atender a tantas operações no mesmo segundo. Pra não mencionar a latência que a CPU gasta pra utilizar o barramento físico e "viajar" até a memória principal.</p>
<p>Tomando como premissa a hierarquia de memória, e se ao invés de armazenar o resultado na memória principal, a CPU resolver armazenar dentro da própria CPU?</p>
<p>Conheça os <strong>registradores de CPU</strong>.</p>
<h3 id="registradores-de-cpu">Registradores de CPU</h3>
<p>Você já pode estar pensando em cache de CPU, né? Mas calma lá jovem, cache de CPU é outra seara que não pretendo entrar, não por agora.</p>
<blockquote>
<p>Mas que também tem seu lugar na hierarquia de memória</p>
</blockquote>
<p>Lembrando (mais uma vez), da hierarquia de memória, de forma muito simplificada:</p>
<ul>
<li>
<p>topo: registradores</p>
</li>
<li>
<p>depois: cache de CPU</p>
</li>
<li>
<p>ainda depois: memória principal (RAM)</p>
</li>
<li>
<p>beeem depois: memória secundária (HD, SSD)</p>
</li>
</ul>
<p>Quanto mais perto do topo, mais rápido a CPU consegue processar, mas em contrapartida é volátil e também tem menor capacidade de armazenamento.</p>
<p>Então, registradores são apenas memórias de hierarquia mais alta que são preferencialmente usadas para computação porque possuem a menor latência do conjunto de memórias disponíveis.</p>
<p>São nos registradores onde a CPU vai armazenar instruções e dados do programa em execução, de modo a manipular sem precisar ficar dando tantos "saltos" na memória principal, economizando assim latência e ciclos de CPU.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zzyclx72ff6nyr7b3ag.png" alt="von neumann - registradores" /></p>
<p>Vamos pensar nos registradores como "caixinhas" de tamanho fixo que ficam dentro da CPU.</p>
<p>E como podemos manipular os registradores da CPU? Devemos estabelecer um padrão, que define como controlar o <strong>conjunto de instruções</strong> da CPU.</p>
<p>Precisamos de uma arquitetura de conjunto de instruções, ou <strong>ISA</strong> (<em>Instruction Set Architecture</em>).</p>
<hr />
<h2 id="isa">ISA</h2>
<p>ISA serve para definir o conjunto instruções e registradores em uma determinada CPU. O fabricante define a ISA, que pode ser classificada de formas diferentes, determinando quantas operações podem ser feitas por instrução, entre outros aspectos.</p>
<p>Neste artigo vamos destacar 2 abordagens de conjunto de instruções: <em>CISC e RISC</em>.</p>
<h3 id="cisc">CISC</h3>
<p>CISC, ou <strong>Complex Instruction Set Computing</strong>, é uma arquitetura onde as instruções podem ser agrupadas em conjuntos mais complexos de instruções, permitindo que uma única instrução execute várias operações complexas.</p>
<p>Aqui, determinadas tarefas podem resultar em apenas um ciclo de CPU, o que aumenta eficiência, mas por outro lado, esta complexidade de instruções pode tornar o tempo de execução menos previsível.</p>
<p>Exemplos de arquiteturas CISC incluem System/360, PDP-11 e Intel 8086.</p>
<h3 id="risc">RISC</h3>
<p>Para resolver o problema de instruções muito complexas em CISC, a arquiteura RISC, ou <strong>Reduced Instruction Set Computing</strong>, determina uma execução mais simples com menos instruções, diminuindo assim o número de circuitos e consequentemente ciclos de CPU. O tamanho das instruções geralmente é fixo, resultando em um desempenho mais rápido e previsível.</p>
<p>Exemplos de arquiteturas RISC são MIPS e ARM, sendo ARM atualmente utilizada nos processadores de MacBook M1 em diante.</p>
<p>Este é um dos motivos de um MacBook ARM consumir menos bateria e fazer menos barulho, por exemplo.</p>
<h3 id="e-já-que-o-tema-é-x86...">E já que o tema é x86...</h3>
<p>Como a saga se trata de x86, especificamente 64-bit (logo mais vamos entender o motivo disso), inicialmente esta arquitetura foi desenvolvida seguindo o padrão CISC, que é o conjunto complexo de instruções.</p>
<p>Entretanto a ISA do x86 foi adaptada para suportar internamente operações simplificadas como encontramos em RISC, portanto pode-se sizer que x86 é um "fake-CISC", que segue um modelo "RISC-ish".</p>
<hr />
<h2 id="por-quê-x86">Por quê x86?</h2>
<p>Alguns leitores mais atentos devem estar se perguntando: por quê raios x86? O que isto significa?</p>
<p>Bom, pra entender o que é isto, vamos mergulhar um pouco na história dos microprocessadores da Intel.</p>
<h3 id="anos-70">Anos 70</h3>
<p>Os anos 70 foram primordiais. Além da explosão cambriana de sistemas operacionais, vemos também a consolidação da era dos transistores e assim a evolução das CPU's.</p>
<p>Do lado Intel, temos o 8080 de 8-bit lançado em 1974, que além de ser utilizado em sistemas industriais, também foi amplamente encontrado nos primeiros computadores pessoais.</p>
<h3 id="intel-8086">Intel 8086</h3>
<p>Esta versão traz consigo conjuntos de instruções de 16-bits e foi um marco na era dos computadores pessoais. É aqui que passa a ser cunhado o termo de família "x86", pois o "x" caracteriza qualquer número que venha antes de "86".</p>
<p>Intuitivo, não?</p>
<h3 id="anos-80-a-década-do-intel-x86">Anos 80, a década do Intel x86</h3>
<p>A partir de então, nesta década vimos a chegada do 80286 (286) que suporta também 16-bit + 8-bit de endereçamento de memória; depois, o famoso 80386 (i386), que trouxe uma grande mudança suportando instruções de 32-bit e os famosos registradores <code>exx</code> (eax, ebx, eip, etc); para então chegarmos ao 80486 (486), que foi uma melhoria do 386 com suporte a instruções mais avançadas.</p>
<blockquote>
<p>Pra quem tiver curiosidade em saber a especificação da arquitetura x86, está tudo bem documentado num simples <a href="https://software.intel.com/en-us/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4">manual de 5000 páginas</a></p>
</blockquote>
<h3 id="anos-90-pentium-e-além">Anos 90, Pentium e além</h3>
<p>O que vem a seguir é a evolução seguindo com os Pentium 586, 686 e depois, uma simplificação dos termos para x86_32 (32-bit) ou x86_64 (64-bit).</p>
<p>Destaca-se os Pentium II, III e os Core "i AlgumaCoisa" que perduram até hoje.</p>
<blockquote>
<p>E os AMD?</p>
</blockquote>
<p>Enquanto a Intel dominava o mercado de CPU's, a AMD (Advanced Micro Devices) mexeu os palitinhos e também lançou versões compatíveis com x86, portanto pode-se dizer que, ao desenvolver para arquitetura x86, é possível executar as mesmas instruções em uma CPU fabricada pela AMD.</p>
<hr />
<h2 id="conclusão">Conclusão</h2>
<p>É isto. Este foi um artigo bastante denso, que cobriu uma breve história dos computadores, passando por modelos computacionais até chegar nas arquiteturas de CPU's e entendermos o que significa aquele "x86" no título do artigo.</p>
<p>No próximo artigo, pretendo trazer brevemente sistema binário e hexadecimal para então começar a apresentar aquilo que estamos todos interessados: linguagem de montagem, ou simplesmente <strong>Assembly</strong>.</p>
<p><em>Artigo revisado com carinho por <a href="https://twitter.com/JeffQuesado">Jeff Quesado</a>, o "Coelho da Bolha", e também por <a href="https://twitter.com/_____cadu_____">Cadu</a>, o músico frustrado (same thing).</em></p>
<hr />
<h2 id="referências">Referências</h2><sub>
Ábaco, Wikipedia
https://pt.wikipedia.org/wiki/%C3%81baco
Máquina analítica, Wikipedia
https://pt.wikipedia.org/wiki/M%C3%A1quina_anal%C3%ADtica
Linguagem Assembly, Wikipedia
https://pt.wikipedia.org/wiki/Linguagem_assembly
Cronologia do x86, Wikipedia
https://pt.wikipedia.org/wiki/X86
Arquitetura de Von Neumann, Wikipedia
https://pt.wikipedia.org/wiki/Arquitetura_de_von_Neumann
Blau Araujo, "Fundamentos de Assembly com NASM"
https://codeberg.org/blau_araujo/assembly-nasm-x86_64
História da Computação, Wikipedia
https://pt.wikipedia.org/wiki/Hist%C3%B3ria_da_computa%C3%A7%C3%A3o
Inifitamente, "Como reinventar um computador do zero"
https://www.youtube.com/watch?v=BbnDmeNojFA
Total Phase, "What's a CPU register"
https://www.totalphase.com/blog/2023/05/what-is-register-in-cpu-how-does-it-work/
Turing Machine, Wikipedia
https://en.wikipedia.org/wiki/Turing_machine
Brilliant, "Turing Machines"
https://brilliant.org/wiki/turing-machines/
Instruction Set Architecture, Wikipedia
https://en.wikipedia.org/wiki/Instruction_set_architecture
</sub>
]]></description>
<pubDate>2024-04-11</pubDate>
</item>
<item>
<title>Construindo um web server em Assembly x86, parte I, introdução</title>
<link>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-i-introducao-14p5.html</link>
<guid>https://leandronsp.com/articles/construindo-um-web-server-em-assembly-x86-parte-i-introducao-14p5.html</guid>
<description><![CDATA[<p><em>Assembly</em>.</p>
<p>Para alguns, um monstrinho. Pra outros, algo antiquado. Mas pra quem tem curiosidade em entender como as coisas funcionam, <strong>oportunidade</strong>.</p>
<p>Nesta saga que será uma série de artigos, vamos explorar Assembly com NASM para arquitetura <em>x86-64</em> em GNU/Linux enquanto desenvolvemos um web server multi-thread bastante simples.</p>
<p>O intuito não está nas capacidades do web server em si, pois este irá apenas responder uma mensagem "Hello, world" em formato HTML, mas sim nos conceitos utilizados para construi-lo.</p>
<p>Para quem não tem muita familiaridade com conceitos de mais baixo-nível em computação e concorrência, não se preocupe, pois queremos com este guia fazer com que temas que são vistos como "complexos" possam ser absorvidos com mais facilidade a quem tem curiosidade, podendo então causar aquela boa impressão no churrasco de domingo ou no jantar de Natal.</p>
<blockquote>
<p>To brincando gente, tá proibido falar de Assembly nestas ocasiões, por favor não façam isso eu imploro</p>
</blockquote>
<hr />
<h2 id="conteúdo-proposto">Conteúdo proposto</h2>
<p>Ao longo dos artigos vamos passar por diversos conceitos de computação, sendo alguns de forma superficial e outros com um pouco mais de profundidade, podendo mencionar alguns:</p>
<ul>
<li>
<p>Arquitetura de computadores</p>
</li>
<li>
<p>Tipos de arquiteturas</p>
</li>
<li>
<p>Padrões, sistema binário e hexadecimal</p>
</li>
<li>
<p>Básicos de Assembly x86-64</p>
</li>
<li>
<p>Debugging com GDB</p>
</li>
<li>
<p>Filesystem, Sockets</p>
</li>
<li>
<p>Threads, pool e alocação de memória</p>
</li>
<li>
<p>Arrays, filas, ponteiros</p>
</li>
<li>
<p>Concorrência e primitivos de sincronização como spinlocks e futex</p>
</li>
<li>
<p>Tag <code>h1</code> do HTML (LOL)</p>
</li>
</ul>
<p>Poderá haver mais conceitos a serem abordados, mas que serão mapeados e detalhados conforme necessidade.</p>
<hr />
<h2 id="é-um-tutorial-de-assembly">É um tutorial de Assembly?</h2>
<p>Definitivamente, não.</p>
<p>A ideia aqui é desenvolver de forma prática um servidor web enquanto passamos por conceitos de Assembly e não só, mas também outros temas importantes sobre concorrência.</p>
<p>Se quer fazer um tutorial rápido para se familiarizar com Assembly x86, há <a href="https://www.tutorialspoint.com/assembly_programming/index.htm">este do tutorials point</a>, mas atenção que ele é para 32-bits, sendo que nosso guia será feito em 64-bits (uma vez entendido os conceitos, fica fácil transportar).</p>
<hr />
<h2 id="é-um-curso-de-assembly">É um curso de Assembly?</h2>
<p><em>Hell no</em>.</p>
<p>Obviamente, vamos aprender diversos conceitos à medida que avançamos na saga, mas se você tem algum interesse em aprender fundamentos de Assembly de forma bastante didática, sugiro acompanhar a playlist de <a href="https://www.youtube.com/live/Ej6U-qk0bdE?feature=shared">Fundamentos de Assembly x86-64</a> do Blau Araújo. Ele é referência no assunto em conteúdo pt-BR e já cortou muito mato neste assunto.</p>
<hr />
<h2 id="requisitos-de-ambiente">Requisitos de ambiente</h2>
<p>É esperado que o código seja executado em um sistema UNIX-based, preferencialmente GNU/Linux x86_64 que é onde testamos o código proposto.</p>
<ul>
<li>
<p>Sistema Operacional Ubuntu 22.04.4 LTS (GNU/Linux 6.5.0-17-generic x86_64)</p>
</li>
<li>
<p>NASM 2.16.01</p>
</li>
<li>
<p>GNU ld 2.38 (binutils)</p>
</li>
</ul>
<p>E para debugging (claro, nesta casa fazemos debugging, não somos brincalhões):</p>
<ul>
<li>
<p>GNU gdb 12.1</p>
</li>
<li>
<p>strace 5.16</p>
</li>
</ul>
<p>Para outros ambientes, pode-se optar por rodar o código dentro de um container Docker, seguindo as versões acima apresentadas.</p>
<p>Exemplo de <strong>Dockerfile</strong> (validar isto plmdds):</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">FROM</span></span><span class="meta function-call arguments shell"> ubuntu</span>
<span class="meta function-call shell"><span class="variable function shell">RUN</span></span><span class="meta function-call arguments shell"> apt-get update</span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="variable function shell">apt-get</span></span><span class="meta function-call arguments shell"><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>y</span> install make binutils gdb build-essential wget strace</span>
<span class="meta function-call shell"><span class="variable function shell">WORKDIR</span></span><span class="meta function-call arguments shell"> /app</span>
<span class="meta function-call shell"><span class="variable function shell">RUN</span></span><span class="meta function-call arguments shell"> wget https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/nasm-2.16.01.tar.gz<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>O</span> nasm.tar.gz</span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="variable function shell">tar</span></span><span class="meta function-call arguments shell"><span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>xzvf</span> nasm.tar.gz</span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="support function cd shell">cd</span></span><span class="meta function-call arguments shell"> nasm-2.16.01</span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="variable function shell">./configure</span></span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="variable function shell">make</span></span> <span class="keyword operator logical and shell">&amp;&amp;</span> <span class="meta function-call shell"><span class="variable function shell">make</span></span><span class="meta function-call arguments shell"> install</span>
</span></code></pre>
<hr />
<h2 id="será-que-consigo-acompanhar">Será que consigo acompanhar?</h2>
<p>Você pode apenas ler e tentar entender os conceitos, ou então ser mais hands-on e escrever código à medida que avança nos artigos.</p>
<p>Recomendo fortemente que experimente o código e rode em seu próprio computador seguindo os requisitos de ambiente, seja em host, virtualizado ou containerizado.</p>
<p>O repositório com o código completo pode ser encontrado em <a href="https://github.com/leandronsp/magali">leandronsp/magali</a>.</p>
<hr />
<p>Este artigo é o primeiro de uma série que vamos explorar sobre Assembly x86-64 enquanto desenvolvemos um web server do zero, sem enrolação e com muita mão na massa.</p>
<p>No próximo artigo já iremos começar com introdução a arquiteturas de computadores e o básico necessário com as terminologias e um pouco de história dos computadores, padrões e linguagens Assembly.</p>
<p>Stay tuned!</p>
]]></description>
<pubDate>2024-04-09</pubDate>
</item>
<item>
<title>Superficial, básico e avançado</title>
<link>https://leandronsp.com/articles/superficial-basico-e-avancado-148n.html</link>
<guid>https://leandronsp.com/articles/superficial-basico-e-avancado-148n.html</guid>
<description><![CDATA[<p>Ufa, finalmente meu primeiro artigo de 2024. Criei <del>vergonha na cara</del> coragem e resolvi sentar e escrever um pouco.</p>
<blockquote>
<p>Vou voltar a escrever coisas técnicas com frequência, prometo</p>
</blockquote>
<p>Mas antes de tudo, queria deixar claro que este <del>bait</del> post aqui é mais uma reflexão do que algo técnico. Não tem referências, não é uma verdade absoluta. Apenas uma reflexão.</p>
<p>Afinal, como dividimos os níveis de conhecimento? Por exemplo, costumamos ver uma divisão entre básico, intermediário e avançado, certo?</p>
<p>Aí é onde entra minha reflexão.</p>
<h2 id="um-pouco-de-contexto">Um pouco de contexto</h2>
<p>Esses dias estava conversando com uns colegas de trabalho e de repente chegamos nesse tema, sobre o que considerar básico ou avançado.</p>
<p>Pra mim, um dos problemas é que esta divisão pode causar um pouco de ansiedade em algumas pessoas, pois elas se consideram no "básico" e se vêem muito longe do conhecimento que consideram "avançado".</p>
<p>O outro problema advém da régua que estamos nivelando. Ao determinar que tudo se começa pelo básico, e ao vermos que o distanciamento para o avançado é muito grande, isto pode nos deixar presos ao que consideramos básico, portanto, sempre nivelando o conhecimento médio para <em>baixo</em>.</p>
<h2 id="o-básico-não-é-o-que-parece">O básico não é o que parece</h2>
<p>Minha provocação é que o básico não deveria ser considerada a <em>porta de entrada</em> do conhecimento em algum tema.</p>
<p>Ao entrarmos em alguma nova área de conhecimento, estamos de fato em uma <em>superfície</em>, portanto coloco este nível de conhecimento como <em>superficial</em>. Após termos um conhecimento superficial sobre algo, é o momento de entrarmos no básico, o que significa aprofundar um pouco mais neste conhecimento de tal modo que possamos estar <strong>dominando</strong> este conhecimento básico.</p>
<p>Veja, não vamos considerar o <em>domínio em algo</em> como sendo expert ou avançado naquele conhecimento. Não. O domínio do básico deveria ser de tal forma que todos nós buscamos se tivermos algum interesse e, principalmente, se formos atuar com aquele tema no dia-dia.</p>
<h2 id="deturparam-o-básico">Deturparam o básico</h2>
<p>Muito se vê comentarem sobre o problema das pessoas saberem o básico ou então criticarem quando alguém compartilha algum tipo de conteúdo considerado "básico".</p>
<p>Algumas definições de <em>básico</em> no dicionário:</p>
<blockquote>
<p>Que serve como base; essencial, basilar.</p>
</blockquote>
<blockquote>
<p>O mais relevante ou importante de; fundamental.</p>
</blockquote>
<p>Ou seja, o básico tem muito a ver com o <em>fundamental</em>, ou <em>essencial</em>. Ao meu ver, é <em>extremamente importante</em> dominarmos o básico se quisermos atuar com este conhecimento de forma frequente.</p>
<h2 id="teu-conhecimento-é-superficial">Teu conhecimento é superficial</h2>
<p>Muitas vezes, o que pensamos ser o conhecimento básico em algo é, na verdade, um conhecimento superficial.</p>
<p>Sabemos apenas a superfície. Temos uma noção de como aquilo funciona. Mas não conhecemos profundamente.</p>
<p>Avançar para o básico consiste em aprofundar neste conhecimento. E o básico pode muitas vezes parecer <strong>complexo</strong>.</p>
<p>Mas calma, já explico como dominar o conhecimento básico, e não precisa se desesperar, é necessário apenas um certo grau de dedicação que no fim vai fazer se sentir melhor e mais próximo do que consideramos <em>avançado</em>.</p>
<h2 id="domínio-do-conhecimento-básico">Domínio do conhecimento básico</h2>
<p>Okay, mas como dominar o conhecimento básico? Aqui entra uma técnica muito sofisticada que consiste em:</p>
<ul>
<li>
<p>fazer tutoriais</p>
</li>
<li>
<p>praticar</p>
</li>
</ul>
<blockquote>
<p>Ah, Leandro. Você tá de BRINCADEIRA COM A MINHA CARA??</p>
</blockquote>
<p>Calma, xofem. Tutoriais são extremamente importantes. Faça tutoriais, um, dois, três, quantos puder. Tire conclusões. Descarte o que não vale a pena.</p>
<p>E depois pratique com aquilo que já sabe. Por exemplo, ao aprender uma nova linguagem de programação, é muito útil escrever um projeto, trecho de código, algoritmo, estrutura de dado, whatever o que quiser que você já tenha feito em outras linguagens.</p>
<p>Isto se chama <em>prática</em>. A prática vai fazer você sair do nível "tutorial" e aprofundar em conceitos básicos, o que naturalmente vai te fazer dominar este nível do conhecimento.</p>
<p>Uma breve analogia (detesto analogias mas aqui vai) é quanto aos níveis de inglês, ou qualquer outro idioma. Muitos pensam que fluência em inglês está no último patamar <em>mas não</em>, a fluência está em todos os níveis: é possível saber apenas o básico do inglês mas buscar fluência dentro do básico.</p>
<p>É sobre isto que estou falando.</p>
<h2 id="saindo-do-superficial">Saindo do superficial</h2>
<p>O lance é que podemos sair do superficial. Este conhecimento de superfície costumo dizer que é como "molhar o pé na piscina". Molhou, a água tá boa? Dá um mergulho, sente a piscina (lá ele com analogia de novo, aff).</p>
<p>O superficial nos dá uma noção, mas sentimos que não dominamos. Sentimos muita dificuldade. Pra mim, muitas dificuldades em algo denunciam um conhecimento superficial, e não o básico.</p>
<p>Ao sair do superficial e buscarmos dominar o básico em algo, estamos subindo a régua, isto nos coloca mais próximos do que consideramos "avançado", mas sem adicionar ansiedade.</p>
<h2 id="tá-mas-o-quê-é-avançado">Tá mas o quê é avançado?</h2>
<p>Pra mim, o avançado é <em>basicamente</em> (trocadilho não intencional) se aprofundar ainda mais naquela área do conhecimento. É quando você, apesar de estar confortável com o conhecimento de base e não ficar bloqueado com frequência, quer entrar mais em detalhes e talvez buscar ser ainda mais proficiente naquela área.</p>
<p>Não vou aprofundar em como entrar no avançado, talvez fique pra outro post. Mas aqui meu foco é saindo de superficial e entrando no básico.</p>
<h2 id="vamos-a-exemplos-práticos">Vamos a exemplos práticos</h2>
<p>Por exemplo, em web, o conhecimento superficial seria saber que eu digito algo no navegador e alguma coisa acontece no servidor. Daí vou olhar o servidor pra ver o que aconteceu. Vejo logs, erros, etc e tento entender esses erros, perguntando, pesquisando e usando outros métodos.</p>
<p>Já o conhecimento básico me coloca num ponto onde sei que por trás desse pedido do navegador, está acontecendo a resolução de nome, roteamento, conexão TCP através da internet, onde do outro lado há uma aplicação rodando em uma porta do sistema operacional atravé de TCP, etc e etc. Este conhecimento me ajuda a aumentar o vocabulário na área e a <em>extrapolar</em> para outros contextos que não web, facilitando na resolução de problemas (troubleshooting).</p>
<p>Já o avançado é quando vou hackear roteadores, usar sysdig para fazer bait de hackers no meu servidor, entre outros aspectos (sigh).</p>
<h2 id="outro-exemplo-prático">Outro exemplo prático</h2>
<p>Compiladores. Saber que nossa linguagem é "compilada" para código de máquina é um conhecimento superficial. Conseguimos seguir adiante com este conhecimento? Claro. No dia-dia muitos de nós fazemos CRUD, não é?</p>
<p>Mas o conhecimento básico nos coloca em outro patamar, como entender que está acontecendo a etapa de análise léxica, parsing, otimizações, transformações etc antes de ser gerado de fato o código de máquina. Dominar o básico de compiladores pode ser essencial para identificar pontos de performance em alguma aplicação quando a "água bater no pescoço" em um problema bicudo.</p>
<p>Se você estiver no superficial em compiladores, okay ninguém vai te cobrar nada. Mas imagina fazer parte do grupo que foi lá, arregaçou a manga e fez aquele tweak no interpretador adicionando uma mísera flag apenas porque você sabe <em>o básico de compiladores</em>? Então...</p>
<p>Já o avançado de compiladores considero que seria entender a fundo as otimizações, criar o próprio JIT, fazer patch em runtime, escrever algoritmos de parsing e coisas do gênero.</p>
<p>And so on...</p>
<h2 id="conclusão">Conclusão</h2>
<p>Veja, cara pessoa leitora, que não quero causar aqui algum tipo de entropia. Quero apenas que entenda que é possível dominar o básico sem ansiedade, sem toda a carga imposta para saber coisas avançadas em algo.</p>
<p>Ao dominar o básico, um dia você pode encontrar inspiração e vontade para ir mais a fundo no avançado (mas isto não é de todo obrigatório), mas entenda que o conhecimento básico é que nos faz subir no conhecimento, nivelando a régua pra cima, e não pra baixo.</p>
<blockquote>
<p>Mas tudo o que você disse não é o mesmo que básico, intermediário e avançado?</p>
</blockquote>
<p>Interprete como quiser, mas a percepção de estarmos no básico nos afasta do intermediário. Bora sair do básico e ir pro intermediário então, se isto ajudar...rs</p>
<blockquote>
<p>Mas eu não quero saber o básico, quero ficar apenas no superficial</p>
</blockquote>
<p>Tá tudo bem também. É a sua escolha saber o superficial em algo. Se isto não causa nenhuma ansiedade ou te faz mal por não saber coisas mais "avançadas", é perfeitamente aceitável continuar no superficial :)</p>
<p>That's all folks!</p>
]]></description>
<pubDate>2024-03-09</pubDate>
</item>
<item>
<title>Building a dead simple background job in Rust</title>
<link>https://leandronsp.com/articles/building-a-dead-simple-background-job-in-rust-4m1d.html</link>
<guid>https://leandronsp.com/articles/building-a-dead-simple-background-job-in-rust-4m1d.html</guid>
<description><![CDATA[<p>In today's post we'll explore how to create a basic background job in Rust, simulating Rust channels with a Vector-based queue.</p>
<hr />
<h2 id="first-things-first">First things first</h2>
<p>Generally, a background job operates on one or more threads that continuously consume messages from a queue.</p>
<p>In this post, we'll use a Vector to represent our queue.</p>
<p>This Vector is an instance of the standard Rust library implementation known as <strong>VecDeque</strong>. <a href="https://doc.rust-lang.org/std/collections/struct.VecDeque.html">VecDeque</a> is a double-ended queue that acts as a growing ring buffer.</p>
<h2 id="data-model">Data model</h2>
<p>To make our solution more organized, we can define 3 structs:</p>
<h3 id="transmitter">Transmitter</h3>
<p>The transmitter (tx) holds an <strong>store</strong>, which is the queue (Vector) encapsulated by a Arc/Mutex; and an <strong>emitter</strong>, which is a Condvar, used for synchronization based on a condition.</p>
<h3 id="receiver">Receiver</h3>
<p>The receiver (rx), pretty much like the transmitter, also holds a store and an emitter.</p>
<h3 id="channel">Channel</h3>
<p>Channel holds a transmitter and a receiver.</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Transmitter</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">store</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Arc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Mutex<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">VecDeque<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">emitter</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Arc<span class="punctuation definition generic begin rust">&lt;</span>Condvar<span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Receiver</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">store</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Arc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Mutex<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">VecDeque<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">emitter</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Arc<span class="punctuation definition generic begin rust">&lt;</span>Condvar<span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Channel</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">tx</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Transmitter<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">rx</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Receiver<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre><h2 id="what-is-an-arc-in-rust">What is an Arc in Rust?</h2>
<p>The queue (VecDeque) is going to be shared across the channel for one or more threads.</p>
<p>In Rust, such problem requires shared ownership addressed by a <strong>reference counter</strong> (Rc), but since we are in a multi-thread scenario, Rc is not thread-safe, that's why we need an <em>atomic reference counter</em>, or simply <strong>Arc</strong>, which is indeed thread-safe.</p>
<blockquote>
<p>You can learn more details about smart pointers by reading my post on <a href="https://leandronsp.com/articles/understanding-the-basics-of-smart-pointers-in-rust-3dff">Understanding the basics of smart pointers in Rust</a></p>
</blockquote>
<h2 id="how-about-mutex">How about Mutex?</h2>
<p>Since Arc is a reference counter, its references are immutable. For mutability in the underlying data, we need <em>interior mutability</em> using RefCell.</p>
<blockquote>
<p>My mentioned post about smart pointers also covers interior mutability, check it out for further details</p>
</blockquote>
<p>In the same as Rc, <em>RefCell is not thread-safe</em>. For a thread-safe scenario, we need to synchronize access to data using <em>locks</em>. That's where <strong>mutual exclusion</strong> (Mutex) comes in.</p>
<h2 id="okay-and-condvar-what-the-heck-is-that">Okay, and Condvar? What the heck is that?</h2>
<p><strong>Condvar</strong> is a primitive for synchronization in concurrent systems where we can put a thread to "wait" (suspended) until a given condition is met.</p>
<p>For blocking queues, we basically want the following condition (pseudo-code):</p>
<pre><code class="sourceCode"><span class="text plain">queue = some_array
mutex = os_lock
emitter = os_condvar

// Thread is suspened until the array gets some data
// There&#39;s no CPU consume
while queue is empty
   emitter.wait(mutex)
end

// Someone emitted a signal
data = queue.pop
</span></code></pre>
<p>In other process:</p>
<pre><code class="sourceCode"><span class="text plain">queue.push(data)
emitter.signal
</span></code></pre><h2 id="data-modeling-implementation">Data modeling implementation</h2>
<p>Now, let's implement the methods <code>send</code> and <code>recv</code> (receive) in our simulated channel.</p>
<h3 id="transmitter">Transmitter</h3>
<p>The transmitter (tx) will have a method called <strong>send</strong>, which basically:</p>
<ul>
<li>
<p>locks the shared queue (<code>store.lock().unwrap()</code>)</p>
</li>
<li>
<p>pushes data to the queue (<code>push_back(data)</code>)</p>
</li>
<li>
<p>emits a signal (<code>emitter.notify_one</code>) to notify some suspended thread that is waiting for data in the queue</p>
</li>
</ul>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta impl rust"><span class="storage type impl rust">impl</span></span><span class="meta impl rust"><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span><span class="meta impl rust"> <span class="entity name impl rust">Transmitter</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span> </span><span class="meta impl rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="meta function rust"><span class="meta function rust"><span class="storage type function rust">fn</span> </span><span class="entity name function rust">send</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters begin rust">(</span><span class="keyword operator rust">&amp;</span><span class="variable parameter rust">self</span>, <span class="variable parameter rust">data</span><span class="punctuation separator rust">:</span> T</span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters end rust">)</span></span></span></span><span class="meta function rust"> </span><span class="meta function rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
        <span class="variable language rust">self</span>.store.<span class="support function rust">lock</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">push_back</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>data</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
        <span class="variable language rust">self</span>.emitter.<span class="support function rust">notify_one</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
    </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre><h3 id="receiver">Receiver</h3>
<p>The receiver (rx) has a method called <strong>recv</strong> (short for <em>receive</em>) which:</p>
<ul>
<li>
<p>creates a lock in the shared queue (<code>store.lock().unwrap()</code>)</p>
</li>
<li>
<p>suspends the current thread until the condition is met, in other words, <strong>while the queue is empty</strong>, the thread is suspended in the operating system, thus not consuming CPU (<code>emitter.wait</code>)</p>
</li>
<li>
<p>once the thread is awaken, it can pops the data from the queue (<code>store.pop_front()</code>)</p>
</li>
</ul>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta impl rust"><span class="storage type impl rust">impl</span></span><span class="meta impl rust"><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span><span class="meta impl rust"> <span class="entity name impl rust">Receiver</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span> </span><span class="meta impl rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="meta function rust"><span class="meta function rust"><span class="storage type function rust">fn</span> </span><span class="entity name function rust">recv</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters begin rust">(</span><span class="keyword operator rust">&amp;</span><span class="variable parameter rust">self</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters end rust">)</span></span></span></span><span class="meta function rust"> <span class="meta function return-type rust"><span class="punctuation separator rust">-&gt;</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span> </span><span class="meta function rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
        <span class="storage type rust">let</span> <span class="storage modifier rust">mut</span> store <span class="keyword operator rust">=</span> <span class="variable language rust">self</span>.store.<span class="support function rust">lock</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

        <span class="keyword control rust">while</span> store.<span class="support function rust">is_empty</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> <span class="meta block rust"><span class="punctuation section block begin rust">{</span>
            store <span class="keyword operator rust">=</span> <span class="variable language rust">self</span>.emitter.<span class="support function rust">wait</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>store</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
        </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span>

        store.<span class="support function rust">pop_front</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>
    </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre>
<p>Moreover, the Receiver struct can have an extra method called <strong>try_recv</strong> which does not block the thread, not using the Condvar condition:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta function rust"><span class="meta function rust"><span class="storage type function rust">fn</span> </span><span class="entity name function rust">try_recv</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters begin rust">(</span><span class="keyword operator rust">&amp;</span><span class="variable parameter rust">self</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters end rust">)</span></span></span></span><span class="meta function rust"> <span class="meta function return-type rust"><span class="punctuation separator rust">-&gt;</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span> </span><span class="meta function rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable language rust">self</span>.store.<span class="support function rust">lock</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">pop_front</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre><h3 id="channel">Channel</h3>
<p>Once the Transmitter and Receiver are already implemented, the implementation of Channel is a piece of cake:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta impl rust"><span class="storage type impl rust">impl</span></span><span class="meta impl rust"><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span><span class="meta impl rust"> <span class="entity name impl rust">Channel</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span> </span><span class="meta impl rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="meta function rust"><span class="meta function rust"><span class="storage type function rust">fn</span> </span><span class="entity name function rust">new</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters begin rust">(</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters end rust">)</span></span></span></span><span class="meta function rust"> <span class="meta function return-type rust"><span class="punctuation separator rust">-&gt;</span> <span class="storage type rust">Self</span></span> </span><span class="meta function rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
        <span class="storage type rust">let</span> store <span class="keyword operator rust">=</span> <span class="meta path rust">Arc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Mutex<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">VecDeque<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
        <span class="storage type rust">let</span> emitter <span class="keyword operator rust">=</span> <span class="meta path rust">Arc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Condvar<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

        Channel <span class="meta block rust"><span class="punctuation section block begin rust">{</span>
            tx<span class="punctuation separator rust">:</span> Transmitter <span class="meta block rust"><span class="punctuation section block begin rust">{</span> store<span class="punctuation separator rust">:</span> <span class="meta path rust">Arc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>store</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation separator rust">,</span> emitter<span class="punctuation separator rust">:</span> <span class="meta path rust">Arc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>emitter</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation separator rust">,</span>
            rx<span class="punctuation separator rust">:</span> Receiver <span class="meta block rust"><span class="punctuation section block begin rust">{</span> store<span class="punctuation separator rust">:</span> <span class="meta path rust">Arc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>store</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation separator rust">,</span> emitter<span class="punctuation separator rust">:</span> <span class="meta path rust">Arc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>emitter</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation separator rust">,</span>
        </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span>
    </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre>
<p>Note that both Mutex and Condvar are encapsulated in an Arc (atomic reference counter), because we have to share them across tx and rx at the same time.</p>
<h3 id="main">Main</h3>
<p>The <strong>main</strong> function can me implemented as follows:</p>
<ul>
<li>
<p>create a channel and binds the <strong>tx</strong> and <strong>rx</strong> respectively</p>
</li>
<li>
<p>the channel holds a shared Mutex/VecDeque and a Condvar</p>
</li>
<li>
<p>tx is used to send data to the channel</p>
</li>
<li>
<p>rx is used from the inner thread to receive data from the channel</p>
</li>
</ul>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta function rust"><span class="meta function rust"><span class="storage type function rust">fn</span> </span><span class="entity name function rust">main</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters begin rust">(</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters end rust">)</span></span></span></span><span class="meta function rust"> </span><span class="meta function rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Initialize channel
</span>    <span class="storage type rust">let</span> channel <span class="keyword operator rust">=</span> <span class="meta path rust">Channel<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
    <span class="storage type rust">let</span> <span class="meta group rust"><span class="punctuation section group begin rust">(</span>tx<span class="punctuation separator rust">,</span> rx</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> <span class="keyword operator rust">=</span> <span class="meta group rust"><span class="punctuation section group begin rust">(</span>channel.tx<span class="punctuation separator rust">,</span> channel.rx</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Push data to the channel
</span>    tx.<span class="support function rust">send</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>Some job to do: 1<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
    tx.<span class="support function rust">send</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>Another job: 2<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Process the channel
</span>    <span class="storage type rust">let</span> worker <span class="keyword operator rust">=</span> <span class="meta path rust">thread<span class="punctuation accessor rust">::</span></span>spawn<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="storage modifier rust">move</span> <span class="keyword operator rust">|</span><span class="keyword operator rust">|</span> <span class="meta block rust"><span class="punctuation section block begin rust">{</span>
        <span class="keyword control rust">loop</span> <span class="meta block rust"><span class="punctuation section block begin rust">{</span>
            <span class="storage type rust">let</span> job <span class="keyword operator rust">=</span> rx.<span class="support function rust">recv</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> we could use try_recv too
</span>
            <span class="keyword control rust">match</span> job <span class="meta block rust"><span class="punctuation section block begin rust">{</span>
                <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>job</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> <span class="keyword operator rust">=&gt;</span> <span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>Job: <span class="constant other placeholder rust">{}</span><span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation separator rust">,</span> job<span class="punctuation section group end rust">)</span></span><span class="punctuation separator rust">,</span>
                <span class="support type rust">None</span> <span class="keyword operator rust">=&gt;</span> <span class="keyword control rust">break</span><span class="punctuation separator rust">,</span>
            </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span>
        </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span>
    </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
    
    <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Push more data to the channel
</span>    tx.<span class="support function rust">send</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>Yet another job<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    worker.<span class="support function rust">join</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre>
<p>We run the code and, <strong>Yay</strong>, everything is working as expected:</p>
<pre><code class="sourceCode"><span class="text plain">Job: Some job to do: 1
Job: Another job: 2
Job: Yet another job
</span></code></pre>
<hr />
<h2 id="rust-channels-for-the-rescue">Rust channels for the rescue</h2>
<p>You may be wondering:</p>
<blockquote>
<p>Hey Leandro, why doesn't Rust bring all this stuff already built-in? Do we really need to implement a raw queue and use synchronization primitives on our own every time we want to create a channel for threads?</p>
</blockquote>
<p><em>Today is your lucky day</em>. Indeed Rust brings <strong>Channels</strong>, which employ the same techniques described in this very post, but more robust, of course:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">sync<span class="punctuation accessor rust">::</span></span>mpsc<span class="punctuation terminator rust">;</span>
<span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span>thread<span class="punctuation terminator rust">;</span>

<span class="meta function rust"><span class="meta function rust"><span class="storage type function rust">fn</span> </span><span class="entity name function rust">main</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters begin rust">(</span></span><span class="meta function rust"><span class="meta function parameters rust"><span class="punctuation section parameters end rust">)</span></span></span></span><span class="meta function rust"> </span><span class="meta function rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Initialize channel
</span>    <span class="storage type rust">let</span> <span class="meta group rust"><span class="punctuation section group begin rust">(</span>tx<span class="punctuation separator rust">,</span> rx</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> <span class="keyword operator rust">=</span> <span class="meta path rust">mpsc<span class="punctuation accessor rust">::</span></span>channel<span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Push data to the channel
</span>    tx.<span class="support function rust">send</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>Some job to do: 1<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
    tx.<span class="support function rust">send</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>Another job: 2<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    <span class="storage type rust">let</span> worker <span class="keyword operator rust">=</span> <span class="meta path rust">thread<span class="punctuation accessor rust">::</span></span>spawn<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="storage modifier rust">move</span> <span class="keyword operator rust">|</span><span class="keyword operator rust">|</span> <span class="meta block rust"><span class="punctuation section block begin rust">{</span>
        <span class="keyword control rust">loop</span> <span class="meta block rust"><span class="punctuation section block begin rust">{</span>
            <span class="storage type rust">let</span> job <span class="keyword operator rust">=</span> rx.<span class="support function rust">recv</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

            <span class="keyword control rust">match</span> job <span class="meta block rust"><span class="punctuation section block begin rust">{</span>
                <span class="support type rust">Ok</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>job</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> <span class="keyword operator rust">=&gt;</span> <span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>Job: <span class="constant other placeholder rust">{}</span><span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation separator rust">,</span> job<span class="punctuation section group end rust">)</span></span><span class="punctuation separator rust">,</span>
                <span class="support type rust">Err</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">_</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> <span class="keyword operator rust">=&gt;</span> <span class="keyword control rust">break</span><span class="punctuation separator rust">,</span>
            </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span>
        </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span>
    </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Push more data to the channel
</span>    tx.<span class="support function rust">send</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>Yet another job<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    worker.<span class="support function rust">join</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre>
<ul>
<li>
<p><code>mpsc</code> stands for <strong>multiple producers, single consumer</strong></p>
</li>
<li>
<p><code>mpsc::channel</code> creates a channel with a internal shared queue and returns a transmitter (tx) and a receiver (rx)</p>
</li>
<li>
<p>pretty much like our custom implementation, <code>tx.send</code> sends data to the channel, whereas <code>tx.recv</code> reads/pops data from the channel</p>
</li>
</ul>
<p><em>How cool is that</em>?</p>
<hr />
<h2 id="references">References</h2>
<p>https://doc.rust-lang.org/book/ch16-00-concurrency.html</p>
<p>https://doc.rust-lang.org/std/vec/struct.Vec.html</p>
<p>https://doc.rust-lang.org/std/collections/struct.VecDeque.html</p>
<p>https://leandronsp.com/articles/understanding-the-basics-of-smart-pointers-in-rust-3dff</p>
]]></description>
<pubDate>2023-11-12</pubDate>
</item>
<item>
<title>Understanding the basics of Smart Pointers in Rust</title>
<link>https://leandronsp.com/articles/understanding-the-basics-of-smart-pointers-in-rust-3dff.html</link>
<guid>https://leandronsp.com/articles/understanding-the-basics-of-smart-pointers-in-rust-3dff.html</guid>
<description><![CDATA[<p>In today's post we'll delve into the basics of smart pointers in Rust, while we build from scratch a simple linked list - starting from a singly linked list and then evolving to a doubly one.</p>
<hr />
<h2 id="prelude-intro-to-rust">Prelude, intro to Rust</h2>
<p>It's not intended to be an introduction about Rust. For that, you can follow along <a href="https://dev.to/mfcastellani/series/23318">this blogpost series</a> by <a href="https://dev.to/mfcastellani">@mfcastellani</a>.</p>
<p>Also, you can read <a href="https://www.casadocodigo.com.br/products/livro-rust">his book</a> (pt-BR). Moreover, I have a <a href="https://www.youtube.com/watch?v=6VSgMbFNUuQ">live coding video</a> where I explored the Rust fundamentals by covering an introduction to Rust, data types, functions, ownership, references, structs/enums and error handling.</p>
<p>Another content about Rust I higly recommend is presented on <a href="https://www.youtube.com/watch?v=zWXloY0sslE">this Youtube channel</a> by Bruno Rocha, which creates great videos about Rust as well (pt-BR).</p>
<blockquote>
<p>Please note that this post you are currently reading was written during a <a href="https://www.youtube.com/watch?v=bdZe0LjDUyk">live coding session (pt-BR)</a> where you can follow the process I use to write blogposts in general and how I created this particular one. It's a novel format I'm experimenting with to share content.</p>
</blockquote>
<p>However, if you are looking for introdutory content in english only, the Youtube channel <a href="https://www.youtube.com/@letsgetrusty">Let's get Rusty</a> provides great content on Rust from basics to advanced.</p>
<hr />
<p>No more introduction, let's embark on this journey of <strong>Smart Pointers in Rust</strong>.</p>
<hr />
<h2 id="table-of-contents">Table of Contents</h2>
<ul>
<li>
<p><a href="#first-things-first">First things first</a></p>
</li>
<li>
<p><a href="#a-linked-list-using-rust">A linked list using Rust</a></p>
</li>
<li>
<p><a href="#box">Meet the Box smart pointer</a></p>
</li>
<li>
<p><a href="#rc">Shared ownership using Rc</a></p>
</li>
<li>
<p><a href="#refcell">Interior mutability with RefCell</a></p>
</li>
<li>
<p><a href="#thinking-about-a-circular-linked-list">Weak references on a circular linked list</a></p>
</li>
</ul>
<hr />
<h2 id="first-things-first">👉 First things first</h2>
<p>Rust employs a mechanism for dealing with memory management where it prevents dangling references, double free error and other problems related to memory management.</p>
<p>This mechanism is called "ownership" and through <a href="https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization">RAII</a> (Resource Acquisition Is Initialization), it follows three basic rules:</p>
<ul>
<li>
<p>Each value in Rust has a single owner</p>
</li>
<li>
<p>There are only <em>one</em> owner at a time</p>
</li>
<li>
<p>When the owner's scope is finished, its associated value is dropped and invalidated</p>
</li>
</ul>
<p>When we need to transfer ownership, in case the value is in the stack (fixed-sized types), Rust performs a <em>Copy</em>:</p>
<blockquote>
<p>I'm assuming that all code snippets within this post are being executed inside a <code>fn main() {}</code> function</p>
</blockquote>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="storage type rust">let</span> age <span class="keyword operator rust">=</span> <span class="constant numeric integer decimal rust">20</span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> copied_age <span class="keyword operator rust">=</span> age<span class="punctuation terminator rust">;</span>

<span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>copied_age: <span class="constant other placeholder rust">{}</span><span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation separator rust">,</span> copied_age<span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>age: <span class="constant other placeholder rust">{}</span><span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation separator rust">,</span> age<span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> age is still valid because Rust performs a &quot;Copy&quot; for data in the stack
</span></span></code></pre>
<p>As for <em>dynamically-sized</em> types, which live in the heap, Rust performs a <em>Move</em>:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="storage type rust">let</span> name <span class="keyword operator rust">=</span> <span class="support type rust">String</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>from<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> other_name <span class="keyword operator rust">=</span> name<span class="punctuation terminator rust">;</span>

<span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>other_name: <span class="constant other placeholder rust">{}</span><span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation separator rust">,</span> other_name<span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>name: <span class="constant other placeholder rust">{}</span><span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation separator rust">,</span> name<span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> name is no loger valid because Rust performs a &quot;Move&quot;
</span>
<span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Error:
</span><span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> error[E0382]: borrow of moved value: `name`
</span></span></code></pre>
<p><em>Copy</em> literally copies the data in the stack, while the <em>Move</em> operation transfers ownership, which means that the former owner is no longer the owner and its reference is completely dropped.</p>
<hr />
<h2 id="a-linked-list-using-rust">👉 A Linked List using Rust</h2>
<p>A linked list is a data structure which represents a collection of nodes where each node points to the next node. This is basically a <strong>singly linked list</strong>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n2et97dstkxf8y265rsv.png" alt="a singly linked list" /></p>
<p>Also, we can build a linked list where each node points to the previous node as well. In this case, such a list is called <strong>doubly linked list</strong>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eq1gutt2osbn8vwiv5ew.png" alt="a doubly linked list" /></p>
<h3 id="a-singly-linked-list">🔵 A Singly Linked List</h3>
<p>The first version of our linked list will be a singly one. As we evolve to a doubly linked list, we'll bring Rust concepts about ownership, references and smart pointers.</p>
<p>We start by modeling the Node:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="entity name struct rust">Node</span> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> <span class="storage type rust">i32</span>,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> Node
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre>
<p>We are bound to situations where the <strong>next</strong> pointer points to "nothing", or simply a <code>null</code> pointer when the list reaches the end, commonly seen in a variety of programming languages.</p>
<p>But Rust has no <code>null</code> pointers. That said, we can represent the <code>next</code> pointer by using the enum <strong>Option</strong>, which in Rust gives us two possibilities of types:</p>
<ul>
<li>
<p>None (the end of the list)</p>
</li>
<li>
<p>Some(node)</p>
</li>
</ul>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="entity name struct rust">Node</span> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> <span class="storage type rust">i32</span>,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span>Node<span class="punctuation definition generic end rust">&gt;</span></span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="support type rust">None</span><span class="punctuation separator rust">,</span> head.next</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>The above code is not yet compiling:</p>
<pre><code class="sourceCode"><span class="text plain">error[E0072]: recursive type `Node` has infinite size
 --&gt; src/main.rs:2:5
  |
2 |     struct Node {
  |     ^^^^^^^^^^^
3 |         value: i32,
4 |         next: Option&lt;Node&gt;
  |                      ---- recursive without indirection
  |
help: insert some indirection (e.g., a `Box`, `Rc`, or `&amp;`) to break the cycle
  |
4 |         next: Option&lt;Box&lt;Node&gt;&gt;
  |                      ++++    +
</span></code></pre>
<p>The Rust compiler is saying that <em>Node</em> has unknown size at compile-time and as such it can't be determined, because the "next" pointer points to another Node which points to another Node and so on, infinitely.</p>
<p>This is a <strong>recursive type</strong>.</p>
<p>In order to solve this problem, we have to help the Rust compiler to use some abstraction which can allocate data on the heap and determine the size of the Node at compile-time, resolving the recursive type.</p>
<p>Such abstraction is called <strong>Box</strong>, which is a smart pointer in Rust.</p>
<hr />
<h2 id="box">👉 Box</h2>
<p>By using Box, we want to allocate the data on the heap.</p>
<p>Also, Box has a known size at compile-time. Being a pointer, the <em>size of the Box is the pointer size</em>, which makes it a good fit for recursive types.</p>
<p>The following code compiles sucessfully:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta annotation rust"><span class="punctuation definition annotation rust">#</span><span class="punctuation section group begin rust">[</span><span class="variable annotation rust">derive</span><span class="meta annotation parameters rust"><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span></span><span class="meta annotation parameters rust"><span class="meta group rust">Debug<span class="punctuation separator rust">,</span> PartialEq</span></span><span class="meta annotation parameters rust"><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="punctuation section group end rust">]</span></span>
<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="entity name struct rust">Node</span> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> <span class="storage type rust">i32</span>,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Box<span class="punctuation definition generic begin rust">&lt;</span>Node<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="support type rust">None</span><span class="punctuation separator rust">,</span> head.next</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>What if we add one more node, called "tail"?</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>As always (the Rust compilers always wins), it won't compile:</p>
<pre><code class="sourceCode"><span class="text plain">---- ^^^^ expected `Box&lt;Node&gt;`, found `Node`
</span></code></pre>
<p>We have to wrap the tail in a <em>Box</em>:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="entity name struct rust">Node</span> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> <span class="storage type rust">i32</span>,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Box<span class="punctuation definition generic begin rust">&lt;</span>Node<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> <span class="support type rust">Box</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> head.next.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<ul>
<li>
<p>We wrap the tail box in an Option (Some)</p>
</li>
<li>
<p>The <em>head.next</em> points to an <strong>Option</strong>. Because it's the enum Option, we have to call <code>unwrap</code> to fetch the underlying value</p>
</li>
</ul>
<p>Let's go further in the example and implement a <strong>doubly linked list</strong>, by specifying the <em>prev</em> attribute on the Node struct.</p>
<h3 id="a-doubly-linked-list">🔵 A Doubly Linked List</h3><pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="entity name struct rust">Node</span> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> <span class="storage type rust">i32</span>,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Box<span class="punctuation definition generic begin rust">&lt;</span>Node<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">prev</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Box<span class="punctuation definition generic begin rust">&lt;</span>Node<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> <span class="support type rust">Box</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<ul>
<li>
<p>the <code>head.prev</code> points to <code>None</code></p>
</li>
<li>
<p>the <code>tail.prev</code> points to <code>None</code> (at this moment...)</p>
</li>
</ul>
<p>In order to change the <code>tail.prev</code>, we have to mutate its underlying value, from <code>None</code> to <code>Some(head)</code>. May we change the source code:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="storage type rust">let</span> <span class="storage modifier rust">mut</span> tail <span class="keyword operator rust">=</span> <span class="support type rust">Box</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="support type rust">Box</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

tail.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> mutating the tail.prev
</span></span></code></pre>
<p>And...</p>
<pre><code class="sourceCode"><span class="text plain">error[E0382]: use of moved value: `head.next`
  --&gt; src/main.rs:14:15
   |
9  | let head = Box::new(Node { value: 1, prev: None, next: Some(tail) });
   |     ---- move occurs because `head` has type `Box&lt;Node&gt;`, which does not implement the `Copy` trait
10 |
11 | tail.prev = Some(head);
   |                  ---- value moved here
...
14 | assert_eq!(2, head.next.unwrap().value);
   |               ^^^^^^^^^ value used here after move
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/znv09sx9a23qp53f4p3k.gif" alt="a very very explosion" /></p>
<p><em>Welcome to the ownership saga in Rust!</em></p>
<p>Let's clarify some points here:</p>
<p>First, a Box has <strong>single ownership</strong>, meaning that each value holds one owner at a time. Here, in this line:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="support type rust">Box</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> value was moved here
</span></span></code></pre>
<p><code>Tail</code> has been <em>moved</em>, that's why we cannot use it later, due to ownership rules.</p>
<p>To fix that, we can make use of the method <code>clone</code> implemented in the Box, which will perform a deep copy (clone) of the value in the heap:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="support type rust">Box</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>tail.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

tail.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>Additionally, in the following line, <code>tail.prev</code> takes ownership of the value of <code>head</code>, so the value was moved to the new owner:</p>
<pre><code class="sourceCode language-rust"><span class="source rust">tail.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> value as moved here
</span></span></code></pre>
<p>Now the solution is calling <code>clone</code> as we did in the <code>tail</code>:</p>
<pre><code class="sourceCode language-rust"><span class="source rust">tail.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>head.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>Here's the current solution for a doubly linked list using Box:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta annotation rust"><span class="punctuation definition annotation rust">#</span><span class="punctuation section group begin rust">[</span><span class="variable annotation rust">derive</span><span class="meta annotation parameters rust"><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span></span><span class="meta annotation parameters rust"><span class="meta group rust">Clone</span></span><span class="meta annotation parameters rust"><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="punctuation section group end rust">]</span></span>
<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="entity name struct rust">Node</span> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> <span class="storage type rust">i32</span>,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Box<span class="punctuation definition generic begin rust">&lt;</span>Node<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">prev</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Box<span class="punctuation definition generic begin rust">&lt;</span>Node<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> <span class="storage modifier rust">mut</span> tail <span class="keyword operator rust">=</span> <span class="support type rust">Box</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="support type rust">Box</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>tail.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

tail.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>head.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> tail.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> head.next.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> tail.prev.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>By using Box, we've solved the problem but we may end up wasting memory, as demonstrated in the following picture:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aj2tz2i7kcpq0cdjzmjb.png" alt="box wasting memory on linked list" /></p>
<p>At this point in time, we have the following abstraction model about ownership, which is single and shares no value in the heap (Box):</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fkmdx1czv6jlulzwqtj.png" alt="box single ownership" /></p>
<p>We have to find a way to overcome the single ownership problem. What about <em>not taking ownership at all</em>, by using <strong>References</strong> instead?</p>
<h3 id="references--lifetimes">🔵 References &amp; Lifetimes</h3>
<p>References in Rust do not take ownership, as they allow to work with the reference of the data which is allocated in the heap.</p>
<p>This way, references can be "borrowed" without taking ownership, and as such they are bound to a mechanism called <strong>borrow checker</strong>.</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="storage type rust">let</span> name <span class="keyword operator rust">=</span> <span class="support type rust">String</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>from<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> value in the heap. name is the owner
</span><span class="storage type rust">let</span> other_name <span class="keyword operator rust">=</span> <span class="keyword operator rust">&amp;</span>name<span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> not a move. other_name has a reference to the value in the heap. name is still the owner
</span>
<span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>other_name: <span class="constant other placeholder rust">{}</span><span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation separator rust">,</span> other_name<span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">println!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>name: <span class="constant other placeholder rust">{}</span><span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation separator rust">,</span> name<span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>The above code compiles successfully. The borrow checker ensures that the reference is pointing to some valid value in the heap, thus not "moving" the ownership.</p>
<p>Let's change the code to use References instead of Box:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="entity name struct rust">Node</span> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> <span class="storage type rust">i32</span>,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="keyword operator rust">&amp;</span>Node<span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<ul>
<li>
<p>The <code>next</code> is an enum Option which wraps a <em>reference to another Node</em></p>
</li>
<li>
<p>The <code>head.next</code> is now using <code>Some(&amp;tail)</code> which is a reference to the tail (other node), instead of a Box which takes ownership</p>
</li>
</ul>
<p>But this code won't compile yet:</p>
<pre><code class="sourceCode"><span class="text plain">error[E0106]: missing lifetime specifier
 --&gt; src/main.rs:4:18
  |
4 |     next: Option&lt;&amp;Node&gt;,
  |                  ^ expected named lifetime parameter
  |
help: consider introducing a named lifetime parameter
  |
2 ~ struct Node&lt;&#39;a&gt; {
3 |     value: i32,
4 ~     next: Option&lt;&amp;&#39;a Node&gt;,
</span></code></pre>
<p>Each reference has an implicit lifetime in the Rust compiler. In our example of a linked list, the compiler can't determine the lifetime of the <code>next</code> pointer because it points to another Node which could have a different lifetime.</p>
<p>Because the borrow checker prevents dangling references by using lifetimes, we have to help the compiler by annotating lifetimes in the struct definition:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span><span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> <span class="storage type rust">i32</span>,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="keyword operator rust">&amp;</span><span class="storage modifier lifetime rust">&#39;a</span> <span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> or, using generics
</span>
<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span>, T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> T,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="keyword operator rust">&amp;</span><span class="storage modifier lifetime rust">&#39;a</span> <span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span>, T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre>
<p><em>It's quite verbose, I know.</em> 😬</p>
<p>Now the version of a singly linked list using references:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta annotation rust"><span class="punctuation definition annotation rust">#</span><span class="punctuation section group begin rust">[</span><span class="variable annotation rust">derive</span><span class="meta annotation parameters rust"><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span></span><span class="meta annotation parameters rust"><span class="meta group rust">Debug<span class="punctuation separator rust">,</span> PartialEq</span></span><span class="meta annotation parameters rust"><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="punctuation section group end rust">]</span></span>
<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span>, T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> T,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="keyword operator rust">&amp;</span><span class="storage modifier lifetime rust">&#39;a</span> <span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span>, T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> head.next.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="support type rust">None</span><span class="punctuation separator rust">,</span> tail.next</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<ul>
<li>
<p>The <code>Node</code> and its <code>next</code> (reference) node has a lifetime <code>'a</code></p>
</li>
<li>
<p>we can use tail/head even after they been applied to the repective nodes, because we took no ownership</p>
</li>
</ul>
<p>But a singly linked list is not enough. We want a doubly one:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="meta annotation rust"><span class="punctuation definition annotation rust">#</span><span class="punctuation section group begin rust">[</span><span class="variable annotation rust">derive</span><span class="meta annotation parameters rust"><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span></span><span class="meta annotation parameters rust"><span class="meta group rust">Debug<span class="punctuation separator rust">,</span> PartialEq</span></span><span class="meta annotation parameters rust"><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="punctuation section group end rust">]</span></span>
<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span>, T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> T,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="keyword operator rust">&amp;</span><span class="storage modifier lifetime rust">&#39;a</span> <span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span>, T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">prev</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="keyword operator rust">&amp;</span><span class="storage modifier lifetime rust">&#39;a</span> <span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span><span class="storage modifier lifetime rust">&#39;a</span>, T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> <span class="storage modifier rust">mut</span> tail <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span><span class="punctuation terminator rust">;</span>

tail.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> head.next.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="support type rust">None</span><span class="punctuation separator rust">,</span> tail.next</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>We run the code and...</p>
<pre><code class="sourceCode"><span class="text plain">error[E0506]: cannot assign to `tail.prev` because it is borrowed
  --&gt; src/main.rs:12:1
   |
10 | let head = Node { value: 1, prev: None, next: Some(&amp;tail) };
   |                                                    ----- `tail.prev` is borrowed here
11 |
12 | tail.prev = Some(&amp;head);
   | ^^^^^^^^^^^^^^^^^^^^^^^ `tail.prev` is assigned to here but it was already borrowed
13 |
14 | assert_eq!(1, head.value);
   | ------------------------- borrow later used here
</span></code></pre>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khry9qxk07s1com4hsik.gif" alt="yet another explosion" /></p>
<p><em>What happened here?</em></p>
<p>The <strong>borrow checker</strong> checks at compile-time that we can have only <em>one mutable reference</em> at a time in the same scope.</p>
<p>Our example has a scenario where the <code>tail.prev</code> is <strong>mutable</strong> and is already borrowed to the <code>head</code>.</p>
<p>That's why we simply <em>can't implement a doubly linked list</em> in Rust using references (AFAIK).</p>
<p>Then we should go back to ownership. But what about having a "shared ownership" instead of a "single ownership" like in the Box example?</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p2l5w1f09rr5oyx3bsk0.png" alt="ideal scenario for shared ownerhsip" /></p>
<p>Enter <em>Rc</em>.</p>
<hr />
<h2 id="rc">👉 Rc</h2>
<p>Rc stands for <strong>reference counting</strong>, which performs heap allocation, like a Box.</p>
<p>But unlike Box, it enables <em>shared ownership</em>, where one or more owners point to the same value in the heap. Each time an owner <em>comes to the party</em>, it increments the counter. When the owner goes out of scope, it decrements the counter.</p>
<p>Only when all owners are dropped, then the Rc is entirely dropped as well freeing the underlying data from the heap.</p>
<p>Rc brings one caveat: <strong>the reference must be immutable</strong>. Otherwise, it would lead to double-free errors.</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">rc<span class="punctuation accessor rust">::</span></span>Rc<span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> name <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="support type rust">String</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>from<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>strong_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="storage type rust">let</span> cloned_name <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>strong_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John<span class="punctuation definition string end rust">&quot;</span></span><span class="punctuation separator rust">,</span> <span class="keyword operator rust">*</span>cloned_name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Dereference
</span><span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John<span class="punctuation definition string end rust">&quot;</span></span><span class="punctuation separator rust">,</span> <span class="keyword operator rust">*</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span> <span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Dereference
</span></span></code></pre>
<p>Each time an <code>Rc</code> is called <code>data.clone()</code> or by using <code>Rc::clone(&amp;data)</code>, the data is not being copied on the heap (deep copy). Only the reference is copied and the strong count of references is incremented.</p>
<p>The original owner is still valid after <em>cloning</em> multiple Rc references.</p>
<p>Let's implement the singly linked list using Rc instead of references or Box:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">rc<span class="punctuation accessor rust">::</span></span>Rc<span class="punctuation terminator rust">;</span>

<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> T,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Rc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>
</span></code></pre>
<p>Cool, now let's add some data to our linked list:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> head.next.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>It simply works! <em>How cool is that?</em></p>
<p>Time to evolve to a doubly linked list using Rc:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">rc<span class="punctuation accessor rust">::</span></span>Rc<span class="punctuation terminator rust">;</span>

<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> T,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Rc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">prev</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Rc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

tail.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> head.next.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>Instead of deep copy like in Box, the Rc smart pointer only increments the reference counter. Check <code>Rc::clone(&amp;head)</code> and <code>Rc::clone(&amp;tail)</code>.</p>
<p>But it won't compile:</p>
<pre><code class="sourceCode"><span class="text plain">error[E0594]: cannot assign to data in an `Rc`
  --&gt; src/main.rs:24:5
   |
24 |     tail.prev = Some(Rc::clone(&amp;head));
   |     ^^^^^^^^^ cannot assign
</span></code></pre>
<p><em>Cannot assign data in an Rc!</em></p>
<p>Even if we used <code>let mut tail = ...</code>, Rc is now allowed to mutate because <strong>all references in Rc are immutable</strong>.</p>
<p>How about <em>mutating the underlying data</em> even if the reference is immutable? We could achieve that by using "unsafe Rust", where <strong>some checks could be done at runtime instead of compile-time.</strong></p>
<p>Even better, what about Rust providing an abstraction which uses unsafe capabilities under the hood but wrapping in a safe API?</p>
<p>Yes, <em>we are talking about RefCell</em>.</p>
<hr />
<h2 id="refcell">👉 RefCell</h2>
<p><strong>RefCell</strong> is an smart pointer which provides a safe API to mutate underlying data (on the heap) but through immutable references.</p>
<p>This approach is called <strong>interior mutability</strong>.</p>
<p>The borrow checker won't perform checks, but Rust will check them at runtime. In case we cause a problem regarding mutable data, the program will crash and stop (<code>panic!</code>).</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">cell<span class="punctuation accessor rust">::</span></span>RefCell<span class="punctuation terminator rust">;</span>

<span class="storage type rust">let</span> name <span class="keyword operator rust">=</span> <span class="meta path rust">RefCell<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="support type rust">String</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>from<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
name.<span class="support function rust">borrow_mut</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">push_str</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span> Doe<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John Doe<span class="punctuation definition string end rust">&quot;</span></span><span class="punctuation separator rust">,</span> <span class="keyword operator rust">*</span>name.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<ul>
<li>
<p>RefCell wraps a String in the heap</p>
</li>
<li>
<p>The reference is immutable</p>
</li>
<li>
<p>Through <code>borrow_mut</code>, we get <code>RefMut&lt;T&gt;</code> to mutate the underlying data</p>
</li>
<li>
<p>Through <code>borrow</code>, we get a <code>Ref&lt;T&gt;</code> to read the underlying data</p>
</li>
</ul>
<p>In a RefCell, we can have multiple borrows for reading or <strong>only one borrow mutable</strong> for writing.</p>
<p>With that in place, time to implement our doubly linked list using Rc + RefCell:</p>
<pre><code class="sourceCode language-rust"><span class="source rust">    <span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">rc<span class="punctuation accessor rust">::</span></span>Rc<span class="punctuation terminator rust">;</span>
    <span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">cell<span class="punctuation accessor rust">::</span></span>RefCell<span class="punctuation terminator rust">;</span>

    <span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
        <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> T,
        <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Rc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">RefCell<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
        <span class="variable other member rust">prev</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Rc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">RefCell<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

    <span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">RefCell<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
    <span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">RefCell<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    tail.<span class="support function rust">borrow_mut</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

    <span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
    <span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> head.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.next.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
    <span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> tail.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.prev.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>Our Node model now is composed of a value and a <code>next</code> pointer which basically is:</p>
<ul>
<li>
<p>an enum Option</p>
</li>
<li>
<p>which wraps an Rc (shared ownership)</p>
</li>
<li>
<p>which wraps an RefCell (for interior mutability)</p>
</li>
<li>
<p>which points to other Node</p>
</li>
<li>
<p>and so on and on and on...</p>
</li>
</ul>
<p>With RefCell, every time we have to write, we use <code>borrow_mut</code>, and every time we have to read, we use <code>borrow</code>.</p>
<p><em>How wonderful is that?</em></p>
<hr />
<h2 id="thinking-about-a-circular-linked-list">👉 Thinking about a circular linked list</h2>
<p>In order to make our linked list to be circular, we have to make <code>tail.next</code> point to the <code>head</code>:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">rc<span class="punctuation accessor rust">::</span></span>Rc<span class="punctuation terminator rust">;</span>
<span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">cell<span class="punctuation accessor rust">::</span></span>RefCell<span class="punctuation terminator rust">;</span>

<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> T,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Rc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">RefCell<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">prev</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Rc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">RefCell<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">RefCell<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">RefCell<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

tail.<span class="support function rust">borrow_mut</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
tail.<span class="support function rust">borrow_mut</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.next <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="keyword operator rust">...</span>.
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> tail.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.next.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>What's the challenges of a circular linked list using Rc?</p>
<h3 id="strong-references-may-never-reach-zero">🔵 Strong references may never reach zero</h3>
<p>Remember that the Rc underlying data is dropped and invalidated when the <code>Rc::strong_count</code> reaches zero.</p>
<p>But in a circular linked list, for instance, we may have a <strong>cyclic reference</strong>, which in turn will never make the <code>strong_count</code> to reach zero, <strong>leading to memory leaks</strong>.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8z6cj08ae1c2788j1uva.png" alt="cyclic references" /></p>
<p>In such a scenario, the <code>tail.next</code> is a "weak" reference. Rust provides a way for <code>Rc</code> to have a different counter, called <code>weak_count</code>.</p>
<p>Thus, the weak counter will not be used for deciding when Rust should drop the value from the heap.</p>
<p>For solving this problem, Rc brings a method called <code>downgrade</code>, which <strong>does not involve ownership at all</strong> and transforms a strong reference into a weak one.</p>
<p>This smart pointer is called <strong>Weak</strong> and it's a weak reference in an <em>Rc</em>.</p>
<p>Let's see a basic usage of downgrading or upgrading references in an Rc (see below in the comments):</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">rc<span class="punctuation accessor rust">::</span></span>Rc<span class="punctuation terminator rust">;</span>

<span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Just a strong reference
</span><span class="storage type rust">let</span> name <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="support type rust">String</span><span class="meta path rust"><span class="punctuation accessor rust">::</span></span>from<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John<span class="punctuation definition string end rust">&quot;</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>strong_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Cloning Rc is a strong reference
</span><span class="storage type rust">let</span> _other_name <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>strong_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">0</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>weak_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Downgrade makes it a weak reference
</span><span class="storage type rust">let</span> weak_name <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>downgrade<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>strong_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>weak_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Upgrade makes it a strong reference again
</span><span class="storage type rust">let</span> upgraded_name <span class="keyword operator rust">=</span> weak_name.<span class="support function rust">upgrade</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">3</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>strong_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>weak_count<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="string quoted double rust"><span class="punctuation definition string begin rust">&quot;</span>John<span class="punctuation definition string end rust">&quot;</span></span><span class="punctuation separator rust">,</span> <span class="keyword operator rust">*</span>upgraded_name</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<p>In a linked list, the <code>prev</code> should be the "weak" reference because starting from the head, the Rc has already strong references that make the entire linked list through the <code>next</code> pointers.</p>
<p>Now, let's explore the final solution of this entire blogpost, using <code>Rc</code> for <strong>shared ownership</strong>, <code>RefCell</code> for <strong>interior mutability</strong> and <code>Rc::Weak</code> for preventing cyclic references in a linked list:</p>
<pre><code class="sourceCode language-rust"><span class="source rust"><span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">rc<span class="punctuation accessor rust">::</span></span>Rc<span class="punctuation terminator rust">;</span>
<span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">cell<span class="punctuation accessor rust">::</span></span>RefCell<span class="punctuation terminator rust">;</span>
<span class="keyword other rust">use</span> <span class="meta path rust">std<span class="punctuation accessor rust">::</span></span><span class="meta path rust">rc<span class="punctuation accessor rust">::</span></span>Weak<span class="punctuation terminator rust">;</span>

<span class="meta struct rust"><span class="storage type struct rust">struct</span> </span><span class="meta struct rust"><span class="meta generic rust"><span class="entity name struct rust">Node</span><span class="meta generic rust"><span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span></span></span><span class="meta struct rust"> </span><span class="meta struct rust"><span class="meta block rust"><span class="punctuation section block begin rust">{</span>
    <span class="variable other member rust">value</span><span class="punctuation separator rust">:</span> T,
    <span class="variable other member rust">next</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Rc<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">RefCell<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
    <span class="variable other member rust">prev</span><span class="punctuation separator rust">:</span> <span class="meta generic rust">Option<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Weak<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">RefCell<span class="punctuation definition generic begin rust">&lt;</span><span class="meta generic rust">Node<span class="punctuation definition generic begin rust">&lt;</span>T<span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span><span class="punctuation definition generic end rust">&gt;</span></span>,
</span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span>

<span class="storage type rust">let</span> tail <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">RefCell<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">None</span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="storage type rust">let</span> head <span class="keyword operator rust">=</span> <span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">RefCell<span class="punctuation accessor rust">::</span></span>new<span class="meta group rust"><span class="punctuation section group begin rust">(</span>Node <span class="meta block rust"><span class="punctuation section block begin rust">{</span> value<span class="punctuation separator rust">:</span> <span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> prev<span class="punctuation separator rust">:</span> <span class="support type rust">None</span><span class="punctuation separator rust">,</span> next<span class="punctuation separator rust">:</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>tail</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span> </span><span class="meta block rust"><span class="punctuation section block end rust">}</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Weak reference (no ownership)
</span>tail.<span class="support function rust">borrow_mut</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.prev <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>downgrade<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="comment line double-slash rust"><span class="punctuation definition comment rust">//</span> Strong reference (shared ownership)
</span>tail.<span class="support function rust">borrow_mut</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.next <span class="keyword operator rust">=</span> <span class="support type rust">Some</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="meta path rust">Rc<span class="punctuation accessor rust">::</span></span>clone<span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="keyword operator rust">&amp;</span>head</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>

<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> head.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">2</span><span class="punctuation separator rust">,</span> head.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.next.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> tail.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.prev.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">upgrade</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
<span class="support macro rust">assert_eq!</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span><span class="constant numeric integer decimal rust">1</span><span class="punctuation separator rust">,</span> tail.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.next.<span class="support function rust">clone</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">unwrap</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.<span class="support function rust">borrow</span><span class="meta group rust"><span class="punctuation section group begin rust">(</span></span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span>.value</span><span class="meta group rust"><span class="punctuation section group end rust">)</span></span><span class="punctuation terminator rust">;</span>
</span></code></pre>
<hr />
<h2 id="wrapping-up">Wrapping Up</h2>
<p>In this very post we demonstrated the fundamentals smart pointers in Rust and the problems they solve about memory management.</p>
<p>This post was written during a <a href="https://www.youtube.com/watch?v=bdZe0LjDUyk">live coding</a> while building a doubly linked list by explaining fundamental concepts of ownership, references, borrowing and smart pointers.</p>
<p>I hope you had fun while learning a bit more about the <em>Rust ownership mental model</em> as I did.</p>
<p><strong>Cheers!</strong></p>
<hr />
<h2 id="references">References</h2>
<p>https://doc.rust-lang.org/book/</p>
<p>https://en.wikipedia.org/wiki/Smart_pointer</p>
<p>https://ricardomartins.cc/2016/06/08/interior-mutability</p>
<p>https://www.youtube.com/watch?v=6VSgMbFNUuQ</p>
]]></description>
<pubDate>2023-11-01</pubDate>
</item>
<item>
<title>Compiladores, trampolim, deque e thread pool</title>
<link>https://leandronsp.com/articles/compiladores-trampolim-deque-e-thread-pool-dd1.html</link>
<guid>https://leandronsp.com/articles/compiladores-trampolim-deque-e-thread-pool-dd1.html</guid>
<description><![CDATA[<p>Faz alguns dias que não escrevo. Minha rotina mudou um pouco e também tenho focado em estudar algumas coisas que eu não tinha tanto domínio. Entretanto tenho algumas coisas pra compartilhar.</p>
<p>Vamos a isso.</p>
<hr />
<h2 id="rinha-de-compiladores">Rinha de compiladores</h2>
<p>Em Setembro de 2023 aconteceu na tal #bolhaDev uma <a href="https://github.com/aripiprazole/rinha-de-compiler">outra competição</a> em formato de rinha, mas desta vez o desafio era a <strong>construção de um compilador/interpretador</strong> que fosse capaz de rodar um programa escrito em uma linguagem especificada para a rinha, chamada - guess what -, <em>rinha</em>.</p>
<p>A competição foi criada por duas meninas fantásticas e que entendem muito desse mundo de compiladores: a <a href="https://twitter.com/algebraic_sofia">Sofia</a> e a <a href="https://twitter.com/algebraic_gabi">Gabi</a>. Ambas tinham o intuito de despertar mais o interesse das pessoas nesse tema de compiladores, o que foi atingido com sucesso: <em>190 projetos</em> foram submetidos em diversas linguagens de programação. Teve até projetos <a href="https://github.com/jeffque/rinha-compiler">submetidos</a> em <a href="https://github.com/tiagosh/garbash">Bash</a> (desta vez não fui eu, risos).</p>
<p>Inicialmente eu só tinha interesse em acompanhar esta rinha de perto sem submeter, apenas pra aprender mais com essa galera que manja bastante. Eu já tinha feito algumas coisas bastante básicas sobre compiladores na faculdade há muito tempo atrás.</p>
<p>Mas após ver a live do brabo <a href="https://www.youtube.com/watch?v=FbCdhicY3sk">Navarro</a>, que trouxe uma didática excelente com sua versão em Rust, decidi entrar também com o intuito de aprender mais e praticar algumas técnicas.</p>
<p>Escolhi Ruby porque eu queria testar um negócio. E disto saiu o <a href="https://github.com/leandronsp/patropi">patropi</a>.</p>
<p>Okay, mas o que era pra ser feito de fato? Vamos voltar duas casas e entender primeiro <strong>o que raios é um compilador ou interpretador</strong>.</p>
<h3 id="arquitetura-de-cpu-e-código-de-máquina">👉🏽 Arquitetura de CPU e código de máquina</h3>
<p>Para que uma CPU possa processar informações, é necessário organizá-la em um conjunto coeso de instruções. A este conjunto organizado de instruções para uma determinada CPU chamamos de <strong>arquitetura da CPU</strong>.</p>
<p>Existem diversos tipos de arquiteturas de CPU disponíveis, e cada CPU traz um conjunto específico de instruções. Exemplos de arquiteturas: x86, x86-64 (64-bits), ARM (baseada em RISC), MIPS, SPARC, PowerPC dentre outros.</p>
<p>As instruções da CPU são mapeadas para componentes da arquitetura chamados <em>registradores</em>. Para manipularmos esses registradores, precisamos utilizar um conjunto de "códigos" que são pré-definidos pelo fabricante da arquitetura da CPU. Estes códigos são chamados de <strong>opcodes</strong>, ou código de máquina, ou instruções de máquina.</p>
<pre><code class="sourceCode"><span class="text plain">0000000000401000 
  401000:       48 c7 c0 01 00 00 00    
  401007:       48 c7 c7 01 00 00 00    
  40100e:       48 c7 c6 00 20 40 00    
  401015:       48 c7 c2 0e 00 00 00    
  40101c:       0f 05                   
  40101e:       48 c7 c0 3c 00 00 00    
  401025:       48 31 ff                
  401028:       0f 05                   
</span></code></pre>
<p>Escrever programas em código de máquina pode ser bastante desafiador, por isso alguns sistemas operacionais e bibliotecas trazem consigo um programa que auxilia na "montagem" desse código de máquina, possibilitando assim escrever programas em uma linguagem mnemônica com base em letras, números e símbolos, sendo mais fácil de memorizar do que os opcodes.</p>
<p>A estes montadores chamamos de <strong>assemblers</strong>.</p>
<h3 id="assemblers">👉🏽 Assemblers</h3>
<p>Com um assembler, podemos escrever código de montagem (assembly), que é convertido para código de máquina.</p>
<p>Exemplo de um simples programa escrito em assembly x86_64 que imprime <code>Hello, World!</code> no standard output:</p>
<pre><code class="sourceCode"><span class="text plain">.section .data
hello:
    .ascii &quot;Hello, World!\n&quot;

.section .text
.global _start

_start:
    # write our string to stdout
    movq $1, %rax         # syscall number for sys_write
    movq $1, %rdi         # file descriptor 1 is stdout
    movq $hello, %rsi     # pointer to the hello string
    movq $14, %rdx        # length of the hello string plus newline character
    syscall               # invoke the kernel

    # exit
    movq $60, %rax        # syscall number for sys_exit
    xorq %rdi, %rdi       # exit code 0
    syscall               # invoke the kernel
</span></code></pre>
<p>Após executar o programa com o assembler <code>as</code> que vem acompanhado no GNU/Linux seguido do linker <code>ld</code>, temos o binário com o código de máquina.</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> as<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>o</span> hello.o hello.s </span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ld<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>o</span> hello hello.o</span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ./hello</span>

<span class="meta function-call shell"><span class="variable function shell">Hello,</span></span><span class="meta function-call arguments shell"> World!</span>
</span></code></pre>
<p>Uma forma de fazer o "disassembly" do binário e ver o assembly equivalente, é com o utilitário <code>objdump</code>, onde podemos ver as instruções de máquina (opcodes) mapeadas para cada instrução assembly contida no nosso código fonte:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> objdump<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>d</span> hello</span>

<span class="meta function-call shell"><span class="variable function shell">hello:</span></span><span class="meta function-call arguments shell">     file format elf64-x86-64</span>


<span class="meta function-call shell"><span class="variable function shell">Disassembly</span></span><span class="meta function-call arguments shell"> of section .text:</span>

<span class="meta function-call shell"><span class="variable function shell">0000000000401000</span></span><span class="meta function-call arguments shell"> <span class="keyword operator assignment redirection shell">&lt;</span>_start<span class="keyword operator assignment redirection shell">&gt;</span>:</span>
  <span class="meta function-call shell"><span class="variable function shell">401000:</span></span><span class="meta function-call arguments shell">       48 c7 c0 01 00 00 00    mov    <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">0</span></span>x1,<span class="meta group expansion job shell"><span class="punctuation definition variable job shell">%</span><span class="variable other readwrite shell">rax</span></span></span>
  <span class="meta function-call shell"><span class="variable function shell">401007:</span></span><span class="meta function-call arguments shell">       48 c7 c7 01 00 00 00    mov    <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">0</span></span>x1,<span class="meta group expansion job shell"><span class="punctuation definition variable job shell">%</span><span class="variable other readwrite shell">rdi</span></span></span>
  <span class="meta function-call shell"><span class="variable function shell">40100e:</span></span><span class="meta function-call arguments shell">       48 c7 c6 00 20 40 00    mov    <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">0</span></span>x402000,<span class="meta group expansion job shell"><span class="punctuation definition variable job shell">%</span><span class="variable other readwrite shell">rsi</span></span></span>
  <span class="meta function-call shell"><span class="variable function shell">401015:</span></span><span class="meta function-call arguments shell">       48 c7 c2 0e 00 00 00    mov    <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">0</span></span>xe,<span class="meta group expansion job shell"><span class="punctuation definition variable job shell">%</span><span class="variable other readwrite shell">rdx</span></span></span>
  <span class="meta function-call shell"><span class="variable function shell">40101c:</span></span><span class="meta function-call arguments shell">       0f 05                   syscall</span>
  <span class="meta function-call shell"><span class="variable function shell">40101e:</span></span><span class="meta function-call arguments shell">       48 c7 c0 3c 00 00 00    mov    <span class="meta group expansion parameter shell"><span class="punctuation definition variable shell">$</span><span class="variable other readwrite shell">0</span></span>x3c,<span class="meta group expansion job shell"><span class="punctuation definition variable job shell">%</span><span class="variable other readwrite shell">rax</span></span></span>
  <span class="meta function-call shell"><span class="variable function shell">401025:</span></span><span class="meta function-call arguments shell">       48 31 ff                xor    <span class="meta group expansion job shell"><span class="punctuation definition variable job shell">%</span><span class="variable other readwrite shell">rdi</span></span>,<span class="meta group expansion job shell"><span class="punctuation definition variable job shell">%</span><span class="variable other readwrite shell">rdi</span></span></span>
  <span class="meta function-call shell"><span class="variable function shell">401028:</span></span><span class="meta function-call arguments shell">       0f 05                   syscall</span>
</span></code></pre>
<p><em>Espetacular, não?</em></p>
<h3 id="tá-mas-e-os-compiladores">👉🏽 Tá, mas e os compiladores?</h3>
<p>Os compiladores entram justamente na categoria de programas de mais alto nível que convertem para o assembly da arquitetura em questão ou diretamente para código de máquina.</p>
<p>Por exemplo, este simples programa escrito em C:</p>
<pre><code class="sourceCode language-c"><span class="source c"><span class="meta preprocessor include c"><span class="keyword control import include c">#include</span> <span class="string quoted other lt-gt include c"><span class="punctuation definition string begin c">&lt;</span>stdio.h<span class="punctuation definition string end c">&gt;</span></span>
</span>
<span class="storage type c">int</span> <span class="meta function c"><span class="entity name function c">main</span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function parameters c"><span class="meta group c"><span class="punctuation section group end c">)</span></span></span><span class="meta function c"> </span><span class="meta function c"><span class="meta block c"><span class="punctuation section block begin c">{</span></span></span><span class="meta function c"><span class="meta block c">
    <span class="meta function-call c"><span class="support function C99 c">printf</span><span class="meta group c"><span class="punctuation section group begin c">(</span></span></span><span class="meta function-call c"><span class="meta group c"><span class="string quoted double c"><span class="punctuation definition string begin c">&quot;</span>Hello, World!<span class="constant character escape c">\n</span><span class="punctuation definition string end c">&quot;</span></span></span></span><span class="meta function-call c"><span class="meta group c"><span class="punctuation section group end c">)</span></span></span><span class="punctuation terminator c">;</span>
    <span class="keyword control c">return</span> <span class="constant numeric c">0</span><span class="punctuation terminator c">;</span>
</span></span><span class="meta function c"><span class="meta block c"><span class="punctuation section block end c">}</span></span></span>
</span></code></pre>
<p>Pode ser compilado para código de máquina utilizando o compilador <code>gcc</code>:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> gcc<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>o</span> hello hello.c </span>
<span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> ./hello</span>

<span class="meta function-call shell"><span class="variable function shell">Hello,</span></span><span class="meta function-call arguments shell"> World!</span>
</span></code></pre>
<blockquote>
<p>É muito comum também compiladores converterem para uma representação intermediária (IR) antes de gerar o código de máquina, como é o caso do próprio gcc, LLVM, dentre outros.</p>
</blockquote>
<h3 id="e-os-interpretadores">👉🏽 E os interpretadores?</h3>
<p>A distinção e similaridade entre compiladores e interpretadores não é um senso bastante comum, embora algumas pessoas entendam que interpretador é um tipo de compilador.</p>
<p>Indo pelo sentido prático, podemos dizer que o compilador <em>compila</em> para instrução de máquina. Enquanto que o interpretador vai lendo linha por linha do código fonte e executando.</p>
<p>Interpretadores modernos possuem um processo interno de compilação em tempo real, chamado <strong>just-in-time</strong>, ou <em>JIT</em>, o que pode inclusive caracterizar interpretadores também no rol de compiladores.</p>
<p>Independente da definição correta ou não de compiladores/interpretadores, uma coisa que devemos ter em mente é que estão acontecendo diversas transformações em camadas até chegar ao código de máquina.</p>
<p>Nesse processo de transformação, acontecem análises e otimizações que vão afetar drasticamente a performance do programa.</p>
<h3 id="frontend-vs-backend">👉🏽 Frontend vs Backend</h3>
<p>Você pensava que a briga front vs back existia apenas na web, pois não? No mundo dos compiladores também!</p>
<blockquote>
<p>To brincando, gente. Não tem briga nenhuma não</p>
</blockquote>
<p><strong>Frontend</strong> é a etapa que faz a leitura do código fonte e gera uma árvore sintática. Esta árvore, como o próprio nome diz, segue uma estrutura de dados muito comum na computação, o que permite a análise de programas seguindo o conjunto de regras definido na gramática.</p>
<p>Basicamente, o frontend faz a análise léxica (gerando tokens válidos da especificação), e em seguida a análise sintática (parsing dos tokens), gerando a árvore sintática abstrata, ou <strong>AST</strong>.</p>
<p>Com a AST, o frontend pode ainda realizar análise semântica e até mesmo gerar um código intermediário (IR), se for o caso.</p>
<p>Já no <strong>Backend</strong> consiste na etapa de, a partir de uma AST ou IR, aplicar otimizações, análise estática (também chamada de <em>ahead-of-time compilation</em>, ou <strong>AOT</strong>), compilação em tempo de execução (JIT) e por fim a geração de assembly ou código de máquina.</p>
<p>Resumindo, então, alguns tipos de assemblers e compiladores:</p>
<ol>
<li>Assemblers</li>
</ol>
<ul>
<li>
<p>NASM</p>
</li>
<li>
<p>GNU as</p>
</li>
</ul>
<ol start="2">
<li>Frontend</li>
</ol>
<ul>
<li>
<p>Clang (para LLVM)</p>
</li>
<li>
<p>GCC</p>
</li>
<li>
<p>javac</p>
</li>
</ul>
<ol start="3">
<li>Backend</li>
</ol>
<ul>
<li>
<p>LLC/LLI (para LLVM)</p>
</li>
<li>
<p>GCC</p>
</li>
<li>
<p>JVM</p>
</li>
</ul>
<h3 id="okay-mas-e-a-rinha">👉🏽 Okay mas e a rinha</h3>
<p>Na rinha, foi disponibilizado um frontend para a especificação da linguagem, em formato de <a href="https://crates.io/crates/rinha">Rust crate</a>.</p>
<p>Bastando ter o Rust instalado, adicionamos a crate e, através do comando <code>rinha</code>, temos uma representação JSON da AST:</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> examples/hello.rinha</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">print</span></span><span class="meta function-call arguments shell">(<span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Hello, world<span class="punctuation definition string end shell">&quot;</span></span></span><span class="meta function-call shell"></span><span class="meta post-cmd shell">)</span>

<span class="comment line number-sign shell"><span class="punctuation definition comment begin shell">#</span></span><span class="comment line number-sign shell"> run frontend</span><span class="comment line number-sign shell">
</span><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> rinha<span class="variable parameter option shell"><span class="punctuation definition parameter shell"> -</span>p</span> examples/hello.rinha</span>

<span class="punctuation definition compound braces begin shell">{</span>
  <span class="meta function-call shell"><span class="variable function shell"><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>name<span class="punctuation definition string end shell">&quot;</span></span>:</span></span><span class="meta function-call arguments shell"> <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>examples/hello.rinha<span class="punctuation definition string end shell">&quot;</span></span>,</span>
  <span class="meta function-call shell"><span class="variable function shell"><span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>expression<span class="punctuation definition string end shell">&quot;</span></span>:</span></span><span class="meta function-call arguments shell"> <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>
    <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>kind<span class="punctuation definition string end shell">&quot;</span></span>: <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Print<span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation separator shell">,</span>
    <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>value<span class="punctuation definition string end shell">&quot;</span></span>: <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>
      <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>kind<span class="punctuation definition string end shell">&quot;</span></span>: <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Str<span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation separator shell">,</span>
      <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>value<span class="punctuation definition string end shell">&quot;</span></span>: <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>Hello, world<span class="punctuation definition string end shell">&quot;</span></span><span class="punctuation separator shell">,</span>
      <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>location<span class="punctuation definition string end shell">&quot;</span></span>: <span class="meta group expansion brace shell"><span class="punctuation section expansion brace begin shell">{</span>
        <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>start<span class="punctuation definition string end shell">&quot;</span></span>: 6<span class="punctuation separator shell">,</span>
        <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>end<span class="punctuation definition string end shell">&quot;</span></span>: 20<span class="punctuation separator shell">,</span>
        <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>filename<span class="punctuation definition string end shell">&quot;</span></span>: <span class="string quoted double shell"><span class="punctuation definition string begin shell">&quot;</span>examples/hello.rinha<span class="punctuation definition string end shell">&quot;</span></span>
      <span class="punctuation section expansion brace end shell">}</span></span>
...........
</span></span></span></span></code></pre>
<p>O desafio? Escrever um compilador/interpretador para este AST. <em>Simples assim.</em></p>
<hr />
<h2 id="patropi-e-o-trampolim">Patropi e o trampolim</h2>
<p>Minha submissão escrita em Ruby foi batizada de <strong>Patropi</strong> (<em>idk either</em>). Optei por fazer um interpretador no formato <em>tree-walking interpreter</em>, que basicamente vai caminhando por cada nó da AST e executando.</p>
<p>Como não sou especialista em compiladores e otimizações, pra mim foi o caminho mais sensato naquele momento.</p>
<p>Um exemplo de código muito simples em Ruby, para interpretar o simples <code>print("Hello world")</code>:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="meta function ruby"><span class="keyword control def ruby">def</span></span><span class="meta function ruby"> <span class="entity name function ruby">evaluate</span></span><span class="meta function parameters ruby"><span class="punctuation definition group begin ruby">(</span></span><span class="meta function parameters ruby"><span class="variable parameter ruby">term</span></span><span class="meta function parameters ruby"><span class="punctuation definition group end ruby">)</span></span>
  <span class="keyword control ruby">case</span> term
  <span class="keyword control ruby">in</span> <span class="punctuation section scope ruby">{</span> <span class="constant other symbol ruby">kind<span class="punctuation definition constant ruby">:</span></span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>Str<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation separator ruby">,</span> <span class="constant other symbol ruby">value<span class="punctuation definition constant ruby">:</span></span> value <span class="punctuation section scope ruby">}</span><span class="punctuation terminator statement ruby">;</span> value<span class="punctuation accessor ruby">.</span><span class="support function builtin ruby">to_s</span>
  <span class="keyword control ruby">in</span> <span class="punctuation section scope ruby">{</span> <span class="constant other symbol ruby">kind<span class="punctuation definition constant ruby">:</span></span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>Print<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation separator ruby">,</span> <span class="constant other symbol ruby">value<span class="punctuation definition constant ruby">:</span></span> next_term <span class="punctuation section scope ruby">}</span><span class="punctuation terminator statement ruby">;</span> <span class="support function builtin ruby">puts</span> evaluate<span class="punctuation definition group begin ruby">(</span>next_term<span class="punctuation definition group end ruby">)</span>
  <span class="keyword control ruby">else</span> <span class="keyword other special-method ruby">raise</span> <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>Unknown term: <span class="source ruby embedded source"><span class="punctuation section embedded ruby">#{</span>term<span class="punctuation section embedded ruby">}</span></span><span class="punctuation definition string end ruby">&quot;</span></span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>
</span></code></pre>
<p>Note que o método <code>evaluate</code> é nosso ponto focal. Ele recebe um termo (nó da AST) e tenta buscar por um match específico. Caso dê match com uma <code>String</code> literal, retorna o valor. Mas se der match com um nó <code>Print</code>, chama o <code>evaluate</code> recursivamente.</p>
<h3 id="recursão">👉🏽 Recursão</h3>
<p><strong>Recursão</strong> é o caminho mais intuitivo para manipular uma árvore na computação. Quase todo compilador é feito inicialmente de forma recursiva na manipulação da árvore justamente porque é intuitivo.</p>
<blockquote>
<p>Enquanto há nó para percorrer, vou chamar minha função novamente, até chegar no fim do galho</p>
</blockquote>
<p>Não vou entrar muito nos detalhes dos trade-offs da recursão, mas se quiser se aprofundar nisto, sugiro a leitura do artigo que escrevi sobre <a href="https://leandronsp.com/articles/entendendo-fundamentos-de-recursao-2ap4">fundamentos de recursão</a>.</p>
<p>Com isto em mente, e sabendo que o pessoal na rinha iria executar alguns programas que exigem muito da memória stack, decidi experimentar uma estratégia não muito ortodoxa e que funciona como alternativa à recursão quando otimizações de recursão de cauda não são possíveis ou são muito limitadas.</p>
<p>A esta estratégia (que também explico com detalhes no artigo apontado), chamamos de <strong>Trampoline</strong>, ou <em>trampolim</em>.</p>
<h3 id="trampolim-para-o-resgate">👉🏽 Trampolim para o resgate</h3>
<p>Basicamente, ao invés de chamar a função recursivamente, eu devolvo uma estrutura chamada "continuation", passando o controle para um loop fora da função.</p>
<p>Este loop imperativo toma a decisão de executar uma closure com o valor passado na continuation ou se vai para o próximo nó da árvore. A cada iteração do loop, por não haver chamada recursiva, não há acúmulo na stack frame, portanto diminui drasticamente a chance de acontecer <strong>stack buffer overflow</strong>, ou seja, praticamente não há chance de estouro de pilha.</p>
<p>Aqui segue uma imagem com a arquitetura do <a href="https://github.com/leandronsp/patropi">Patropi</a>:</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jsbup3brs6qdax53p4sy.png" alt="arquitetura do patropi" /></p>
<blockquote>
<p>Para mais detalhes de código, basta seguir o link do <a href="https://github.com/leandronsp/patropi">repositório no Github</a></p>
</blockquote>
<h3 id="and-the-oscar-goes-to...">👉🏽 And the Oscar goes to...</h3>
<p>O <a href="https://github.com/aripiprazole/rinha-de-compiler/blob/main/TESTS.md">ranking oficial</a> está divulgado no repositório da rinha, e em primeiro lugar ficou uma solução escrita em Golang de tree-walking interpreter. Achei incrível, here we "Go" again :P</p>
<p>Minha solução em Ruby, o Patropi, das 190 submissões, ficou entre as 68 que rodaram, amargando a 65ª posição.</p>
<p>Apesar de ter sido divertido implementar o trampolim, Patropi não soube lidar muito bem com Tuplas e falhou em diversos testes...</p>
<hr />
<h2 id="fila-duplamente-terminada-em-go">Fila duplamente terminada em Go</h2>
<p>Neste intervalo de estudos, aproveitei também para contribuir para um projeto de <a href="https://github.com/kelvins/algorithms-and-data-structures">algoritmos e estruturas de dados</a> no Github. A ideia do repositório é muito boa, basicamente ali tem dezenas de algoritmos que podem ser implementados por qualquer pessoa em diversas linguagens. Basta contribuir :)</p>
<p>Aproveitei a deixa para submeter <a href="https://github.com/kelvins/algorithms-and-data-structures/pulls?q=is%3Apr+author%3Aleandronsp+is%3Aclosed">alguns algoritmos e estruturas de dados</a> em Rust, Go e Ruby. Mas queria destacar uma fila duplamente terminada (double-ended queue, ou <strong>deque</strong>) que <a href="https://github.com/kelvins/algorithms-and-data-structures/pull/211">fiz em Go</a>.</p>
<p><strong>Deque</strong> é uma estrutura de dados de fila que permite adicionar ou remover elementos em qualquer um dos lados.</p>
<p>Por exemplo, uma pilha permite adicionar e remover em apenas um lado (LIFO). Em uma fila, adicionamos a um lado e removemos do outro (FIFO).</p>
<p>A versatilidade da deque permite na média um acesso em tempo constante em ambos os lados (início da fila ou fim), tanto para adição (push) ou remoção (pop).</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cutdsqnv54nvvvehskxo.png" alt="deque" /></p>
<p>Um caso prático de deque seria no histórico de um navegador web, por exemplo. Como o armazenamento no navegador é limitado, o histórico precisa ter um limite de tamanho. Portanto adicionar e remover em ambas extremidades com o mesmo custo passa a ser uma vantagem neste cenário.</p>
<p>Em Go, poderíamos implementar em baby-steps da seguinte forma. Primeiro, definimos a type struct que terá um slice de inteiros:</p>
<pre><code class="sourceCode language-go"><span class="source go"><span class="keyword control go">package</span> main

<span class="meta import go"><span class="meta import go"><span class="keyword control import go">import</span> </span><span class="string quoted double go"><span class="punctuation definition string begin go">&quot;</span>fmt<span class="punctuation definition string end go">&quot;</span></span></span>

<span class="meta struct go"><span class="storage type go">type</span> <span class="entity name struct go">Deque</span> <span class="storage type go">struct</span> <span class="meta block go"><span class="punctuation definition block begin go">{</span>
	<span class="variable other member go">Store</span> <span class="meta brackets go"><span class="punctuation definition brackets begin go">[</span><span class="punctuation definition brackets end go">]</span></span><span class="storage type go">int</span>
</span><span class="meta block go"><span class="punctuation definition block end go">}</span></span></span>
</span></code></pre>
<p>Agora, temos que implementar as operações do lado direito, <code>Rpush</code> e <code>RPop</code>:</p>
<pre><code class="sourceCode language-go"><span class="source go"><span class="meta function declaration go"><span class="storage type go">func</span> <span class="meta group go"><span class="punctuation definition group begin go">(</span><span class="variable parameter receiver go">deque</span> <span class="keyword operator go">*</span>Deque<span class="punctuation definition group end go">)</span></span> <span class="entity name function go">RPush</span></span><span class="meta function parameters go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span><span class="meta function parameters go"></span><span class="meta function parameters go"><span class="meta group go"><span class="variable parameter go">element</span></span></span><span class="meta function parameters go"><span class="meta group go"> <span class="storage type go">int</span></span></span><span class="meta function parameters go"></span><span class="meta function parameters go"><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span><span class="meta function go"> </span><span class="meta function go"><span class="meta block go"><span class="punctuation definition block begin go">{</span></span></span><span class="meta function go"><span class="meta block go">
	deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span> <span class="keyword operator assignment go">=</span> <span class="meta function-call go"><span class="support function builtin go">append</span><span class="meta function-call go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span></span><span class="meta function-call go"><span class="meta group go">deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span><span class="punctuation separator go">,</span> element</span><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span>
</span></span><span class="meta function go"><span class="meta block go"><span class="punctuation definition block end go">}</span></span></span>

<span class="meta function declaration go"><span class="storage type go">func</span> <span class="meta group go"><span class="punctuation definition group begin go">(</span><span class="variable parameter receiver go">deque</span> <span class="keyword operator go">*</span>Deque<span class="punctuation definition group end go">)</span></span> <span class="entity name function go">RPop</span></span><span class="meta function parameters go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span><span class="meta function parameters go"></span><span class="meta function parameters go"></span><span class="meta function parameters go"><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span><span class="meta function go"> </span><span class="meta function return-type go"><span class="keyword operator go">*</span><span class="storage type go">int</span> </span><span class="meta function go"><span class="meta block go"><span class="punctuation definition block begin go">{</span></span></span><span class="meta function go"><span class="meta block go">
	<span class="keyword control go">if</span> <span class="meta function-call go"><span class="support function builtin go">len</span><span class="meta function-call go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span></span><span class="meta function-call go"><span class="meta group go">deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span></span><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span> <span class="keyword operator go">==</span> <span class="constant numeric integer decimal go">0</span> <span class="meta block go"><span class="punctuation definition block begin go">{</span>
		<span class="keyword control go">return</span> <span class="constant language go">nil</span>
	<span class="punctuation definition block end go">}</span></span>

	<span class="meta initialization short go"><span class="variable other go">element</span> <span class="keyword operator initialize go">:=</span></span> deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span><span class="meta brackets go"><span class="punctuation definition brackets begin go">[</span><span class="meta function-call go"><span class="support function builtin go">len</span><span class="meta function-call go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span></span><span class="meta function-call go"><span class="meta group go">deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span></span><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span><span class="keyword operator go">-</span><span class="constant numeric integer decimal go">1</span><span class="punctuation definition brackets end go">]</span></span>
	deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span> <span class="keyword operator assignment go">=</span> deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span><span class="meta brackets go"><span class="punctuation definition brackets begin go">[</span><span class="punctuation separator go">:</span><span class="meta function-call go"><span class="support function builtin go">len</span><span class="meta function-call go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span></span><span class="meta function-call go"><span class="meta group go">deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span></span><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span><span class="keyword operator go">-</span><span class="constant numeric integer decimal go">1</span><span class="punctuation definition brackets end go">]</span></span>

	<span class="keyword control go">return</span> <span class="keyword operator go">&amp;</span>element
</span></span><span class="meta function go"><span class="meta block go"><span class="punctuation definition block end go">}</span></span></span>
</span></code></pre>
<ul>
<li>
<p>RPush: utiliza o built-in <code>append</code> no lado direito, que é uma operação constante</p>
</li>
<li>
<p>RPop: manipula o slice, trabalhando apenas com os índices</p>
</li>
</ul>
<p>Para terminar, fazer o mesmo do lado esquerdo:</p>
<pre><code class="sourceCode language-go"><span class="source go"><span class="meta function declaration go"><span class="storage type go">func</span> <span class="meta group go"><span class="punctuation definition group begin go">(</span><span class="variable parameter receiver go">deque</span> <span class="keyword operator go">*</span>Deque<span class="punctuation definition group end go">)</span></span> <span class="entity name function go">LPush</span></span><span class="meta function parameters go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span><span class="meta function parameters go"></span><span class="meta function parameters go"><span class="meta group go"><span class="variable parameter go">element</span></span></span><span class="meta function parameters go"><span class="meta group go"> <span class="storage type go">int</span></span></span><span class="meta function parameters go"></span><span class="meta function parameters go"><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span><span class="meta function go"> </span><span class="meta function go"><span class="meta block go"><span class="punctuation definition block begin go">{</span></span></span><span class="meta function go"><span class="meta block go">
	deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span> <span class="keyword operator assignment go">=</span> <span class="meta function-call go"><span class="support function builtin go">append</span><span class="meta function-call go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span></span><span class="meta function-call go"><span class="meta group go"><span class="meta brackets go"><span class="punctuation definition brackets begin go">[</span><span class="punctuation definition brackets end go">]</span></span><span class="storage type go">int</span>{element}<span class="punctuation separator go">,</span> deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span>...</span><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span>
</span></span><span class="meta function go"><span class="meta block go"><span class="punctuation definition block end go">}</span></span></span>

<span class="meta function declaration go"><span class="storage type go">func</span> <span class="meta group go"><span class="punctuation definition group begin go">(</span><span class="variable parameter receiver go">deque</span> <span class="keyword operator go">*</span>Deque<span class="punctuation definition group end go">)</span></span> <span class="entity name function go">LPop</span></span><span class="meta function parameters go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span><span class="meta function parameters go"></span><span class="meta function parameters go"></span><span class="meta function parameters go"><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span><span class="meta function go"> </span><span class="meta function return-type go"><span class="keyword operator go">*</span><span class="storage type go">int</span> </span><span class="meta function go"><span class="meta block go"><span class="punctuation definition block begin go">{</span></span></span><span class="meta function go"><span class="meta block go">
	<span class="keyword control go">if</span> <span class="meta function-call go"><span class="support function builtin go">len</span><span class="meta function-call go"><span class="meta group go"><span class="punctuation definition group begin go">(</span></span></span></span><span class="meta function-call go"><span class="meta group go">deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span></span><span class="meta group go"><span class="punctuation definition group end go">)</span></span></span> <span class="keyword operator go">==</span> <span class="constant numeric integer decimal go">0</span> <span class="meta block go"><span class="punctuation definition block begin go">{</span>
		<span class="keyword control go">return</span> <span class="constant language go">nil</span>
	<span class="punctuation definition block end go">}</span></span>

	<span class="meta initialization short go"><span class="variable other go">element</span> <span class="keyword operator initialize go">:=</span></span> deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span><span class="meta brackets go"><span class="punctuation definition brackets begin go">[</span><span class="constant numeric integer decimal go">0</span><span class="punctuation definition brackets end go">]</span></span>
	deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span> <span class="keyword operator assignment go">=</span> deque<span class="punctuation accessor go">.</span><span class="variable other member go">Store</span><span class="meta brackets go"><span class="punctuation definition brackets begin go">[</span><span class="constant numeric integer decimal go">1</span><span class="punctuation separator go">:</span><span class="punctuation definition brackets end go">]</span></span>

	<span class="keyword control go">return</span> <span class="keyword operator go">&amp;</span>element
</span></span><span class="meta function go"><span class="meta block go"><span class="punctuation definition block end go">}</span></span></span>
</span></code></pre>
<p>No lado esquerdo, as operações passam a ter um custo linear, mas na média, por ser uma fila duplamente terminada, esse custo é amortizado caindo pra constante.</p>
<hr />
<h2 id="thread-pool-no-adelnor">Thread pool no Adelnor</h2>
<p>Pra finalizar, meu projetinho xodó do momento, o <a href="https://github.com/leandronsp/adelnor">leandronsp/adelnor</a>, precisava de uns ajustes importantes. Cada request HTTP era servido dentro da thread principal, não havia qualquer tipo de concorrência, e portanto o server não conseguia entregar muitos requests.</p>
<p>Resolvi implementar uma thread pool modesta <a href="https://github.com/leandronsp/adelnor/pull/1">submetendo este PR</a>, em live na Twitch e também no <a href="https://www.youtube.com/watch?v=a8Ccxt0UGqA">Youtube</a>.</p>
<pre><code class="sourceCode language-bash"><span class="source shell bash"><span class="meta function-call shell"><span class="variable function shell">$</span></span><span class="meta function-call arguments shell"> gem install adelnor</span>
</span></code></pre><pre><code class="sourceCode language-ruby"><span class="source ruby"><span class="meta require ruby"><span class="keyword other special-method ruby">require</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>adelnor<span class="punctuation definition string end ruby">&#39;</span></span></span>

app <span class="keyword operator assignment ruby">=</span> <span class="keyword operator arithmetic ruby">-</span><span class="keyword operator comparison ruby">&gt;</span> <span class="punctuation definition group begin ruby">(</span>env<span class="punctuation definition group end ruby">)</span> <span class="keyword control start-block ruby">do</span>
  <span class="punctuation section array ruby">[</span><span class="constant numeric ruby">200</span><span class="punctuation separator ruby">,</span> <span class="punctuation section scope ruby">{</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>Content-Type<span class="punctuation definition string end ruby">&#39;</span></span> <span class="punctuation separator key-value ruby">=&gt;</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>text/html<span class="punctuation definition string end ruby">&#39;</span></span> <span class="punctuation section scope ruby">}</span><span class="punctuation separator ruby">,</span> <span class="string quoted single ruby"><span class="punctuation definition string begin ruby">&#39;</span>Hello world!<span class="punctuation definition string end ruby">&#39;</span></span><span class="punctuation section array ruby">]</span>
<span class="keyword control ruby">end</span>

<span class="support class ruby">Adelnor</span><span class="punctuation accessor ruby">::</span><span class="support class ruby">Server</span><span class="punctuation accessor ruby">.</span>run app<span class="punctuation separator ruby">,</span> <span class="constant numeric ruby">3000</span><span class="punctuation separator ruby">,</span> <span class="constant other symbol ruby">thread_pool<span class="punctuation definition constant ruby">:</span></span> <span class="constant numeric ruby">5</span>
</span></code></pre>
<p>Foi um processo interessante. Após subir o server com uma pool de 5 threads, a app conseguiu entregar 4x mais requests do que na versão single-threaded.</p>
<p>E caso queira aprender mais sobre threads em Ruby, recomendo muito <a href="https://workingwithruby.com/wwrt/intro">este guia</a>.</p>
<hr />
<h2 id="conclusão">Conclusão</h2>
<p>É isto que tive experimentando ultimamente. No momento, estou fazendo algumas melhorias no Adelnor, nomeadamente implementar modelo de atores com Ractors, mas vou entrar em detalhes disto num blogpost à parte.</p>
<hr />
<h2 id="referências">Referências</h2>
<p><a href="https://computersciencewiki.org/index.php/Architecture_of_the_central_processing_unit_(CPU)">CPU architecture</a>
<a href="http://sparksandflames.com/files/x86InstructionChart.html">x86 instructions chart</a>
<a href="https://craftinginterpreters.com/">Crafting Interpreters</a>
<a href="https://github.com/aripiprazole/rinha-de-compiler">Rinha de compiladores</a>
<a href="https://github.com/reu/rinha-compiladores">reu/rinha-compiladores</a>
<a href="https://github.com/leandronsp/patropi">leandronsp/patropi</a>
<a href="https://leandronsp.com/articles/entendendo-fundamentos-de-recursao-2ap4">Fundamentos de Recursão</a>
<a href="https://en.wikipedia.org/wiki/Double-ended_queue">Double-ended queue</a>
<a href="https://workingwithruby.com/">workingwithruby.com</a>
<a href="https://github.com/leandronsp/adelnor">leandronsp/adelnor</a></p>
]]></description>
<pubDate>2023-10-17</pubDate>
</item>
<item>
<title>Rust, Go, Rinha e I/O</title>
<link>https://leandronsp.com/articles/rust-go-rinha-e-io-39o2.html</link>
<guid>https://leandronsp.com/articles/rust-go-rinha-e-io-39o2.html</guid>
<description><![CDATA[<p>Este artigo é o início de um formato diferente de conteúdo que quero experimentar, um apanhado (ou resumão, ou dump, como queiram chamar) de coisas que tenho visto nos últimos dias, com uma pegada informal e um leve toque de didática como de costume.</p>
<hr />
<h2 id="rust-go-e-background-jobs">Rust, Go e background jobs</h2>
<p>Em 2022 eu estava aprendendo Rust.</p>
<p>Numa bela 4a feira de chuva, fiz um tweet dizendo que iria tentar implementar uma lista duplamente ligada em Rust. Minutos depois, fiz <a href="https://twitter.com/leandronsp/status/1578154810612027392?s=20">outro tweet</a> dizendo que iria desistir e ver Netflix.</p>
<p>Então desisti do Rust.</p>
<p>Recentemente em 2023 comecei uma saga para aprender Golang. Como a sintaxe me incomodou um pouco, talvez pela verbosidade dos <code>if err != nil</code> a dar com telha, decidi continuar kkk</p>
<p>Mas adicionando uma complexidade nisto tudo: voltar a aprender Rust junto com Go.</p>
<blockquote>
<p>As vezes eu meto dessas, em 2015/16 decidi aprender Elixir e redes neurais artificiais tudo junto, e saiu o <a href="https://github.com/leandronsp/morphine">morphine</a></p>
</blockquote>
<p>Nesta segunda tentativa com Rust, bateu um sentimento, confesso. <em>Sentimento bom</em>, no caso.</p>
<p>Com isto, passei a praticar em Rust e Go (e porque não Ruby) estruturas de dados simples que já estou habituado a implementar (pq pratico muito): filas, pilhas, listas ligadas, mutexes etc etc. E claro, programação em sockets como de praxe.</p>
<p>Desta massarocada toda saiu <a href="https://gist.github.com/leandronsp/31ad977cf1a68f5d7b3d13d46ab34a8c">um UNIX server</a> em Go, <a href="https://gist.github.com/leandronsp/b72b2b21d2ef8f8f3ccb2ab8af422c2b">outro</a> em Rust, pelo que indo de milho em milho, saiu um background job em <a href="https://gist.github.com/leandronsp/c0a7daaa27f75dd65d9fa803db8489ad">ambas</a> distintas <a href="https://gist.github.com/leandronsp/90f0e97ef28586c5c996835b311f9ac5">linguagens</a>.</p>
<p>Cheguei a um <a href="https://gist.github.com/leandronsp/90f0e97ef28586c5c996835b311f9ac5">background job em Rust</a> muito overkill, vale a pena dar uma olhada, lá abordo lista duplamente ligada, fila duplamente terminada, rpoplpush, blocking queue, DLQ, retries, threads etc.</p>
<p>Tudo isso implementado com os smart pointers em Rust, para resolver problemas inerentes (ok, não são bem problemas) a ownership e borrow checker.</p>
<blockquote>
<p>Em breve vou escrever sobre meu aprendizado em Rust com artigos mais detalhados, preciso arrumar um tempo na minha vida, salvar pinguins na Antártida é mais urgente que isso</p>
</blockquote>
<p>Mas se você acha que é  ̶m̶u̶i̶t̶o̶ ̶m̶a̶i̶s̶ ̶e̶l̶e̶g̶a̶n̶t̶e̶ mais fácil ver um código Ruby, <a href="https://github.com/leandronsp/fun/blob/master/dsa/queues/ruby/background_job.rb">aqui neste arquivo</a> no meu projeto <a href="https://github.com/leandronsp/fun">leandronsp/fun</a> também abordo um background job em Ruby com os mesmos conceitos aplicados ali em Rust e Go.</p>
<hr />
<h2 id="rinha-de-backend">Rinha de backend</h2>
<p>Entre Julho e Agosto aconteceu na famosa #bolhaDev no Twitter uma competição chamada <a href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3">rinha de backend</a>, criada pelo <a href="https://twitter.com/zanfranceschi">Zan do Twitter</a> e nosso arauto do sarcasmo <a href="https://twitter.com/wilcorrea">Will Correa</a>.</p>
<p>A ideia era que as pessoas participantes trouxessem a implementação de uma API definida nas regras da competição.</p>
<p>O desafio tinha como requisito uma arquitetura composta por basicamente <strong>um NGINX</strong> fazendo load balancing para <strong>2 API's</strong> mandando dados para <strong>um banco de dados</strong>, tudo rodando em containers.</p>
<blockquote>
<p>Se você quer saber mais sobre containers e Docker, dê uma olhadinha <a href="https://leandronsp.com/articles/kubernetes-101-part-i-the-fundamentals-23a1">nesta série de artigos</a> que escrevi centuries ago</p>
</blockquote>
<p>Pra deixar mais desafiador ainda, havia uma restrição obrigatória de recursos onde o total de containers não podia exceder o limite de 1.5 CPU's e 3GB de memória.</p>
<p>Em uma data previamente estipulada, todas as submissões seriam submetidas a test de stress (violento, diga-se de passagem) através de uma ferramenta chamada <a href="https://gatling.io/docs/gatling/tutorials/installation/">Gatling</a>.</p>
<p>Foi uma iniciativa muito bacana pois trouxe à luz pessoas que pouco interagiam por ali e que eram muito talentosas. Deu pra aprender e trocar muita figurinha durante os dias pré-submissão.</p>
<p>Outra coisa boa foi que o <a href="https://twitter.com/coproduto">polvo lá do Twitter</a> organizou um <a href="https://www.meetup.com/import-beer/events/295288014/">encontro presencial</a> que iria transmitir a live da rinha, onde deu pra conhecer mais pessoas interessadas no tema.</p>
<h3 id="plain-ruby-chespirito-e-roda">Plain Ruby, Chespirito e Roda</h3>
<p>Decidi participar submetendo uma versão em Ruby (sem Rails) tentando colocar em prova um web framework muito simples que criei chamado <a href="https://github.com/leandronsp/chespirito">Chespirito</a>.</p>
<p>Infelizmente, durante os testes no meu ambiente local não consegui grandes números com o Chespirito e acabei indo de <a href="https://github.com/jeremyevans/roda">Roda</a>, que por acaso é o pior framework que já vi, pois sou muito hater de DSL's em situações onde não precisamos delas.</p>
<p>Um exemplo da tamanha verbosidade que atingimos com este framework:</p>
<pre><code class="sourceCode language-ruby"><span class="source ruby">r<span class="punctuation accessor ruby">.</span>get <span class="keyword control start-block ruby">do</span>              <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> GET
</span>  r<span class="punctuation accessor ruby">.</span>on <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>a<span class="punctuation definition string end ruby">&quot;</span></span> <span class="keyword control start-block ruby">do</span>         <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> GET /a branch
</span>    r<span class="punctuation accessor ruby">.</span>on <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>b<span class="punctuation definition string end ruby">&quot;</span></span> <span class="keyword control start-block ruby">do</span>       <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> GET /a/b branch
</span>      r<span class="punctuation accessor ruby">.</span>is <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>c<span class="punctuation definition string end ruby">&quot;</span></span> <span class="keyword control start-block ruby">do</span> <span class="keyword control ruby">end</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> GET /a/b/c request
</span>      r<span class="punctuation accessor ruby">.</span>is <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>d<span class="punctuation definition string end ruby">&quot;</span></span> <span class="keyword control start-block ruby">do</span> <span class="keyword control ruby">end</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> GET /a/b/d request
</span>    <span class="keyword control ruby">end</span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>

r<span class="punctuation accessor ruby">.</span>post <span class="keyword control start-block ruby">do</span>             <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> POST
</span>  r<span class="punctuation accessor ruby">.</span>on <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>a<span class="punctuation definition string end ruby">&quot;</span></span> <span class="keyword control start-block ruby">do</span>         <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> POST /a branch
</span>    r<span class="punctuation accessor ruby">.</span>on <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>b<span class="punctuation definition string end ruby">&quot;</span></span> <span class="keyword control start-block ruby">do</span>       <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> POST /a/b branch
</span>      r<span class="punctuation accessor ruby">.</span>is <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>c<span class="punctuation definition string end ruby">&quot;</span></span> <span class="keyword control start-block ruby">do</span> <span class="keyword control ruby">end</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> POST /a/b/c request
</span>      r<span class="punctuation accessor ruby">.</span>is <span class="string quoted double ruby"><span class="punctuation definition string begin ruby">&quot;</span>e<span class="punctuation definition string end ruby">&quot;</span></span> <span class="keyword control start-block ruby">do</span> <span class="keyword control ruby">end</span> <span class="comment line number-sign ruby"><span class="punctuation definition comment ruby">#</span> POST /a/b/e request
</span>    <span class="keyword control ruby">end</span>
  <span class="keyword control ruby">end</span>
<span class="keyword control ruby">end</span>
</span></code></pre>
<blockquote>
<p>Escolhi Roda pq me disseram que era rápido. Não comparei com Sinatra, apenas confiei</p>
</blockquote>
<p>Submeti então minha versão naquela terça-feira sombria às 22h42 com Roda e <a href="https://github.com/puma/puma">Puma</a>, pois meu ambiente não me ajudou a tirar bons números com I/O assíncrono no <a href="https://github.com/socketry/falcon">Falcon</a>.</p>
<blockquote>
<p>Logo mais chegamos no ponto do meu ambiente</p>
</blockquote>
<p>Portanto, minha submissão ficou assim:</p>
<ul>
<li>
<p>Multi-threading com Puma, com uma modesta pool de threads 0:5, que é o default no Puma, e sem CPU workers</p>
</li>
<li>
<p><a href="https://github.com/mperham/connection_pool">Pool</a> de 5 conexões com o PostgreSQL</p>
</li>
<li>
<p>PostgreSQL nos defaults (100 max_connections)</p>
</li>
<li>
<p>NGINX nos defaults com um ligeiro aumento para 1024 worker_connections</p>
</li>
</ul>
<p>No docker-compose submetido, dividi os recursos da seguinte forma:</p>
<ul>
<li>
<p>0.4 CPU | 1GB mem para as API's (x2)</p>
</li>
<li>
<p>0.6 CPU | 0.8GB mem para o PostgreSQL</p>
</li>
<li>
<p>0.1 CPU | 0.2GB mem para o NGINX</p>
</li>
</ul>
<p>Depois vou explicar como que distribuindo melhor os recursos e <a href="https://twitter.com/leandronsp/status/1699568664859603184">diminuindo os números do NGINX e PostgreSQL</a> fez meu troughput melhorar, mas só consegui fazer isto dias depois da rinha ter terminado.</p>
<h3 id="o-grande-momento-the-big-moment">O grande momento, the big moment</h3>
<p>Minha submissão Ruby ficou em 20º lugar num ranking de 51 submissões funcionais (quase 100 foram submetidas mas muitas não rodaram lá na máquina dos caras), com um total de 24k inserts no banco de dados após o teste de stress com carga dobrada.</p>
<p>Não achei um número ruim mas eu tinha uma noção de que o desafio era muito I/O-bound, coisa que expliquei <a href="https://twitter.com/leandronsp/status/1695470712738210189">nesta thread</a> do Twitter e também <a href="https://twitter.com/leandronsp/status/1699568664859603184">nesta outra thread</a> dias depois.</p>
<blockquote>
<p>Se I/O-bound ou CPU-bound são termos esquisitos pra você, sugiro dar um passo atrás e aprender os fundamentos de concorrência em sistemas operacionais, <a href="https://web101.leandronsp.com/">neste super guia</a> que escrevi anos atrás sobre o funcionamento da Web</p>
</blockquote>
<h3 id="resumo-da-ópera">Resumo da ópera</h3>
<p>O resumo disto é que depois com mais calma, consegui ajustar melhor meu ambiente de desenvolvimento. Abandonei o <a href="https://github.com/abiosoft/colima">colima</a> que tava com performance horrível no meu macOS e abracei o <a href="https://orbstack.dev/">orbstack</a>. So far, so good.</p>
<p>Com isto, pude rodar de forma mais assertiva com restrição de recursos os testes de stress no meu ambiente. Tem a ver com a virtualização do orbstack ser mais performática etc e tal.</p>
<h3 id="a-new-hope-for-plain-ruby">A new hope for plain Ruby</h3>
<p>Isto abriu portas para que eu voltasse a experimentar Falcon e meu filho Chespirito. Guess what, os números começaram a bater a famigerada dupla Roda/Puma.</p>
<p>Aproveitei também para utilizar o <a href="https://www.portainer.io/">Portainer</a> para visualizar métricas de CPU e memória dos containers no Docker.</p>
<p>Não apenas isto, também mexi nos meus limites no docker-compose, ficando assim, delegando mais recursos para o PostgreSQL que, tadinho, era o que mais apanhava (parabéns guerreiro, tmj):</p>
<ul>
<li>
<p>0.2 CPU | 0.3GB para API's (x2)</p>
</li>
<li>
<p>1 CPU | 1.7GB para PostgreSQL (sim, nessa arquitetura, db sempre gasta mais CPU e memória)</p>
</li>
<li>
<p>0.1 CPU | 0.1GB para o NGINX</p>
</li>
</ul>
<p>Diferente de muitas submissões na rinha, fiquei entre poucos que optaram por não utilizar qualquer estratégia de cache ou batch insert de forma assíncrona.</p>
<p>Meu intuito sempre foi experimentar algo que acredito muito e que trago nos projetos em que trabalho: não abusar de cache ou estratégia assíncrona onde não precisa. Cache ajuda mas pode trazer muitos desafios e encarecer custos no fim das contas.</p>
<blockquote>
<p>Claro que, para a rinha, tudo era válido. Foi um amontoado positivo de diferentes soluções e troca de conhecimento</p>
</blockquote>
<p>Mas como sou chato com custos, eu sempre vou pra solução mais simples possível e que causa menos entropia possível, <em>até que se prove o contrário</em>.</p>
<p>Cenário então fica assim:</p>
<ul>
<li>
<p>I/O não-bloqueante com Falcon, atendendo requests com multitasking cooperativo (Fibers)</p>
</li>
<li>
<p>Chespirito, que não faz grande coisa a não ser rotear mensagens do Rack para a lógica devida, mas com código muito mais explícito e sem aquela DSL  ̶h̶o̶r̶r̶o̶r̶o̶s̶a̶ estranha do Roda</p>
</li>
</ul>
<p>Os números melhoraram, indo pra 35k. Not bad. Mas eu tinha uma leve suspeita de que algo errado ainda estava com minha solução. Por ser um desafio muito I/O-heavy, os requests ficavam pouco no Ruby, então eu tinha que melhorar a latência do PostgreSQL.</p>
<p>Foi aí que inverti a lógica.</p>
<h3 id="fechando-a-torneira">Fechando a torneira</h3>
<p><a href="https://twitter.com/leandronsp/status/1699568664859603184">Nesta thread</a> compartilhei recentemente como consegui atingir 46k inserts, mas em suma eu basicamente percebi que muitos requests à espera (Gatling judia) fazem aumentar a latência e consequentemente ciclo de CPU para fazer gestão das filas nos sockets.</p>
<p>Minha ideia então foi não deixar muito requests à espera, mesmo porque as queries no db são muito rápidas (remember kids, índices corretos salvam vidas).</p>
<p>Para atingir isto, resolvi diminuir o PostgreSQL para 30 max_connections e NGINX para 256 worker_connections (podia até ser 128 ou 64 tbh). Na API, como são duas, deixei uma pool de 15 conexões, pois o PostgreSQL neste caso iria até 30.</p>
<p>O resultado trouxe um troughput melhor e garantiu 46k inserts.</p>
<blockquote>
<p>Em breve vou escrever um artigo mais detalhado sobre esta saga do Ruby na rinha</p>
</blockquote>
<h3 id="e-o-bash">E o Bash?</h3>
<p>It turns out que também fiz <a href="https://github.com/leandronsp/rinha-backend-bash">outra versão</a> e submeti, escrita em Bash script, apenas for fun mesmo. Foi produto de um tweet inocente que fiz, o pessoal não perdoou e fez o tweet viralizar, pelo que me senti obrigado e implementar a API em Bash.</p>
<p>Na verdade, como eu já venho de uma saga ensinando fundamentos de computação <a href="https://leandronsp.com/articles/building-a-web-server-in-bash-part-i-sockets-2n8b">nos meus artigos</a> usando Bash, foi tranquilo fazer uma versão minimamente aceitável com mkfifo e netcat.</p>
<p>Submeti sem grandes pretensões, rodei o teste local apenas uma vez e deu um monte de erro, pensei "freak it vou mandar mesmo assim" e foi.</p>
<p>Para meu deleite, a solução em Bash ficou dentre as 51 funcionais da rinha, conquistando a tão sonhada 51ª posição, com um total de 17 inserts.</p>
<blockquote>
<p>Isso mesmo, 17 inserts</p>
</blockquote>
<p>Twitter não perdoa e então começaram a me chamar de "carinha do Bash", "ministro dos scripts Bash" e etc, mas gente <strong>EU NAO PROGRAMO EM BASH</strong>. Sou apenas um dev scriptzero que usa Bash as vezes pra facilitar minha vida e automatizar o que não preciso, mas longe de "manjar" de Bash kkkkk</p>
<hr />
<h2 id="io-assíncrono-e-live-coding-do-leandro">I/O assíncrono e live coding do Leandro</h2>
<p>Com o término da rinha, foi gerado um buzz muito alto em torno de I/O, principalmente o famoso <strong>I/O assíncrono</strong>, ou então como alguns costumam referenciar por <strong>I/O não-bloqueante</strong>.</p>
<p>Em breve escrevo artigos mais formais e detalhados sobre I/O não-bloqueante, mas recentemente fui de <a href="https://www.youtube.com/watch?v=w1ejKYlxhaA">live mesmo</a>, com um formato mais de "explicação", indo lá atrás de forma resumida nos aspectos de concorrência em sistemas operacionais até chegar em I/O não-bloqueante.</p>
<p>Na <a href="https://www.youtube.com/watch?v=w1ejKYlxhaA">live</a> eu trouxe exemplos em Ruby, Bash e C. Se você quer dar uma espreitada no que aconteceu por lá, <a href="https://www.youtube.com/watch?v=w1ejKYlxhaA">CLIQUE AQUI</a>.</p>
<hr />
<h2 id="thats-all-folks">That's all folks</h2>
<p>É isto, o intuito deste breve artigo foi fazer um apanhado das coisas que tenho olhado recentemente, em um formato mais informal como costumo usar no Twitter.</p>
<p>Espero que o formato possa ser útil, caso contrário irei apenas continuar com aquele formato  ̶c̶h̶a̶t̶o̶ denso e didático.</p>
<p>Claro que não deixarei de escrever os artigos técnicos de costume. E pode ser que eu misture inglês com português e a massarocada toda.</p>
<p>Fiquem ligades.</p>
]]></description>
<pubDate>2023-09-08</pubDate>
</item>
</channel></rss>
