<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ddupard</title>
    <description>The latest articles on DEV Community by ddupard (@ddupard).</description>
    <link>https://dev.to/ddupard</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3949744%2Fab1a1cf3-7a46-4fa9-92d1-8ac9855809d3.png</url>
      <title>DEV Community: ddupard</title>
      <link>https://dev.to/ddupard</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ddupard"/>
    <language>en</language>
    <item>
      <title>Reverse Engineering Undocumented Architectures: Creating Custom Processors</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Sun, 06 Sep 2026 18:21:25 +0000</pubDate>
      <link>https://dev.to/ddupard/reverse-engineering-undocumented-architectures-creating-custom-processors-198e</link>
      <guid>https://dev.to/ddupard/reverse-engineering-undocumented-architectures-creating-custom-processors-198e</guid>
      <description>&lt;p&gt;When facing a binary for which &lt;strong&gt;Ghidra&lt;/strong&gt; lacks the SLEIGH specifications required to disassemble it, you hit a problem that the vast majority of reverse engineers will never encounter.&lt;/p&gt;

&lt;p&gt;Out of an estimated &lt;strong&gt;25,000 reverse engineers&lt;/strong&gt; in the United States, only about &lt;strong&gt;500 (~2%)&lt;/strong&gt; work on this specific domain.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Reality of Undocumented ISAs
&lt;/h3&gt;

&lt;p&gt;A processor without a documented instruction set is &lt;strong&gt;never completely exotic&lt;/strong&gt;. Recreating an Instruction Set Architecture (ISA) from scratch is far too expensive.&lt;/p&gt;

&lt;p&gt;Consequently, almost all undocumented processors are derivatives of major existing families:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base architectures with stripped-down instructions&lt;/li&gt;
&lt;li&gt;Custom instructions added for dedicated workloads&lt;/li&gt;
&lt;li&gt;Scrambled or non-standard opcodes due to the confidentiality of underlying operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To master this niche, hands-on experience is everything. CTFs with custom VMs are a good start, but &lt;strong&gt;nothing beats generating your own custom processors&lt;/strong&gt; and sharpening your tools against custom-built challenges.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Pitfalls of Processor Generation
&lt;/h3&gt;

&lt;p&gt;Building a custom processor generator sounds straightforward, until you run into data extraction issues: &lt;strong&gt;retrieving valid opcode/instruction tables for major architectures&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note on LLMs:&lt;/strong&gt; For ancient 8-bit architectures with reduced instruction sets, LLMs can extract tables flawlessly (see my previous research on dev.to/ddupard). However, as soon as you target modern, heavy ISAs, LLMs break down.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  The Reliable Approach:
&lt;/h4&gt;

&lt;p&gt;The most robust solution consists of extracting, cleaning, and parsing the &lt;code&gt;xxx-dis.c&lt;/code&gt; files (such as &lt;code&gt;arm-dis.c&lt;/code&gt;) directly from &lt;strong&gt;binutils-gdb&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Custom Processor Toolchain
&lt;/h3&gt;

&lt;p&gt;To generate a custom processor, you need a core &lt;strong&gt;&lt;code&gt;(match, mask, instruction)&lt;/code&gt;&lt;/strong&gt; triplet.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example in ARM 32-bit:&lt;/em&gt;&lt;br&gt;
&lt;code&gt;0x04400000&lt;/code&gt; | &lt;code&gt;0x0c500010&lt;/code&gt; | &lt;code&gt;strb%t%c\t%12-15R, %a&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This triplet determines the possible permutations applicable to both opcode and operand bits, as well as the exact search space. Once you possess a clean table, the process becomes a pure pipeline problem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a Transcoding Table:&lt;/strong&gt; Map native instructions to your custom ISA (optionally dropping specific instructions).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transcode the Target Binary:&lt;/strong&gt; Process a standard binary compiled for the native ISA through your map.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inject Custom Instructions:&lt;/strong&gt; Insert new logic while recalculating jump, branch, and call offsets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix Binary Headers:&lt;/strong&gt; Re-align sections (e.g., within ELF structures).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-assemble &amp;amp; Output:&lt;/strong&gt; Regenerate a valid, clean custom binary.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You now have a fully functional custom binary ready for analysis practice.&lt;/p&gt;




&lt;h3&gt;
  
  
  Taking It to the Hardware Level (FPGA Obfuscation)
&lt;/h3&gt;

&lt;p&gt;This software approach also maps directly to hardware logic. You can easily derive a &lt;strong&gt;Verilog file&lt;/strong&gt; from your pipeline to deploy an FPGA dedicated to this new processor.&lt;/p&gt;

&lt;p&gt;If your goal is to make analysis virtually impossible, you can add layers of defense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Two-Layer Encryption:&lt;/strong&gt; One static key combined with one dynamic key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LUT Geometry Alteration:&lt;/strong&gt; Tweak Lookup Table geometry to break standard ASIC/FPGA reversing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redundancy &amp;amp; Voting Systems:&lt;/strong&gt; Implement hardware voting modules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-Tamper Physical Actions:&lt;/strong&gt; Remove JTAG access and blow physical security fuses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By removing hardware debug interfaces, standard chip-attack techniques fail — leaving the analyst with pure, unassisted combinatorial complexity.&lt;/p&gt;




</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>cybersecurity</category>
      <category>security</category>
    </item>
    <item>
      <title>RV32I vs x86_32: How Branching Works Across Architectural Lines</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Sun, 06 Sep 2026 16:11:43 +0000</pubDate>
      <link>https://dev.to/ddupard/rv32i-vs-x8632-how-branching-works-across-architectural-lines-58l3</link>
      <guid>https://dev.to/ddupard/rv32i-vs-x8632-how-branching-works-across-architectural-lines-58l3</guid>
      <description>&lt;h4&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In control flow operations—such as jumps (&lt;code&gt;jmp&lt;/code&gt;), branch instructions, and function calls (&lt;code&gt;call&lt;/code&gt;)—the distinction between CISC and RISC architectures becomes immediately visible.&lt;/p&gt;

&lt;p&gt;In a variable-length CISC architecture like x86, the processor can encode absolute 32-bit addresses directly into jump instructions. Conversely, a fixed-length 32-bit RISC architecture like RISC-V (RV32I) must fit every instruction, including its opcode, target registers, and offset payload, into exactly 4 bytes (32 bits).&lt;/p&gt;

&lt;p&gt;This constraint introduces a fundamental challenge: &lt;strong&gt;How do you execute a long jump or function call to an arbitrary address in a 32-bit memory space when instructions are limited to 32 bits?&lt;/strong&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;How x86_32 Handles Jumps and Calls&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;On x86_32, jumps and calls can encode either relative or absolute 32-bit offsets directly inside the instruction stream.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.intel_syntax noprefix
.section .text
.global _start

_start:
    call 0x12345678    # Call a function located at address 0x12345678
    jmp  0x87654321    # Absolute / Far Jump to 0x87654321

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When assembled and disassembled, x86 produces single multi-byte instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="err"&gt;08049000&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;_start&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="err"&gt;8049000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nf"&gt;e8&lt;/span&gt; &lt;span class="mi"&gt;73&lt;/span&gt; &lt;span class="mi"&gt;66&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;        &lt;span class="nv"&gt;call&lt;/span&gt;   &lt;span class="mi"&gt;12345678&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;_start&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mh"&gt;0x0a2f6678&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="err"&gt;8049005&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nf"&gt;ea&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt; &lt;span class="mi"&gt;43&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt; &lt;span class="mi"&gt;87&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;00&lt;/span&gt;  &lt;span class="nv"&gt;jmp&lt;/span&gt;    &lt;span class="mi"&gt;001&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;87654321&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The x86 architecture seamlessly embeds the full target address or relative offset into 5-byte to 7-byte instruction encodings.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;How RISC-V (RV32I) Handles Long Jumps and Calls&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Because an RV32I instruction cannot exceed 32 bits, a single instruction cannot encode a full 32-bit target address.&lt;/p&gt;

&lt;p&gt;To solve this, RISC-V provides two primary hardware instructions for jumps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;jal&lt;/code&gt; (&lt;strong&gt;Jump and Link&lt;/strong&gt;, J-Type format): Uses a 20-bit immediate field (sign-extended and shifted left by 1 bit), allowing relative jumps within a &lt;strong&gt;±1 MiB range&lt;/strong&gt; around the current program counter (&lt;code&gt;pc&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jalr&lt;/code&gt; (&lt;strong&gt;Jump and Link Register&lt;/strong&gt;, I-Type format): Adds a 12-bit signed immediate offset to a base register.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a jump target exceeds the ±1 MiB reach of a single &lt;code&gt;jal&lt;/code&gt;, the RISC-V assembler converts pseudo-instructions like &lt;code&gt;call&lt;/code&gt; or &lt;code&gt;tail&lt;/code&gt; into a two-instruction pair.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.section .text
.global _start

_start:
    call target_func    # Pseudo-instruction for function call

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;target_func&lt;/code&gt; is located beyond the 1 MiB limit (e.g., at address &lt;code&gt;0x12345678&lt;/code&gt;), the assembler expands &lt;code&gt;call&lt;/code&gt; into the following sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight armasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;00010074&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nf"&gt;_start&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;:&lt;/span&gt;
   &lt;span class="err"&gt;10074:&lt;/span&gt; &lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="mf"&gt;0e7&lt;/span&gt;            &lt;span class="nv"&gt;auipc&lt;/span&gt;  &lt;span class="nv"&gt;ra&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x12345&lt;/span&gt;
   &lt;span class="err"&gt;10078:&lt;/span&gt; &lt;span class="mi"&gt;678&lt;/span&gt;&lt;span class="mf"&gt;0e0&lt;/span&gt;&lt;span class="nv"&gt;e7&lt;/span&gt;            &lt;span class="nv"&gt;jalr&lt;/span&gt;   &lt;span class="nv"&gt;ra&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1656&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;ra&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;   &lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="mi"&gt;1656&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x678&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h4&gt;
  
  
  &lt;strong&gt;Understanding &lt;code&gt;auipc&lt;/code&gt; + `jalr&lt;/strong&gt;`
&lt;/h4&gt;

&lt;p&gt;The combined sequence works through two distinct steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;auipc ra, 0x12345&lt;/code&gt; (&lt;strong&gt;Add Upper Immediate to PC&lt;/strong&gt;): Adds the upper 20 bits shifted left by 12 bits to the current value of the program counter (&lt;code&gt;pc&lt;/code&gt;) and stores the result in register &lt;code&gt;ra&lt;/code&gt; (Return Address).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jalr ra, 1656(ra)&lt;/code&gt; (&lt;strong&gt;Jump and Link Register&lt;/strong&gt;): Adds the remaining sign-extended 12-bit offset (&lt;code&gt;0x678&lt;/code&gt; = 1656) to &lt;code&gt;ra&lt;/code&gt;, saves &lt;code&gt;pc + 4&lt;/code&gt; into &lt;code&gt;ra&lt;/code&gt;, and jumps to the calculated target.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This combination allows RISC-V to execute &lt;strong&gt;PC-relative calls anywhere within a ±2 GiB address space&lt;/strong&gt; using two 32-bit instructions (8 bytes in total).&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;The Sign-Extension Trap on Relocations&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Just like loading constants with &lt;code&gt;lui&lt;/code&gt; + &lt;code&gt;addi&lt;/code&gt;, &lt;code&gt;auipc&lt;/code&gt; + &lt;code&gt;jalr&lt;/code&gt; is vulnerable to sign-extension issues.&lt;/p&gt;

&lt;p&gt;If bit 11 of the 12-bit offset in &lt;code&gt;jalr&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt; (i.e., the offset is negative), &lt;code&gt;jalr&lt;/code&gt; will subtract from the address pre-calculated by &lt;code&gt;auipc&lt;/code&gt;. To prevent incorrect branching, the linker or assembler must automatically compensate by &lt;strong&gt;adding &lt;code&gt;1&lt;/code&gt; to the 20-bit upper immediate&lt;/strong&gt; passed to &lt;code&gt;auipc&lt;/code&gt;.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Architectural Comparison&lt;/strong&gt;
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;CISC (x86_32)&lt;/th&gt;
&lt;th&gt;RISC (RISC-V RV32I)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Max Reach of Single Jump&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full 32-bit address space (4 GiB)&lt;/td&gt;
&lt;td&gt;±1 MiB (&lt;code&gt;jal&lt;/code&gt; relative)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Long Call Sequence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single &lt;code&gt;call&lt;/code&gt; instruction (5 bytes)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;auipc&lt;/code&gt; + &lt;code&gt;jalr&lt;/code&gt; pair (8 bytes total)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relocation Style&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Absolute or PC-relative&lt;/td&gt;
&lt;td&gt;Fully PC-relative (Position Independent Code by design)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware Impact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Variable-length instruction decoding&lt;/td&gt;
&lt;td&gt;Uniform 32-bit pipeline fetching and simplified branching logic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Epilogue&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;While x86 relies on complex decoding hardware to handle multi-byte branch targets inline, RISC-V enforces strict structural simplicity. By coupling &lt;code&gt;auipc&lt;/code&gt; and &lt;code&gt;jalr&lt;/code&gt;, RISC-V achieves fully position-independent control flow across the entire memory space without requiring complex multi-length instruction decoders.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>hardware</category>
    </item>
    <item>
      <title>Reverse Engineering Undocumented Architectures: LLM-Driven Opcode Table Extraction vs. Legacy Tooling Constraints</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Sat, 05 Sep 2026 04:14:12 +0000</pubDate>
      <link>https://dev.to/ddupard/reverse-engineering-undocumented-architectures-llm-driven-opcode-table-extraction-vs-legacy-20kb</link>
      <guid>https://dev.to/ddupard/reverse-engineering-undocumented-architectures-llm-driven-opcode-table-extraction-vs-legacy-20kb</guid>
      <description>&lt;h2&gt;
  
  
  Executive Summary
&lt;/h2&gt;

&lt;p&gt;When building a custom disassembler for an undocumented, legacy, or modified CPU architecture, the primary challenge is not writing the decoding loop, but obtaining a structured, machine-readable &lt;strong&gt;opcode-to-instruction mapping table&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While one might expect to extract these tables from existing reverse-engineering frameworks like Ghidra, doing so is surprisingly difficult. Ghidra’s instruction definitions are deeply integrated into its SLAgh engine and designed for internal P-Code translation rather than data export. Traditional CLI disassemblers (like &lt;code&gt;dis51&lt;/code&gt;) hardcode their mappings directly inside compiled execution logic.&lt;/p&gt;

&lt;p&gt;This article presents an alternative methodology: leveraging a Large Language Model (Gemini) to reconstruct, normalize, and export a complete opcode lookup table into a clean Python structure in minutes, and using it to power a lightweight &lt;strong&gt;linear sweep disassembler&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Core Problem: Why Extracting Opcode Tables from Existing Tools Fails
&lt;/h2&gt;

&lt;p&gt;To build a lightweight, custom disassembler, you need a simple lookup table:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Opcode Byte ──&amp;gt; (Length, Mnemonic, Operand Formatting)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, existing toolchains make retrieving this structured table nearly impossible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ghidra (SLAgh Engine Integration):&lt;/strong&gt;&lt;br&gt;
Ghidra holds extensive architecture data within its &lt;code&gt;.slaspec&lt;/code&gt; files. However, these files are written in SLAgh—a complex domain-specific language designed to compile instruction logic into Ghidra’s internal P-Code representation. Ghidra offers no straightforward API or export utility to extract a flat opcode mapping table from these definitions without parsing SLAgh grammar or running heavy Java context frameworks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dedicated Disassemblers (&lt;code&gt;dis51&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
Standalone tools do not store opcode maps as external data files. The byte decoding, instruction length calculation, and operand formatting are hardcoded directly into C/C++ control-flow logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Datasheets and Specifications:&lt;/strong&gt;&lt;br&gt;
Manufacturer documentation presents opcode tables in fragmented PDF tables, diagrams, and text descriptions, requiring hours of manual, error-prone data entry.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Experimental Protocol &amp;amp; Testing Baseline
&lt;/h2&gt;

&lt;p&gt;To validate our LLM-based table generation against a ground-truth baseline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Image Generation (&lt;code&gt;test1_8051.rom&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
A target program (&lt;code&gt;test1.c&lt;/code&gt;) containing mixed 8/16/32-bit arithmetic, conditional branches, &lt;code&gt;switch&lt;/code&gt; jump tables, and embedded literal strings (&lt;code&gt;"TARGET_STRING"&lt;/code&gt;) was compiled using &lt;strong&gt;SDCC&lt;/strong&gt; (&lt;code&gt;-mmcs51&lt;/code&gt;). The result was converted into a raw binary ROM image containing both code (&lt;code&gt;crt0&lt;/code&gt;, math helpers) and read-only data blocks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Black-Box Experiment:&lt;/strong&gt;&lt;br&gt;
We treated &lt;code&gt;test1_8051.rom&lt;/code&gt; as an unknown architecture binary to evaluate how different disassembly strategies perform when full control-flow entry points are not pre-configured.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  3. Disassembly Behavior &amp;amp; Tooling Benchmark
&lt;/h2&gt;

&lt;p&gt;Evaluating the binary across different disassembly methods highlighted distinct architectural limits:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool / Approach&lt;/th&gt;
&lt;th&gt;Method for Opcode Mapping&lt;/th&gt;
&lt;th&gt;Disassembly Coverage&lt;/th&gt;
&lt;th&gt;Main Limitation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ghidra&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Requires SLAgh (&lt;code&gt;.slaspec&lt;/code&gt;) definitions&lt;/td&gt;
&lt;td&gt;N/A (Requires setup)&lt;/td&gt;
&lt;td&gt;Cannot export raw opcode maps; requires full framework setup.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;dis51&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hardcoded C logic&lt;/td&gt;
&lt;td&gt;Incomplete (Stalls)&lt;/td&gt;
&lt;td&gt;Stops at &lt;code&gt;RET&lt;/code&gt; / helper functions / inline strings (&lt;code&gt;"TARGET_STRING"&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Python (Our Approach)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Gemini LLM Reconstruction&lt;/strong&gt;&lt;br&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;100% (Linear Sweep)&lt;/strong&gt;&lt;br&gt;
&lt;/td&gt;
&lt;td&gt;Ignores control flow; requires manual identification of data vs. code.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Why &lt;code&gt;dis51&lt;/code&gt; Fails on Raw Binaries
&lt;/h3&gt;

&lt;p&gt;Because &lt;code&gt;dis51&lt;/code&gt; uses recursive traversal (tracing execution paths from &lt;code&gt;0x0000&lt;/code&gt;), it relies on detecting jump/call boundaries. When it hits library return instructions (&lt;code&gt;RET&lt;/code&gt;), runtime math helpers, or inline data blocks (such as &lt;code&gt;"TARGET_STRING"&lt;/code&gt; at &lt;code&gt;0x02CA&lt;/code&gt;), tracing halts. Unreached code sections are prematurely categorized as raw bytes (&lt;code&gt;.DB&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Pipeline: LLM-Driven Opcode Extraction &amp;amp; Linear Sweep
&lt;/h2&gt;

&lt;p&gt;By shifting the role of the LLM from "disassembling code" to &lt;strong&gt;"extracting and structuring the opcode table"&lt;/strong&gt;, we decouple data extraction from execution logic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Raw Specification / PDF / Prompt ] ──&amp;gt; [ Gemini LLM ] ──&amp;gt; [ Python INSTRUCTION_TABLE ]
                                                                       │
[ Raw Binary Image (.rom) ] ─────────────&amp;gt; [ Linear Sweep Engine ] ────┴─&amp;gt; [ Assembly Output ]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1: Opcode Normalization via Gemini
&lt;/h3&gt;

&lt;p&gt;Instead of parsing Ghidra’s SLAgh files or writing complex XML parsers, we prompt Gemini directly to extract, deduplicate, and structure the architecture's instruction set from raw reference data.&lt;/p&gt;

&lt;p&gt;We used the following structured prompt to enforce a strict, semicolon-delimited CSV-like format:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Prompt sent to Gemini:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;"Generate an output file where each line follows this exact structure:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;1) The number of bytes in the instruction (e.g., &lt;code&gt;3&lt;/code&gt;)&lt;/em&gt;&lt;br&gt;
&lt;em&gt;2) The instruction opcode bytes in hexadecimal (e.g., &lt;code&gt;75 81 18&lt;/code&gt;)&lt;/em&gt;&lt;br&gt;
&lt;em&gt;3) The disassembled assembly instruction (e.g., &lt;code&gt;MOV SP, 18h&lt;/code&gt;)&lt;/em&gt;&lt;br&gt;
&lt;em&gt;4) A column with the generic instruction pattern (e.g., &lt;code&gt;MOV register, value8&lt;/code&gt;)&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Use a semicolon (&lt;code&gt;;&lt;/code&gt;) as the field delimiter.&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Example 1:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;02 30 00&lt;/code&gt; &lt;em&gt;must become:&lt;/em&gt; &lt;code&gt;3;02 30 00;LJMP 0030;LJMP addr16&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Deduplication rule:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;If two consecutive lines share the exact same value in the last column and that pattern does **not&lt;/em&gt;* contain the word &lt;code&gt;register&lt;/code&gt;, omit the second line from the generated file.*&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Example 2:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;If the following two entries are generated:&lt;/em&gt;&lt;br&gt;
&lt;code&gt;3;02 30 00;LJMP 0030;LJMP addr16&lt;/code&gt;&lt;br&gt;
&lt;code&gt;3;02 30 01;LJMP 0130;LJMP addr16&lt;/code&gt;&lt;br&gt;
&lt;em&gt;Do **not&lt;/em&gt;* include the second line in the final output."*&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The raw output generated by the LLM is then directly converted into a lightweight, standalone Python lookup dictionary used by our disassembler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# LLM-Generated Mapping Table (parsed from structured output)
&lt;/span&gt;&lt;span class="n"&gt;INSTRUCTION_TABLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NOP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="mh"&gt;0x02&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LJMP&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;addr16&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="mh"&gt;0x12&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LCALL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;addr16&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="mh"&gt;0x75&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MOV&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;register, value8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="mh"&gt;0x22&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="mh"&gt;0x54&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ANL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A, #data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;# ... fully populated and deduplicated by Gemini
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Linear Sweep Disassembly Engine
&lt;/h3&gt;

&lt;p&gt;A minimal Python script sweeps through the binary sequentially:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Reads the lead byte as an opcode index.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fetches instruction length, mnemonic, and operand rules from &lt;code&gt;INSTRUCTION_TABLE&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Formats operands and advances the offset pointer linearly.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Step 3: Comparative Analysis &amp;amp; Family Identification (Differential Mapping)
&lt;/h3&gt;

&lt;p&gt;The true power of generating a standardized, machine-readable opcode table via LLM lies in &lt;strong&gt;cross-architecture correlation&lt;/strong&gt;. Once a partial or candidate opcode table is constructed from an unknown binary, it can be diffed against a reference database of known ISA (Instruction Set Architecture) tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
[ Candidate / Partial Table ] ──┐
├──&amp;gt; [ LLM / Script Diff Engine ] ──&amp;gt; 1. Identify Core Architecture
[ Known ISA Database (8051, ] ──┘                                     2. Infer Missing Opcodes
Z80, RISC-V, PIC...)                                                3. Highlight Custom Extensions

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This differential analysis enables three critical reverse-engineering breakthroughs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Architecture Classification (Fingerprinting):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Even heavily customized microcontrollers usually retain structural heritage from legacy families (e.g., MCS-51, Z80, or AVR). By comparing opcode frequency and instruction layout, the LLM can instantly recognize the underlying base architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inference of Unobserved Opcodes:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If an unknown binary only utilizes 60% of the processor's opcode map, comparing the partial table against known variants allows us to predict the meaning and operand structure of the remaining 40% unobserved instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Isolating Proprietary Opcodes:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Any opcode that deviates from standard reference tables immediately highlights hardware-specific customizations, undocumented vendor extensions, or custom security mechanisms.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  5. Results &amp;amp; Conclusion
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ghidra and legacy disassemblers lock away opcode knowledge:&lt;/strong&gt; They are built to execute disassembly, not to expose their internal mapping tables as clean, reusable datasets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LLMs solve the table generation bottleneck:&lt;/strong&gt; Gemini bridges the gap between raw, unstructured datasheets and structured Python lookup tables in minutes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Linear sweeping guarantees full coverage:&lt;/strong&gt; Sequential sweeping ignores control-flow traps (&lt;code&gt;RET&lt;/code&gt;, jump tables, inline constants), ensuring every byte of an undocumented binary is decoded and exposed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The need for a global opcode database:&lt;/strong&gt; To analyze truly undocumented binaries at scale, the community must build a normalized, open-access database of opcode maps across all known architectures (from vintage CPUs to modern proprietary MCUs). By running automated differential matching between an unclassified binary's opcode distribution and this reference database, reverse engineers can instantly determine which processor family an unknown chip is derived from and accelerate hardware fingerprinting.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>llm</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>CrackMe Level 6: part 2</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Fri, 04 Sep 2026 15:43:43 +0000</pubDate>
      <link>https://dev.to/ddupard/crackme-level-6-part-2-54k3</link>
      <guid>https://dev.to/ddupard/crackme-level-6-part-2-54k3</guid>
      <description>&lt;h3&gt;
  
  
  1. Introduction
&lt;/h3&gt;

&lt;p&gt;In the previous article, we began studying a level 6 CrackMe and quickly reached the Serial verification routine based on the Name.&lt;/p&gt;

&lt;p&gt;Here is this routine below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   0x401510:   pusha                         ; Save all general-purpose registers

   ; -------------------------------------------------------------------------
   ; PHASE 1: BASE64 DECODING AND SIZE CHECK
   ; -------------------------------------------------------------------------
   0x401511:   mov    ebx,DWORD PTR [esp+0x2c]; ebx = Pointer to Serial (passed as parameter)
   0x401515:   mov    esi,0x404200           ; esi = Destination buffer for decoded Serial
   0x40151a:   push   ebx                    ; Argument 2: Serial string
   0x40151b:   push   esi                    ; Argument 1: Output buffer
   0x40151c:   call   0x401633               ; CALL: Custom Base64 decoder
   0x401521:   cmp    eax,0x10               ; Is the decoded buffer exactly 16 bytes (128 bits)?
   0x401524:   jne    0x40162f               ; No -&amp;gt; Direct failure (Jump to failure)

   ; -------------------------------------------------------------------------
   ; PHASE 2: CHECK AND PREPARATION OF 64-BIT INTEGERS (S1 AND S2)
   ; -------------------------------------------------------------------------
   0x40152a:   lea    edi,[esi+0x10]         ; edi = Pointer to second memory block (0x404210)

   ; Verification of the First 64-bit Number: S1 = [esi] (0x404200)
   0x40152d:   mov    eax,DWORD PTR [esi]    ; eax = Low 32 bits of S1
   0x40152f:   mov    edx,DWORD PTR [esi+0x4]; edx = High 32 bits of S1
   0x401532:   test   edx,edx                ; Is S1 zero?
   0x401534:   jne    0x40153e
   0x401536:   test   eax,eax
   0x401538:   je     0x40162f               ; If S1 == 0 -&amp;gt; Failure

   ; Comparison of S1 with Modulus M (stored at 0x40403c)
   0x40153e:   sub    eax,DWORD PTR ds:0x40403c ; S1 - Modulus (low part)
   0x401544:   sbb    edx,DWORD PTR ds:0x404040 ; S1 - Modulus (high part with borrow)
   0x40154a:   jae    0x40162f               ; If S1 &amp;gt;= Modulus -&amp;gt; Failure (S1 must be &amp;lt; M)

   ; Copy and Verification of the Second 64-bit Number: S2 = [esi+0x8] (0x404208)
   0x401550:   mov    eax,DWORD PTR [esi+0x8]; eax = Low 32 bits of S2
   0x401553:   mov    edx,DWORD PTR [esi+0xc]; edx = High 32 bits of S2
   0x401556:   mov    DWORD PTR [edi],eax    ; Copy S2 to edi
   0x401558:   mov    DWORD PTR [edi+0x4],edx
   0x40155b:   test   edx,edx                ; Is S2 zero?
   0x40155d:   jne    0x401567
   0x40155f:   test   eax,eax
   0x401561:   je     0x40162f               ; If S2 == 0 -&amp;gt; Failure

   ; Comparison of S2 with Modulus M
   0x401567:   sub    eax,DWORD PTR ds:0x40403c
   0x40156d:   sbb    edx,DWORD PTR ds:0x404040
   0x401573:   jae    0x40162f               ; If S2 &amp;gt;= Modulus -&amp;gt; Failure

   ; Initialize structures for big integer calculations
   0x401579:   mov    ebx,0x4041e0           ; ebx = Intermediate result structure
   0x40157e:   and    DWORD PTR [esi+0x8],0x0; Zero out structure ends (Padding)
   0x401582:   and    DWORD PTR [edi+0x8],0x0

   ; -------------------------------------------------------------------------
   ; PHASE 3: CRYPTOGRAPHIC CALCULATIONS (MODULAR EXPONENTIATION)
   ; -------------------------------------------------------------------------
   ; Preparation for first modular calculation: C1 = (S2 ^ e) mod M
   0x401586:   push   0x404220               ; Destination for result
   0x40158b:   push   0x404020               ; Pointer to Public Exponent (e)
   0x401590:   push   edi                    ; Operand: S2
   0x401591:   call   0x4020e0               ; CALL: BigInt Math (Modular Exponentiation)

   ; Preparation for second modular calculation: C2 = (S1 ^ e) mod M
   0x401596:   push   ebx                    ; Destination
   0x401597:   push   0x404000               ; Pointer to Modulus / Parameters
   0x40159c:   push   esi                    ; Operand: S1
   0x40159d:   call   0x4020e0               ; CALL: BigInt Math (Modular Exponentiation)

   ; Combine intermediate results
   0x4015a2:   push   ebx
   0x4015a3:   push   0x404220
   0x4015a8:   call   0x401e30               ; CALL: Multiplication / Modular transformation
   0x4015ad:   mov    eax,DWORD PTR [ebx]
   0x4015af:   test   eax,eax                ; Check result validity
   0x4015b1:   je     0x40162f

   0x4015b3:   mov    edi,0x404240
   0x4015b8:   push   edi
   0x4015b9:   push   ebx
   0x4015ba:   call   0x402087               ; CALL: BigInt Normalization / Reduction
   0x4015bf:   push   0x404250
   0x4015c4:   push   edi
   0x4015c5:   call   0x4021cd               ; CALL: Extract final 64-bit value

   ; Modular adjustment of S1
   0x4015ca:   mov    eax,DWORD PTR [esi]
   0x4015cc:   mov    edx,DWORD PTR [esi+0x4]
   0x4015cf:   sub    eax,DWORD PTR ds:0x404250
   0x4015d5:   sbb    edx,DWORD PTR ds:0x404254
   0x4015db:   jae    0x4015e9
   0x4015dd:   add    eax,DWORD PTR ds:0x40403c
   0x4015e3:   adc    edx,DWORD PTR ds:0x404040

   ; -------------------------------------------------------------------------
   ; PHASE 4: NAME HASHING AND FINAL COMBINATION (CHECK)
   ; -------------------------------------------------------------------------
   0x4015e9:   mov    esi,DWORD PTR [esp+0x24]; esi = Length of Name
   0x4015ed:   mov    ecx,DWORD PTR [esp+0x28]; ecx = Pointer to Name string
   0x4015f1:   push   esi
   0x4015f2:   push   ecx
   0x4015f3:   push   edi                     ; Buffer receiving the Hash
   0x4015f4:   call   0x401700                ; CALL: Name Hashing Function (H_Name)

   ; Extract calculated footprint from Name
   0x4015f9:   mov    ebx,DWORD PTR [edi]     ; ebx = Hash_Name (low 32 bits)
   0x4015fb:   mov    ebp,DWORD PTR [edi+0x4] ; ebp = Hash_Name (high 32 bits)
   0x4015fe:   xor    ebx,DWORD PTR [edi+0x8] ; XOR masking with derived components
   0x401601:   xor    ebp,DWORD PTR [edi+0xc]

   ; Adjustment / Reduction of the final mask with the Modulus
   0x401604:   sub    ebx,DWORD PTR ds:0x40403c
   0x40160a:   sbb    ebp,DWORD PTR ds:0x404040
   0x401610:   jae    0x40161e
   0x401612:   add    ebx,DWORD PTR ds:0x40403c
   0x401618:   adc    ebp,DWORD PTR ds:0x404040

   ; FINAL CHECK: Comparison (Calculated Result XOR Name Mask) == 0 ?
   0x40161e:   xor    eax,ebx                 ; Difference on low part
   0x401620:   xor    edx,ebp                 ; Difference on high part
   0x401622:   or     eax,edx                 ; Combine both parts (EAX = 0 if exact match)
   0x401624:   jne    0x40162f                ; If EAX != 0 -&amp;gt; Bad Serial!

   ; -------------------------------------------------------------------------
   ; PHASE 5: SUCCESS OR FAILURE
   ; -------------------------------------------------------------------------
   0x401626:   inc    eax                     ; EAX = 1 (Success)
   0x401627:   mov    DWORD PTR [esp+0x1c],eax; Save return code in stack frame
   0x40162b:   popa                           ; Restore registers
   0x40162c:   ret    0xc                     ; Clean up stack and return (Validated)

   0x40162f:   xor    eax,eax                 ; EAX = 0 (Failure)
   0x401631:   jmp    0x401627                ; Exit to failure

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While the first part of the disassembly was fairly ordinary, this one confirms why this crackme is rated level 6.&lt;/p&gt;


&lt;h3&gt;
  
  
  2. Algorithm Analysis
&lt;/h3&gt;

&lt;p&gt;A detailed analysis of the code reveals a structured and advanced algorithmic architecture:&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;
  
  
  A. Custom / Base64 Decoding (&lt;code&gt;0x00401633&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;The secondary function called at the very beginning (&lt;code&gt;0x0040151c: call 0x401633&lt;/code&gt;) is a custom implementation of a &lt;strong&gt;Base64 decoder&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Custom Alphabet (&lt;code&gt;0x404048&lt;/code&gt;):&lt;/strong&gt; The code iterates through an alphabet stored at address &lt;code&gt;0x404048&lt;/code&gt; (&lt;code&gt;mov bl, 0x3f&lt;/code&gt; 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
   from 63 down to 0) to map the characters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Padding Handling (&lt;code&gt;0x00401687&lt;/code&gt; and &lt;code&gt;0x004016a4&lt;/code&gt;):&lt;/strong&gt; It looks for the &lt;code&gt;=&lt;/code&gt; character (&lt;code&gt;0x3D&lt;/code&gt;) and increments &lt;code&gt;dh&lt;/code&gt; to manage the final padding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Byte Reconstitution (&lt;code&gt;0x004016c3&lt;/code&gt; - &lt;code&gt;0x004016e0&lt;/code&gt;):&lt;/strong&gt; Packets of 4 6-bit characters (24 bits) are reassembled and extracted as 3 binary bytes using rotations &lt;code&gt;rol eax, 0x10&lt;/code&gt;, &lt;code&gt;0x8&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Size Verification (&lt;code&gt;0x00401521&lt;/code&gt;):&lt;/strong&gt; The decoded result must be &lt;strong&gt;exactly 16 bytes&lt;/strong&gt; (&lt;code&gt;0x10&lt;/code&gt;, or 128 bits). This is why the entered Serial had to consist of 24 Base64 characters (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;24&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;6&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;144&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;&amp;nbsp;bits&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 , or 18 raw bytes with padding).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;
  
  
  B. Large-Scale Arithmetic Validation (Asymmetric Cryptography / RSA)
&lt;/h4&gt;

&lt;p&gt;Once the 16 bytes are split into two 64-bit blocks (&lt;code&gt;[esi]&lt;/code&gt; and &lt;code&gt;[esi+0x8]&lt;/code&gt;), the program switches to a big-integer arithmetic library:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bounds Checks (&lt;code&gt;0x0040153e&lt;/code&gt; and &lt;code&gt;0x00401567&lt;/code&gt;):&lt;/strong&gt; The 64-bit integers are compared (via &lt;code&gt;sub&lt;/code&gt; / &lt;code&gt;sbb&lt;/code&gt; / &lt;code&gt;jae&lt;/code&gt;) against a modulus or maximum value stored at &lt;code&gt;0x40403c&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular Operations (&lt;code&gt;0x00401591&lt;/code&gt; and &lt;code&gt;0x0040159d&lt;/code&gt;: &lt;code&gt;call 0x4020e0&lt;/code&gt;):&lt;/strong&gt; These functions serve as wrappers for &lt;strong&gt;modular exponentiation&lt;/strong&gt; (RSA or Diffie-Hellman type) or elliptic curve calculations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Name&lt;/code&gt;-related Comparison (&lt;code&gt;0x004015f4: call 0x401700&lt;/code&gt;):&lt;/strong&gt; The username is hashed or derived to serve as a comparison key/mask (&lt;code&gt;xor ebx, [edi+0x8]&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;
  
  
  C. Summary
&lt;/h4&gt;

&lt;p&gt;The mechanism boils down to three main phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Phase 1 (Format):&lt;/strong&gt; Conversion of the 24-character Serial (Base64) into a 16-byte (128-bit) binary buffer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 2 (Mathematics):&lt;/strong&gt; Processing the 128 bits as two 64-bit integers subjected to modular exponentiation equations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 3 (Name/Key Binding):&lt;/strong&gt; A fingerprint derived from the &lt;code&gt;Name&lt;/code&gt; is injected via a XOR mask to verify final equality (&lt;code&gt;or eax, edx&lt;/code&gt; 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 &lt;code&gt;jne 0x40162f&lt;/code&gt; / failure).&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  3. How to Break This CrackMe?
&lt;/h3&gt;

&lt;p&gt;To break a CrackMe based on modular arithmetic (RSA or 64-bit modular exponentiation type), two main approaches are available: &lt;strong&gt;mathematical inversion (Keygenning)&lt;/strong&gt; or &lt;strong&gt;binary modification (Patching)&lt;/strong&gt;. We covered binary modification in the previous article; in this article, we will look at Keygenning.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;
  
  
  A. Mathematical Engine of the CrackMe
&lt;/h4&gt;

&lt;p&gt;The core of the verification follows this logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. &lt;strong&gt;Extraction:&lt;/strong&gt; The Serial (24 Base64 chars) is decoded into a &lt;strong&gt;128-bit&lt;/strong&gt; block divided into two 64-bit integers: 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/li&gt;
&lt;li&gt;2. &lt;strong&gt;Modular Computation:&lt;/strong&gt; The program executes a modular exponentiation:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;or&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;ModularExponentiation&lt;/span&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;3. &lt;strong&gt;Binding with the Name:&lt;/strong&gt; The result 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is combined via a XOR mask with a fingerprint of the &lt;code&gt;Name&lt;/code&gt; 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;Name&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 :&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⊕&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;Name&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop"&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mclose mtight"&gt;?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;4. &lt;strong&gt;Validation:&lt;/strong&gt; At address &lt;code&gt;0x00401622&lt;/code&gt;, the register EAX holds the result of the equality check. If EAX = 0, the program jumps to failure (&lt;code&gt;jne 0x40162f&lt;/code&gt;). If there is equality, EAX is incremented to 1 (&lt;code&gt;inc eax&lt;/code&gt;), validating the serial.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Keygenning (Mathematical Resolution)
&lt;/h4&gt;

&lt;p&gt;This type of function &lt;strong&gt;can be inverted to generate a valid Serial for any Name&lt;/strong&gt;, provided you extract the cryptographic parameters from the binary.&lt;/p&gt;

&lt;p&gt;Unlike a pure hash (such as MD5 or SHA-256) which destroys information, the core of this function relies on &lt;strong&gt;asymmetric cryptography (modular exponentiation / RSA type)&lt;/strong&gt;. The mathematical relationship is designed to be a trapdoor function: difficult to invert without the private key, but perfectly reversible if one manages to break the modulus 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;u&gt;a. Why and how is this function inverted?&lt;/u&gt;
&lt;/h5&gt;

&lt;p&gt;The verification process executes the following public operation:&lt;br&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;To build a key generator (&lt;em&gt;Keygen&lt;/em&gt;) for a given &lt;code&gt;Name&lt;/code&gt;, the process involves inverting this equation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. &lt;strong&gt;Computing the Name Hash:&lt;/strong&gt; You pass the &lt;code&gt;Name&lt;/code&gt; through the hashing function &lt;code&gt;0x00401700&lt;/code&gt; to obtain the fingerprint 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord text mtight"&gt;&lt;span class="mord mtight"&gt;Name&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
.&lt;/li&gt;
&lt;li&gt;2. &lt;strong&gt;Reconstructing the Target:&lt;/strong&gt; By analyzing the XOR operations and modular adjustments in Phase 4, you deduce the target value 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 that the calculation must yield.&lt;/li&gt;
&lt;li&gt;3. &lt;strong&gt;Calculating the Private Key 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You retrieve the modulus 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (at address &lt;code&gt;0x40403c&lt;/code&gt;) and the public exponent 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (at address &lt;code&gt;0x404020&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Since 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is a 64-bit integer (i.e., 8 bytes, visible with the 32-bit &lt;code&gt;sub&lt;/code&gt;/&lt;code&gt;sbb&lt;/code&gt; instructions), &lt;strong&gt;its factorization into two prime numbers 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is instantaneous&lt;/strong&gt; on a modern computer (using a tool like &lt;em&gt;PARI/GP&lt;/em&gt;, &lt;em&gt;SageMath&lt;/em&gt;, or &lt;em&gt;Factordb&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Once 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 are known, you calculate Euler's totient function 
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ϕ&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;q&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;
, and then the private exponent 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 such that:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;≡&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ϕ&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;4. &lt;strong&gt;Calculating 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
:&lt;/strong&gt; You recover the original value 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 by applying the private key:&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;5. &lt;strong&gt;Final Encoding:&lt;/strong&gt; You assemble the 16-byte block 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 and pass it through the Base64 encoder using the custom alphabet located at address &lt;code&gt;0x404048&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;u&gt;b. The Invertibility Condition&lt;/u&gt;
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;If the modulus 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is 64-bit:&lt;/strong&gt; The system is &lt;strong&gt;fully invertible&lt;/strong&gt; in a fraction of a second, because 64-bit factorization cannot resist modern algorithms (such as MPQS or GNFS).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 had been 2048-bit:&lt;/strong&gt; The function would be mathematically invertible in theory, but practically unbreakable without knowing the private key 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, making brute-force Keygen creation impossible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h5&gt;
  
  
  &lt;u&gt;c. Summary&lt;/u&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;We can recover the Serial from the Name.&lt;/strong&gt; This is not about guessing the Serial by brute force, but about solving the modular exponentiation equation by factorizing the 64-bit modulus present in the program's data.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. The Name Hash
&lt;/h3&gt;

&lt;p&gt;Below is the complete code for the routine&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   0x401700:    pusha                                      ; Save all general-purpose registers onto the stack[cite: 1]
   0x401701:    mov    ecx,DWORD PTR [esp+0x28]            ; Retrieve message size to hash from the stack[cite: 1]
   0x401705:    mov    esi,DWORD PTR [esp+0x2c]            ; Retrieve pointer to source data[cite: 1]
   0x401709:    mov    BYTE PTR ds:0x404288,0x1             ; Set hash initialization state flag to 1[cite: 1]
   0x401710:    mov    DWORD PTR ds:0x404284,ecx           ; Store current message size[cite: 1]
   0x401716:    mov    DWORD PTR ds:0x404270,0x67452301    ; MD5 initial constant (A)[cite: 1]
   0x401720:    mov    DWORD PTR ds:0x404274,0xefcdab89    ; MD5 initial constant (B)[cite: 1]
   0x40172a:    mov    DWORD PTR ds:0x404278,0x98badcfe    ; MD5 initial constant (C)[cite: 1]
   0x401734:    mov    DWORD PTR ds:0x40427c,0x10325476    ; MD5 initial constant (D)[cite: 1]
   0x40173e:    mov    DWORD PTR ds:0x404280,ecx           ; Copy total message size for final computation[cite: 1]
   0x401744:    cmp    DWORD PTR ds:0x404284,0x40          ; Check if buffer contains at least 64 bytes (0x40)[cite: 1]
   0x40174b:    jb     0x401dab                            ; If less than 64 bytes, jump to padding/completion stage[cite: 1]
   0x401751:    mov    eax,ds:0x404270                     ; Load current state A into EAX[cite: 1]
   0x401756:    mov    ebx,DWORD PTR ds:0x404274           ; Load current state B into EBX[cite: 1]
   0x40175c:    mov    ecx,DWORD PTR ds:0x404278           ; Load current state C into ECX[cite: 1]
   0x401762:    mov    edx,DWORD PTR ds:0x40427c           ; Load current state D into EDX[cite: 1]
   0x401768:    mov    ebp,ebx                             ; Copy B to EBP for F(B,C,D) calculation[cite: 1]
   0x40176a:    mov    edi,ebx                             ; Copy B to EDI[cite: 1]
   0x40176c:    not    ebp                                 ; EBP = NOT B[cite: 1]
   0x40176e:    and    edi,ecx                             ; EDI = B AND C[cite: 1]
   0x401770:    and    ebp,edx                             ; EBP = (NOT B) AND D[cite: 1]
   0x401772:    add    eax,DWORD PTR [esi]                 ; A = A + M[0][cite: 1]
   0x401774:    or     edi,ebp                             ; EDI = F(B,C,D) = (B AND C) OR ((NOT B) AND D)[cite: 1]
   0x401776:    lea    eax,[edi+eax*1-0x28955b88]          ; A = A + F(B,C,D) + K[0] (0xd76aa478)[cite: 1]
   0x40177d:    rol    eax,0x7                             ; A = A ROL 7[cite: 1]
   0x401780:    add    eax,ebx                             ; A = A + B[cite: 1]
   0x401782:    mov    ebp,eax                             ; Copy A to EBP[cite: 1]
   0x401784:    mov    edi,eax                             ; Copy A to EDI[cite: 1]
   0x401786:    not    ebp                                 ; EBP = NOT A[cite: 1]
   0x401788:    and    edi,ebx                             ; EDI = A AND B[cite: 1]
   0x40178a:    and    ebp,ecx                             ; EBP = (NOT A) AND C[cite: 1]
   0x40178c:    add    edx,DWORD PTR [esi+0x4]             ; D = D + M[1][cite: 1]
   0x40178f:    or     edi,ebp                             ; EDI = F(A,B,C)[cite: 1]
   0x401791:    lea    edx,[edi+edx*1-0x173848aa]          ; D = D + F(A,B,C) + K[1][cite: 1]
   0x401798:    rol    edx,0xc                             ; D = D ROL 12[cite: 1]
   0x40179b:    add    edx,eax                             ; D = D + A[cite: 1]
   0x40179d:    mov    ebp,edx                             ; Copy D to EBP[cite: 1]
   0x40179f:    mov    edi,edx                             ; Copy D to EDI[cite: 1]
   0x4017a1:    not    ebp                                 ; EBP = NOT D[cite: 1]
   0x4017a3:    and    edi,eax                             ; EDI = D AND A[cite: 1]
   0x4017a5:    and    ebp,ebx                             ; EBP = (NOT D) AND B[cite: 1]
   0x4017a7:    add    ecx,DWORD PTR [esi+0x8]             ; C = C + M[2][cite: 1]
   0x4017aa:    or     edi,ebp                             ; EDI = F(D,A,B)[cite: 1]
   0x4017ac:    lea    ecx,[edi+ecx*1+0x242070db]          ; C = C + F(D,A,B) + K[2][cite: 1]
   0x4017b3:    rol    ecx,0x11                            ; C = C ROL 17[cite: 1]
   0x4017b6:    add    ecx,edx                             ; C = C + D[cite: 1]
   0x4017b8:    mov    ebp,ecx                             ; Copy C to EBP[cite: 1]
   0x4017ba:    mov    edi,ecx                             ; Copy C to EDI[cite: 1]
   0x4017bc:    not    ebp                                 ; EBP = NOT C[cite: 1]
   0x4017be:    and    edi,edx                             ; EDI = C AND D[cite: 1]
   0x4017c0:    and    ebp,eax                             ; EBP = (NOT C) AND A[cite: 1]
   0x4017c2:    add    ebx,DWORD PTR [esi+0xc]             ; B = B + M[3][cite: 1]
   0x4017c5:    or     edi,ebp                             ; EDI = F(C,D,A)[cite: 1]
   0x4017c7:    lea    ebx,[edi+ebx*1-0x3e423112]          ; B = B + F(C,D,A) + K[3][cite: 1]
   0x4017ce:    rol    ebx,0x16                            ; B = B ROL 22[cite: 1]
   0x4017d1:    add    ebx,ecx                             ; B = B + C[cite: 1]
   0x4017d3:    mov    ebp,ebx                             ; MD5 Operation Round 1, step 5[cite: 1]
   0x4017d5:    mov    edi,ebx                             ; Prepare bitwise masks[cite: 1]
   0x4017d7:    not    ebp                                 ; Invert B[cite: 1]
   0x4017d9:    and    edi,ecx                             ; B AND C[cite: 1]
   0x4017db:    and    ebp,edx                             ; (NOT B) AND D[cite: 1]
   0x4017dd:    add    eax,DWORD PTR [esi+0x10]             ; Add M[4][cite: 1]
   0x4017e0:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x4017e2:    lea    eax,[edi+eax*1-0xa83f051]           ; Add constant K[4][cite: 1]
   0x4017e9:    rol    eax,0x7                             ; Bitwise circular shift of 7 bits[cite: 1]
   0x4017ec:    add    eax,ebx                             ; Accumulate into A[cite: 1]
   0x4017ee:    mov    ebp,eax                             ; MD5 Operation Round 1, step 6[cite: 1]
   0x4017f0:    mov    edi,eax                             ; Prepare bitwise masks[cite: 1]
   0x4017f2:    not    ebp                                 ; Invert A[cite: 1]
   0x4017f4:    and    edi,ebx                             ; A AND B[cite: 1]
   0x4017f6:    and    ebp,ecx                             ; (NOT A) AND C[cite: 1]
   0x4017f8:    add    edx,DWORD PTR [esi+0x14]             ; Add M[5][cite: 1]
   0x4017fb:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x4017fd:    lea    edx,[edi+edx*1+0x4787c62a]          ; Add constant K[5][cite: 1]
   0x401804:    rol    edx,0xc                             ; Bitwise circular shift of 12 bits[cite: 1]
   0x401807:    add    edx,eax                             ; Accumulate into D[cite: 1]
   0x401809:    mov    ebp,edx                             ; MD5 Operation Round 1, step 7[cite: 1]
   0x40180b:    mov    edi,edx                             ; Prepare bitwise masks[cite: 1]
   0x40180d:    not    ebp                                 ; Invert D[cite: 1]
   0x40180f:    and    edi,eax                             ; D AND A[cite: 1]
   0x401811:    and    ebp,ebx                             ; (NOT D) AND B[cite: 1]
   0x401813:    add    ecx,DWORD PTR [esi+0x18]             ; Add M[6][cite: 1]
   0x401816:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x401818:    lea    ecx,[edi+ecx*1-0x57cfb9ed]          ; Add constant K[6][cite: 1]
   0x40181f:    rol    ecx,0x11                            ; Bitwise circular shift of 17 bits[cite: 1]
   0x401822:    add    ecx,edx                             ; Accumulate into C[cite: 1]
   0x401824:    mov    ebp,ecx                             ; MD5 Operation Round 1, step 8[cite: 1]
   0x401826:    mov    edi,ecx                             ; Prepare bitwise masks[cite: 1]
   0x401828:    not    ebp                                 ; Invert C[cite: 1]
   0x40182a:    and    edi,edx                             ; C AND D[cite: 1]
   0x40182c:    and    ebp,eax                             ; (NOT C) AND A[cite: 1]
   0x40182e:    add    ebx,DWORD PTR [esi+0x1c]             ; Add M[7][cite: 1]
   0x401831:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x401833:    lea    ebx,[edi+ebx*1-0x2b96aff]           ; Add constant K[7][cite: 1]
   0x40183a:    rol    ebx,0x16                            ; Bitwise circular shift of 22 bits[cite: 1]
   0x40183d:    add    ebx,ecx                             ; Accumulate into B[cite: 1]
   0x40183f:    mov    ebp,ebx                             ; MD5 Operation Round 1, step 9[cite: 1]
   0x401841:    mov    edi,ebx                             ; Prepare bitwise masks[cite: 1]
   0x401843:    not    ebp                                 ; Invert B[cite: 1]
   0x401845:    and    edi,ecx                             ; B AND C[cite: 1]
   0x401847:    and    ebp,edx                             ; (NOT B) AND D[cite: 1]
   0x401849:    add    eax,DWORD PTR [esi+0x20]             ; Add M[8][cite: 1]
   0x40184c:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x40184e:    lea    eax,[edi+eax*1+0x698098d8]          ; Add constant K[8][cite: 1]
   0x401855:    rol    eax,0x7                             ; Bitwise circular shift of 7 bits[cite: 1]
   0x401858:    add    eax,ebx                             ; Accumulate into A[cite: 1]
   0x40185a:    mov    ebp,eax                             ; MD5 Operation Round 1, step 10[cite: 1]
   0x40185c:    mov    edi,eax                             ; Prepare bitwise masks[cite: 1]
   0x40185e:    not    ebp                                 ; Invert A[cite: 1]
   0x401860:    and    edi,ebx                             ; A AND B[cite: 1]
   0x401862:    and    ebp,ecx                             ; (NOT A) AND C[cite: 1]
   0x401864:    add    edx,DWORD PTR [esi+0x24]             ; Add M[9][cite: 1]
   0x401867:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x401869:    lea    edx,[edi+edx*1-0x74bb0851]          ; Add constant K[9][cite: 1]
   0x401870:    rol    edx,0xc                             ; Bitwise circular shift of 12 bits[cite: 1]
   0x401873:    add    edx,eax                             ; Accumulate into D[cite: 1]
   0x401875:    mov    ebp,edx                             ; MD5 Operation Round 1, step 11[cite: 1]
   0x401877:    mov    edi,edx                             ; Prepare bitwise masks[cite: 1]
   0x401879:    not    ebp                                 ; Invert D[cite: 1]
   0x40187b:    and    edi,eax                             ; D AND A[cite: 1]
   0x40187d:    and    ebp,ebx                             ; (NOT D) AND B[cite: 1]
   0x40187f:    add    ecx,DWORD PTR [esi+0x28]             ; Add M[10][cite: 1]
   0x401882:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x401884:    lea    ecx,[edi+ecx*1-0xa44f]              ; Add constant K[10][cite: 1]
   0x40188b:    rol    ecx,0x11                            ; Bitwise circular shift of 17 bits[cite: 1]
   0x40188e:    add    ecx,edx                             ; Accumulate into C[cite: 1]
   0x401890:    mov    ebp,ecx                             ; MD5 Operation Round 1, step 12[cite: 1]
   0x401892:    mov    edi,ecx                             ; Prepare bitwise masks[cite: 1]
   0x401894:    not    ebp                                 ; Invert C[cite: 1]
   0x401896:    and    edi,edx                             ; C AND D[cite: 1]
   0x401898:    and    ebp,eax                             ; (NOT C) AND A[cite: 1]
   0x40189a:    add    ebx,DWORD PTR [esi+0x2c]             ; Add M[11][cite: 1]
   0x40189d:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x40189f:    lea    ebx,[edi+ebx*1-0x76a32842]          ; Add constant K[11][cite: 1]
   0x4018a6:    rol    ebx,0x16                            ; Bitwise circular shift of 22 bits[cite: 1]
   0x4018a9:    add    ebx,ecx                             ; Accumulate into B[cite: 1]
   0x4018ab:    mov    ebp,ebx                             ; MD5 Operation Round 1, step 13[cite: 1]
   0x4018ad:    mov    edi,ebx                             ; Prepare bitwise masks[cite: 1]
   0x4018af:    not    ebp                                 ; Invert B[cite: 1]
   0x4018b1:    and    edi,ecx                             ; B AND C[cite: 1]
   0x4018b3:    and    ebp,edx                             ; (NOT B) AND D[cite: 1]
   0x4018b5:    add    eax,DWORD PTR [esi+0x30]             ; Add M[12][cite: 1]
   0x4018b8:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x4018ba:    lea    eax,[edi+eax*1+0x6b901122]          ; Add constant K[12][cite: 1]
   0x4018c1:    rol    eax,0x7                             ; Bitwise circular shift of 7 bits[cite: 1]
   0x4018c4:    add    eax,ebx                             ; Accumulate into A[cite: 1]
   0x4018c6:    mov    ebp,eax                             ; MD5 Operation Round 1, step 14[cite: 1]
   0x4018c8:    mov    edi,eax                             ; Prepare bitwise masks[cite: 1]
   0x4018ca:    not    ebp                                 ; Invert A[cite: 1]
   0x4018cc:    and    edi,ebx                             ; A AND B[cite: 1]
   0x4018ce:    and    ebp,ecx                             ; (NOT A) AND C[cite: 1]
   0x4018d0:    add    edx,DWORD PTR [esi+0x34]             ; Add M[13][cite: 1]
   0x4018d3:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x4018d5:    lea    edx,[edi+edx*1-0x2678e6d]           ; Add constant K[13][cite: 1]
   0x4018dc:    rol    edx,0xc                             ; Bitwise circular shift of 12 bits[cite: 1]
   0x4018df:    add    edx,eax                             ; Accumulate into D[cite: 1]
   0x4018e1:    mov    ebp,edx                             ; MD5 Operation Round 1, step 15[cite: 1]
   0x4018e3:    mov    edi,edx                             ; Prepare bitwise masks[cite: 1]
   0x4018e5:    not    ebp                                 ; Invert D[cite: 1]
   0x4018e7:    and    edi,eax                             ; D AND A[cite: 1]
   0x4018e9:    and    ebp,ebx                             ; (NOT D) AND B[cite: 1]
   0x4018eb:    add    ecx,DWORD PTR [esi+0x38]             ; Add M[14][cite: 1]
   0x4018ee:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x4018f0:    lea    ecx,[edi+ecx*1-0x5986bc72]          ; Add constant K[14][cite: 1]
   0x4018f7:    rol    ecx,0x11                            ; Bitwise circular shift of 17 bits[cite: 1]
   0x4018fa:    add    ecx,edx                             ; Accumulate into C[cite: 1]
   0x4018fc:    mov    ebp,ecx                             ; MD5 Operation Round 1, step 16[cite: 1]
   0x4018fe:    mov    edi,ecx                             ; Prepare bitwise masks[cite: 1]
   0x401900:    not    ebp                                 ; Invert C[cite: 1]
   0x401902:    and    edi,edx                             ; C AND D[cite: 1]
   0x401904:    and    ebp,eax                             ; (NOT C) AND A[cite: 1]
   0x401906:    add    ebx,DWORD PTR [esi+0x3c]             ; Add M[15][cite: 1]
   0x401909:    or     edi,ebp                             ; Combine logical results[cite: 1]
   0x40190b:    lea    ebx,[edi+ebx*1+0x49b40821]          ; Add constant K[15][cite: 1]
   0x401912:    rol    ebx,0x16                            ; Bitwise circular shift of 22 bits[cite: 1]
   0x401915:    add    ebx,ecx                             ; End of Round 1[cite: 1]
   0x401917:    mov    ebp,edx                             ; Start of Round 2 - G(B,C,D) = (B AND D) OR (C AND NOT D)[cite: 1]
   0x401919:    mov    edi,edx                             ; Copy D to EDI[cite: 1]
   0x40191b:    not    ebp                                 ; EBP = NOT D[cite: 1]
   0x40191d:    and    edi,ebx                             ; EDI = D AND B[cite: 1]
   0x40191f:    and    ebp,ecx                             ; EBP = (NOT D) AND C[cite: 1]
   0x401921:    add    eax,DWORD PTR [esi+0x4]              ; A = A + M[1][cite: 1]
   0x401924:    or     edi,ebp                             ; EDI = G(B,C,D)[cite: 1]
   0x401926:    lea    eax,[edi+eax*1-0x9e1da9e]           ; A = A + G(B,C,D) + K[16][cite: 1]
   0x40192d:    rol    eax,0x5                             ; Bitwise circular shift of 5 bits[cite: 1]
   0x401930:    add    eax,ebx                             ; A = A + B[cite: 1]
   0x401932:    mov    ebp,ecx                             ; MD5 Operation Round 2, step 2[cite: 1]
   0x401934:    mov    edi,ecx                             ; Prepare G function[cite: 1]
   0x401936:    not    ebp                                 ; Invert C[cite: 1]
   0x401938:    and    edi,eax                             ; C AND A[cite: 1]
   0x40193a:    and    ebp,ebx                             ; (NOT C) AND B[cite: 1]
   0x40193c:    add    edx,DWORD PTR [esi+0x18]             ; Add M[6][cite: 1]
   0x40193f:    or     edi,ebp                             ; Combine[cite: 1]
   0x401941:    lea    edx,[edi+edx*1-0x3fbf4cc0]          ; Add constant K[17][cite: 1]
   0x401948:    rol    edx,0x9                             ; Bitwise circular shift of 9 bits[cite: 1]
   0x40194b:    add    edx,eax                             ; Accumulate[cite: 1]
   0x40194d:    mov    ebp,ebx                             ; MD5 Operation Round 2, step 3[cite: 1]
   0x40194f:    mov    edi,ebx                             ; Prepare G function[cite: 1]
   0x401951:    not    ebp                                 ; Invert B[cite: 1]
   0x401953:    and    edi,edx                             ; B AND D[cite: 1]
   0x401955:    and    ebp,eax                             ; (NOT B) AND A[cite: 1]
   0x401957:    add    ecx,DWORD PTR [esi+0x2c]             ; Add M[11][cite: 1]
   0x40195a:    or     edi,ebp                             ; Combine[cite: 1]
   0x40195c:    lea    ecx,[edi+ecx*1+0x265e5a51]          ; Add constant K[18][cite: 1]
   0x401963:    rol    ecx,0xe                             ; Bitwise circular shift of 14 bits[cite: 1]
   0x401966:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401968:    mov    ebp,eax                             ; MD5 Operation Round 2, step 4[cite: 1]
   0x40196a:    mov    edi,eax                             ; Prepare G function[cite: 1]
   0x40196c:    not    ebp                                 ; Invert A[cite: 1]
   0x40196e:    and    edi,ecx                             ; A AND C[cite: 1]
   0x401970:    and    ebp,edx                             ; (NOT A) AND D[cite: 1]
   0x401972:    add    ebx,DWORD PTR [esi]                 ; Add M[0][cite: 1]
   0x401974:    or     edi,ebp                             ; Combine[cite: 1]
   0x401976:    lea    ebx,[edi+ebx*1-0x16493856]          ; Add constant K[19][cite: 1]
   0x40197d:    rol    ebx,0x14                            ; Bitwise circular shift of 20 bits[cite: 1]
   0x401980:    add    ebx,ecx                             ; Accumulate[cite: 1]
   0x401982:    mov    ebp,edx                             ; MD5 Operation Round 2, step 5[cite: 1]
   0x401984:    mov    edi,edx                             ; Prepare G function[cite: 1]
   0x401986:    not    ebp                                 ; Invert D[cite: 1]
   0x401988:    and    edi,ebx                             ; D AND B[cite: 1]
   0x40198a:    and    ebp,ecx                             ; (NOT D) AND C[cite: 1]
   0x40198c:    add    eax,DWORD PTR [esi+0x14]             ; Add M[5][cite: 1]
   0x40198f:    or     edi,ebp                             ; Combine[cite: 1]
   0x401991:    lea    eax,[edi+eax*1-0x29d0efa3]          ; Add constant K[20][cite: 1]
   0x401998:    rol    eax,0x5                             ; Bitwise circular shift of 5 bits[cite: 1]
   0x40199b:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x40199d:    mov    ebp,ecx                             ; MD5 Operation Round 2, step 6[cite: 1]
   0x40199f:    mov    edi,ecx                             ; Prepare G function[cite: 1]
   0x4019a1:    not    ebp                                 ; Invert C[cite: 1]
   0x4019a3:    and    edi,eax                             ; C AND A[cite: 1]
   0x4019a5:    and    ebp,ebx                             ; (NOT C) AND B[cite: 1]
   0x4019a7:    add    edx,DWORD PTR [esi+0x28]             ; Add M[10][cite: 1]
   0x4019aa:    or     edi,ebp                             ; Combine[cite: 1]
   0x4019ac:    lea    edx,[edi+edx*1+0x2441453]           ; Add constant K[21][cite: 1]
   0x4019b3:    rol    edx,0x9                             ; Bitwise circular shift of 9 bits[cite: 1]
   0x4019b6:    add    edx,eax                             ; Accumulate[cite: 1]
   0x4019b8:    mov    ebp,ebx                             ; MD5 Operation Round 2, step 7[cite: 1]
   0x4019ba:    mov    edi,ebx                             ; Prepare G function[cite: 1]
   0x4019bc:    not    ebp                                 ; Invert B[cite: 1]
   0x4019be:    and    edi,edx                             ; B AND D[cite: 1]
   0x4019c0:    and    ebp,eax                             ; (NOT B) AND A[cite: 1]
   0x4019c2:    add    ecx,DWORD PTR [esi+0x3c]             ; Add M[15][cite: 1]
   0x4019c5:    or     edi,ebp                             ; Combine[cite: 1]
   0x4019c7:    lea    ecx,[edi+ecx*1-0x275e197f]          ; Add constant K[22][cite: 1]
   0x4019ce:    rol    ecx,0xe                             ; Bitwise circular shift of 14 bits[cite: 1]
   0x4019d1:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x4019d3:    mov    ebp,eax                             ; MD5 Operation Round 2, step 8[cite: 1]
   0x4019d5:    mov    edi,eax                             ; Prepare G function[cite: 1]
   0x4019d7:    not    ebp                                 ; Invert A[cite: 1]
   0x4019d9:    and    edi,ecx                             ; A AND C[cite: 1]
   0x4019db:    and    ebp,edx                             ; (NOT A) AND D[cite: 1]
   0x4019dd:    add    ebx,DWORD PTR [esi+0x10]             ; Add M[4][cite: 1]
   0x4019e0:    or     edi,ebp                             ; Combine[cite: 1]
   0x4019e2:    lea    ebx,[edi+ebx*1-0x182c0438]          ; Add constant K[23][cite: 1]
   0x4019e9:    rol    ebx,0x14                            ; Bitwise circular shift of 20 bits[cite: 1]
   0x4019ec:    add    ebx,ecx                             ; Accumulate[cite: 1]
   0x4019ee:    mov    ebp,edx                             ; MD5 Operation Round 2, step 9[cite: 1]
   0x4019f0:    mov    edi,edx                             ; Prepare G function[cite: 1]
   0x4019f2:    not    ebp                                 ; Invert D[cite: 1]
   0x4019f4:    and    edi,ebx                             ; D AND B[cite: 1]
   0x4019f6:    and    ebp,ecx                             ; (NOT D) AND C[cite: 1]
   0x4019f8:    add    eax,DWORD PTR [esi+0x24]             ; Add M[9][cite: 1]
   0x4019fb:    or     edi,ebp                             ; Combine[cite: 1]
   0x4019fd:    lea    eax,[edi+eax*1+0x21e1cde6]          ; Add constant K[24][cite: 1]
   0x401a04:    rol    eax,0x5                             ; Bitwise circular shift of 5 bits[cite: 1]
   0x401a07:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x401a09:    mov    ebp,ecx                             ; MD5 Operation Round 2, step 10[cite: 1]
   0x401a0b:    mov    edi,ecx                             ; Prepare G function[cite: 1]
   0x401a0d:    not    ebp                                 ; Invert C[cite: 1]
   0x401a0f:    and    edi,eax                             ; C AND A[cite: 1]
   0x401a11:    and    ebp,ebx                             ; (NOT C) AND B[cite: 1]
   0x401a13:    add    edx,DWORD PTR [esi+0x38]             ; Add M[14][cite: 1]
   0x401a16:    or     edi,ebp                             ; Combine[cite: 1]
   0x401a18:    lea    edx,[edi+edx*1-0x3cc8f82a]          ; Add constant K[25][cite: 1]
   0x401a1f:    rol    edx,0x9                             ; Bitwise circular shift of 9 bits[cite: 1]
   0x401a22:    add    edx,eax                             ; Accumulate[cite: 1]
   0x401a24:    mov    ebp,ebx                             ; MD5 Operation Round 2, step 11[cite: 1]
   0x401a26:    mov    edi,ebx                             ; Prepare G function[cite: 1]
   0x401a28:    not    ebp                                 ; Invert B[cite: 1]
   0x401a2a:    and    edi,edx                             ; B AND D[cite: 1]
   0x401a2c:    and    ebp,eax                             ; (NOT B) AND A[cite: 1]
   0x401a2e:    add    ecx,DWORD PTR [esi+0xc]              ; Add M[3][cite: 1]
   0x401a31:    or     edi,ebp                             ; Combine[cite: 1]
   0x401a33:    lea    ecx,[edi+ecx*1-0xb2af279]           ; Add constant K[26][cite: 1]
   0x401a3a:    rol    ecx,0xe                             ; Bitwise circular shift of 14 bits[cite: 1]
   0x401a3d:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401a3f:    mov    ebp,eax                             ; MD5 Operation Round 2, step 12[cite: 1]
   0x401a41:    mov    edi,eax                             ; Prepare G function[cite: 1]
   0x401a43:    not    ebp                                 ; Invert A[cite: 1]
   0x401a45:    and    edi,ecx                             ; A AND C[cite: 1]
   0x401a47:    and    ebp,edx                             ; (NOT A) AND D[cite: 1]
   0x401a49:    add    ebx,DWORD PTR [esi+0x20]             ; Add M[8][cite: 1]
   0x401a4c:    or     edi,ebp                             ; Combine[cite: 1]
   0x401a4e:    lea    ebx,[edi+ebx*1+0x455a14ed]          ; Add constant K[27][cite: 1]
   0x401a55:    rol    ebx,0x14                            ; Bitwise circular shift of 20 bits[cite: 1]
   0x401a58:    add    ebx,ecx                             ; Accumulate[cite: 1]
   0x401a5a:    mov    ebp,edx                             ; MD5 Operation Round 2, step 13[cite: 1]
   0x401a5c:    mov    edi,edx                             ; Prepare G function[cite: 1]
   0x401a5e:    not    ebp                                 ; Invert D[cite: 1]
   0x401a60:    and    edi,ebx                             ; D AND B[cite: 1]
   0x401a62:    and    ebp,ecx                             ; (NOT D) AND C[cite: 1]
   0x401a64:    add    eax,DWORD PTR [esi+0x34]             ; Add M[13][cite: 1]
   0x401a67:    or     edi,ebp                             ; Combine[cite: 1]
   0x401a69:    lea    eax,[edi+eax*1-0x561c16fb]          ; Add constant K[28][cite: 1]
   0x401a70:    rol    eax,0x5                             ; Bitwise circular shift of 5 bits[cite: 1]
   0x401a73:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x401a75:    mov    ebp,ecx                             ; MD5 Operation Round 2, step 14[cite: 1]
   0x401a77:    mov    edi,ecx                             ; Prepare G function[cite: 1]
   0x401a79:    not    ebp                                 ; Invert C[cite: 1]
   0x401a7b:    and    edi,eax                             ; C AND A[cite: 1]
   0x401a7d:    and    ebp,ebx                             ; (NOT C) AND B[cite: 1]
   0x401a7f:    add    edx,DWORD PTR [esi+0x8]              ; Add M[2][cite: 1]
   0x401a82:    or     edi,ebp                             ; Combine[cite: 1]
   0x401a84:    lea    edx,[edi+edx*1-0x3105c08]           ; Add constant K[29][cite: 1]
   0x401a8b:    rol    edx,0x9                             ; Bitwise circular shift of 9 bits[cite: 1]
   0x401a8e:    add    edx,eax                             ; Accumulate[cite: 1]
   0x401a90:    mov    ebp,ebx                             ; MD5 Operation Round 2, step 15[cite: 1]
   0x401a92:    mov    edi,ebx                             ; Prepare G function[cite: 1]
   0x401a94:    not    ebp                                 ; Invert B[cite: 1]
   0x401a96:    and    edi,edx                             ; B AND D[cite: 1]
   0x401a98:    and    ebp,eax                             ; (NOT B) AND A[cite: 1]
   0x401a9a:    add    ecx,DWORD PTR [esi+0x1c]             ; Add M[7][cite: 1]
   0x401a9d:    or     edi,ebp                             ; Combine[cite: 1]
   0x401a9f:    lea    ecx,[edi+ecx*1+0x676f02d9]          ; Add constant K[30][cite: 1]
   0x401aa6:    rol    ecx,0xe                             ; Bitwise circular shift of 14 bits[cite: 1]
   0x401aa9:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401aab:    mov    ebp,eax                             ; MD5 Operation Round 2, step 16[cite: 1]
   0x401aad:    mov    edi,eax                             ; Prepare G function[cite: 1]
   0x401aaf:    not    ebp                                 ; Invert A[cite: 1]
   0x401ab1:    and    edi,ecx                             ; A AND C[cite: 1]
   0x401ab3:    and    ebp,edx                             ; (NOT A) AND D[cite: 1]
   0x401ab5:    add    ebx,DWORD PTR [esi+0x30]             ; Add M[12][cite: 1]
   0x401ab8:    or     edi,ebp                             ; Combine[cite: 1]
   0x401aba:    lea    ebx,[edi+ebx*1-0x72d5b376]          ; Add constant K[31][cite: 1]
   0x401ac1:    rol    ebx,0x14                            ; Bitwise circular shift of 20 bits[cite: 1]
   0x401ac4:    add    ebx,ecx                             ; End of Round 2[cite: 1]
   0x401ac6:    mov    ebp,edx                             ; Start of Round 3 - H(B,C,D) = B XOR C XOR D[cite: 1]
   0x401ac8:    add    eax,DWORD PTR [esi+0x14]             ; A = A + M[5][cite: 1]
   0x401acb:    xor    ebp,ecx                             ; EBP = D XOR C[cite: 1]
   0x401acd:    xor    ebp,ebx                             ; EBP = D XOR C XOR B[cite: 1]
   0x401acf:    lea    eax,[ebp+eax*1-0x5c6be]             ; A = A + H(B,C,D) + K[32][cite: 1]
   0x401ad6:    rol    eax,0x4                             ; Bitwise circular shift of 4 bits[cite: 1]
   0x401ad9:    add    eax,ebx                             ; A = A + B[cite: 1]
   0x401adb:    mov    ebp,ecx                             ; MD5 Operation Round 3, step 2[cite: 1]
   0x401add:    add    edx,DWORD PTR [esi+0x20]             ; Add M[8][cite: 1]
   0x401ae0:    xor    ebp,ebx                             ; C XOR B[cite: 1]
   0x401ae2:    xor    ebp,eax                             ; C XOR B XOR A[cite: 1]
   0x401ae4:    lea    edx,[ebp+edx*1-0x788e097f]          ; Add constant K[33][cite: 1]
   0x401aeb:    rol    edx,0xb                             ; Bitwise circular shift of 11 bits[cite: 1]
   0x401aee:    add    edx,eax                             ; Accumulate into D[cite: 1]
   0x401af0:    mov    ebp,ebx                             ; MD5 Operation Round 3, step 3[cite: 1]
   0x401af2:    add    ecx,DWORD PTR [esi+0x2c]             ; Add M[11][cite: 1]
   0x401af5:    xor    ebp,eax                             ; B XOR A[cite: 1]
   0x401af7:    xor    ebp,edx                             ; B XOR A XOR D[cite: 1]
   0x401af9:    lea    ecx,[ebp+ecx*1+0x6d9d6122]          ; Add constant K[34][cite: 1]
   0x401b00:    rol    ecx,0x10                            ; Bitwise circular shift of 16 bits[cite: 1]
   0x401b03:    add    ecx,edx                             ; Accumulate into C[cite: 1]
   0x401b05:    mov    ebp,eax                             ; MD5 Operation Round 3, step 4[cite: 1]
   0x401b07:    add    ebx,DWORD PTR [esi+0x38]             ; Add M[14][cite: 1]
   0x401b0a:    xor    ebp,edx                             ; A XOR D[cite: 1]
   0x401b0c:    xor    ebp,ecx                             ; A XOR D XOR C[cite: 1]
   0x401b0e:    lea    ebx,[ebp+ebx*1-0x21ac7f4]           ; Add constant K[35][cite: 1]
   0x401b15:    rol    ebx,0x17                            ; Bitwise circular shift of 23 bits[cite: 1]
   0x401b18:    add    ebx,ecx                             ; Accumulate into B[cite: 1]
   0x401b1a:    mov    ebp,edx                             ; MD5 Operation Round 3, step 5[cite: 1]
   0x401b1c:    add    eax,DWORD PTR [esi+0x4]              ; Add M[1][cite: 1]
   0x401b1f:    xor    ebp,ecx                             ; D XOR C[cite: 1]
   0x401b21:    xor    ebp,ebx                             ; D XOR C XOR B[cite: 1]
   0x401b23:    lea    eax,[ebp+eax*1-0x5b4115bc]          ; Add constant K[36][cite: 1]
   0x401b2a:    rol    eax,0x4                             ; Bitwise circular shift of 4 bits[cite: 1]
   0x401b2d:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x401b2f:    mov    ebp,ecx                             ; MD5 Operation Round 3, step 6[cite: 1]
   0x401b31:    add    edx,DWORD PTR [esi+0x10]             ; Add M[4][cite: 1]
   0x401b34:    xor    ebp,ebx                             ; C XOR B[cite: 1]
   0x401b36:    xor    ebp,eax                             ; C XOR B XOR A[cite: 1]
   0x401b38:    lea    edx,[ebp+edx*1+0x4bdecfa9]          ; Add constant K[37][cite: 1]
   0x401b3f:    rol    edx,0xb                             ; Bitwise circular shift of 11 bits[cite: 1]
   0x401b42:    add    edx,eax                             ; Accumulate[cite: 1]
   0x401b44:    mov    ebp,ebx                             ; MD5 Operation Round 3, step 7[cite: 1]
   0x401b46:    add    ecx,DWORD PTR [esi+0x1c]             ; Add M[7][cite: 1]
   0x401b49:    xor    ebp,eax                             ; B XOR A[cite: 1]
   0x401b4b:    xor    ebp,edx                             ; B XOR A XOR D[cite: 1]
   0x401b4d:    lea    ecx,[ebp+ecx*1-0x944b4a0]           ; Add constant K[38][cite: 1]
   0x401b54:    rol    ecx,0x10                            ; Bitwise circular shift of 16 bits[cite: 1]
   0x401b57:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401b59:    mov    ebp,eax                             ; MD5 Operation Round 3, step 8[cite: 1]
   0x401b5b:    add    ebx,DWORD PTR [esi+0x28]             ; Add M[10][cite: 1]
   0x401b5e:    xor    ebp,edx                             ; A XOR D[cite: 1]
   0x401b60:    xor    ebp,ecx                             ; A XOR D XOR C[cite: 1]
   0x401b62:    lea    ebx,[ebp+ebx*1-0x41404390]          ; Add constant K[39][cite: 1]
   0x401b69:    rol    ebx,0x17                            ; Bitwise circular shift of 23 bits[cite: 1]
   0x401b6c:    add    ebx,ecx                             ; Accumulate[cite: 1]
   0x401b6e:    mov    ebp,edx                             ; MD5 Operation Round 3, step 9[cite: 1]
   0x401b70:    add    eax,DWORD PTR [esi+0x34]             ; Add M[13][cite: 1]
   0x401b73:    xor    ebp,ecx                             ; D XOR C[cite: 1]
   0x401b75:    xor    ebp,ebx                             ; D XOR C XOR B[cite: 1]
   0x401b77:    lea    eax,[ebp+eax*1+0x289b7ec6]          ; Add constant K[40][cite: 1]
   0x401b7e:    rol    eax,0x4                             ; Bitwise circular shift of 4 bits[cite: 1]
   0x401b81:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x401b83:    mov    ebp,ecx                             ; MD5 Operation Round 3, step 10[cite: 1]
   0x401b85:    add    edx,DWORD PTR [esi]                 ; Add M[0][cite: 1]
   0x401b87:    xor    ebp,ebx                             ; C XOR B[cite: 1]
   0x401b89:    xor    ebp,eax                             ; C XOR B XOR A[cite: 1]
   0x401b8b:    lea    edx,[ebp+edx*1-0x155ed806]          ; Add constant K[41][cite: 1]
   0x401b92:    rol    edx,0xb                             ; Bitwise circular shift of 11 bits[cite: 1]
   0x401b95:    add    edx,eax                             ; Accumulate[cite: 1]
   0x401b97:    mov    ebp,ebx                             ; MD5 Operation Round 3, step 11[cite: 1]
   0x401b99:    add    ecx,DWORD PTR [esi+0xc]              ; Add M[3][cite: 1]
   0x401b9c:    xor    ebp,eax                             ; B XOR A[cite: 1]
   0x401b9e:    xor    ebp,edx                             ; B XOR A XOR D[cite: 1]
   0x401ba0:    lea    ecx,[ebp+ecx*1-0x2b10cf7b]          ; Add constant K[42][cite: 1]
   0x401ba7:    rol    ecx,0x10                            ; Bitwise circular shift of 16 bits[cite: 1]
   0x401baa:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401bac:    mov    ebp,eax                             ; MD5 Operation Round 3, step 12[cite: 1]
   0x401bae:    add    ebx,DWORD PTR [esi+0x18]             ; Add M[6][cite: 1]
   0x401bb1:    xor    ebp,edx                             ; A XOR D[cite: 1]
   0x401bb3:    xor    ebp,ecx                             ; A XOR D XOR C[cite: 1]
   0x401bb5:    lea    ebx,[ebp+ebx*1+0x4881d05]           ; Add constant K[43][cite: 1]
   0x401bbc:    rol    ebx,0x17                            ; Bitwise circular shift of 23 bits[cite: 1]
   0x401bbf:    add    ebx,ecx                             ; Accumulate[cite: 1]
   0x401bc1:    mov    ebp,edx                             ; MD5 Operation Round 3, step 13[cite: 1]
   0x401bc3:    add    eax,DWORD PTR [esi+0x24]             ; Add M[9][cite: 1]
   0x401bc6:    xor    ebp,ecx                             ; D XOR C[cite: 1]
   0x401bc8:    xor    ebp,ebx                             ; D XOR C XOR B[cite: 1]
   0x401bca:    lea    eax,[ebp+eax*1-0x262b2fc7]          ; Add constant K[44][cite: 1]
   0x401bd1:    rol    eax,0x4                             ; Bitwise circular shift of 4 bits[cite: 1]
   0x401bd4:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x401bd6:    mov    ebp,ecx                             ; MD5 Operation Round 3, step 14[cite: 1]
   0x401bd8:    add    edx,DWORD PTR [esi+0x30]             ; Add M[12][cite: 1]
   0x401bdb:    xor    ebp,ebx                             ; C XOR B[cite: 1]
   0x401bdd:    xor    ebp,eax                             ; C XOR B XOR A[cite: 1]
   0x401bdf:    lea    edx,[ebp+edx*1-0x1924661b]          ; Add constant K[45][cite: 1]
   0x401be6:    rol    edx,0xb                             ; Bitwise circular shift of 11 bits[cite: 1]
   0x401be9:    add    edx,eax                             ; Accumulate[cite: 1]
   0x401beb:    mov    ebp,ebx                             ; MD5 Operation Round 3, step 15[cite: 1]
   0x401bed:    add    ecx,DWORD PTR [esi+0x3c]             ; Add M[15][cite: 1]
   0x401bf0:    xor    ebp,eax                             ; B XOR A[cite: 1]
   0x401bf2:    xor    ebp,edx                             ; B XOR A XOR D[cite: 1]
   0x401bf4:    lea    ecx,[ebp+ecx*1+0x1fa27cf8]          ; Add constant K[46][cite: 1]
   0x401bfb:    rol    ecx,0x10                            ; Bitwise circular shift of 16 bits[cite: 1]
   0x401bfe:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401c00:    mov    ebp,eax                             ; MD5 Operation Round 3, step 16[cite: 1]
   0x401c02:    add    ebx,DWORD PTR [esi+0x8]              ; Add M[2][cite: 1]
   0x401c05:    xor    ebp,edx                             ; A XOR D[cite: 1]
   0x401c07:    xor    ebp,ecx                             ; A XOR D XOR C[cite: 1]
   0x401c09:    lea    ebx,[ebp+ebx*1-0x3b53a99b]          ; Add constant K[47][cite: 1]
   0x401c10:    rol    ebx,0x17                            ; Bitwise circular shift of 23 bits[cite: 1]
   0x401c13:    add    ebx,ecx                             ; End of Round 3[cite: 1]
   0x401c15:    mov    edi,edx                             ; Start of Round 4 - I(B,C,D) = C XOR (B OR NOT D)[cite: 1]
   0x401c17:    add    eax,DWORD PTR [esi]                 ; A = A + M[0][cite: 1]
   0x401c19:    not    edi                                 ; EDI = NOT D[cite: 1]
   0x401c1b:    or     edi,ebx                             ; EDI = B OR (NOT D)[cite: 1]
   0x401c1d:    xor    edi,ecx                             ; EDI = C XOR (B OR NOT D)[cite: 1]
   0x401c1f:    lea    eax,[edi+eax*1-0xbd6ddbc]           ; A = A + I(B,C,D) + K[48][cite: 1]
   0x401c26:    rol    eax,0x6                             ; Bitwise circular shift of 6 bits[cite: 1]
   0x401c29:    add    eax,ebx                             ; A = A + B[cite: 1]
   0x401c2b:    mov    edi,ecx                             ; MD5 Operation Round 4, step 2[cite: 1]
   0x401c2d:    add    edx,DWORD PTR [esi+0x1c]             ; Add M[7][cite: 1]
   0x401c30:    not    edi                                 ; NOT C[cite: 1]
   0x401c32:    or     edi,eax                             ; A OR (NOT C)[cite: 1]
   0x401c34:    xor    edi,ebx                             ; B XOR (A OR NOT C)[cite: 1]
   0x401c36:    lea    edx,[edi+edx*1+0x432aff97]          ; Add constant K[49][cite: 1]
   0x401c3d:    rol    edx,0xa                             ; Bitwise circular shift of 10 bits[cite: 1]
   0x401c40:    add    edx,eax                             ; Accumulate into D[cite: 1]
   0x401c42:    mov    edi,ebx                             ; MD5 Operation Round 4, step 3[cite: 1]
   0x401c44:    add    ecx,DWORD PTR [esi+0x38]             ; Add M[14][cite: 1]
   0x401c47:    not    edi                                 ; NOT B[cite: 1]
   0x401c49:    or     edi,edx                             ; D OR (NOT B)[cite: 1]
   0x401c4b:    xor    edi,eax                             ; A XOR (D OR NOT B)[cite: 1]
   0x401c4d:    lea    ecx,[edi+ecx*1-0x546bdc59]          ; Add constant K[50][cite: 1]
   0x401c54:    rol    ecx,0xf                             ; Bitwise circular shift of 15 bits[cite: 1]
   0x401c57:    add    ecx,edx                             ; Accumulate into C[cite: 1]
   0x401c59:    mov    edi,eax                             ; MD5 Operation Round 4, step 4[cite: 1]
   0x401c5b:    add    ebx,DWORD PTR [esi+0x14]             ; Add M[5][cite: 1]
   0x401c5e:    not    edi                                 ; NOT A[cite: 1]
   0x401c60:    or     edi,ecx                             ; C OR (NOT A)[cite: 1]
   0x401c62:    xor    edi,edx                             ; D XOR (C OR NOT A)[cite: 1]
   0x401c64:    lea    ebx,[edi+ebx*1-0x36c5fc7]           ; Add constant K[51][cite: 1]
   0x401c6b:    rol    ebx,0x15                            ; Bitwise circular shift of 21 bits[cite: 1]
   0x401c6e:    add    ebx,ecx                             ; Accumulate into B[cite: 1]
   0x401c70:    mov    edi,edx                             ; MD5 Operation Round 4, step 5[cite: 1]
   0x401c72:    add    eax,DWORD PTR [esi+0x30]             ; Add M[12][cite: 1]
   0x401c75:    not    edi                                 ; NOT D[cite: 1]
   0x401c77:    or     edi,ebx                             ; B OR (NOT D)[cite: 1]
   0x401c79:    xor    edi,ecx                             ; C XOR (B OR NOT D)[cite: 1]
   0x401c7b:    lea    eax,[edi+eax*1+0x655b59c3]          ; Add constant K[52][cite: 1]
   0x401c82:    rol    eax,0x6                             ; Bitwise circular shift of 6 bits[cite: 1]
   0x401c85:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x401c87:    mov    edi,ecx                             ; MD5 Operation Round 4, step 6[cite: 1]
   0x401c89:    add    edx,DWORD PTR [esi+0xc]              ; Add M[3][cite: 1]
   0x401c8c:    not    edi                                 ; NOT C[cite: 1]
   0x401c8e:    or     edi,eax                             ; A OR (NOT C)[cite: 1]
   0x401c90:    xor    edi,ebx                             ; B XOR (A OR NOT C)[cite: 1]
   0x401c92:    lea    edx,[edi+edx*1-0x70f3336e]          ; Add constant K[53][cite: 1]
   0x401c99:    rol    edx,0xa                             ; Bitwise circular shift of 10 bits[cite: 1]
   0x401c9c:    add    edx,eax                             ; Accumulate[cite: 1]
   0x401c9e:    mov    edi,ebx                             ; MD5 Operation Round 4, step 7[cite: 1]
   0x401ca0:    add    ecx,DWORD PTR [esi+0x28]             ; Add M[10][cite: 1]
   0x401ca3:    not    edi                                 ; NOT B[cite: 1]
   0x401ca5:    or     edi,edx                             ; D OR (NOT B)[cite: 1]
   0x401ca7:    xor    edi,eax                             ; A XOR (D OR NOT B)[cite: 1]
   0x401ca9:    lea    ecx,[edi+ecx*1-0x100b83]            ; Add constant K[54][cite: 1]
   0x401cb0:    rol    ecx,0xf                             ; Bitwise circular shift of 15 bits[cite: 1]
   0x401cb3:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401cb5:    mov    edi,eax                             ; MD5 Operation Round 4, step 8[cite: 1]
   0x401cb7:    add    ebx,DWORD PTR [esi+0x4]              ; Add M[1][cite: 1]
   0x401cba:    not    edi                                 ; NOT A[cite: 1]
   0x401cbc:    or     edi,ecx                             ; C OR (NOT A)[cite: 1]
   0x401cbe:    xor    edi,edx                             ; D XOR (C OR NOT A)[cite: 1]
   0x401cc0:    lea    ebx,[edi+ebx*1-0x7a7ba22f]          ; Add constant K[55][cite: 1]
   0x401cc7:    rol    ebx,0x15                            ; Bitwise circular shift of 21 bits[cite: 1]
   0x401cca:    add    ebx,ecx                             ; Accumulate[cite: 1]
   0x401ccc:    mov    edi,edx                             ; MD5 Operation Round 4, step 9[cite: 1]
   0x401cce:    add    eax,DWORD PTR [esi+0x20]             ; Add M[8][cite: 1]
   0x401cd1:    not    edi                                 ; NOT D[cite: 1]
   0x401cd3:    or     edi,ebx                             ; B OR (NOT D)[cite: 1]
   0x401cd5:    xor    edi,ecx                             ; C XOR (B OR NOT D)[cite: 1]
   0x401cd7:    lea    eax,[edi+eax*1+0x6fa87e4f]          ; Add constant K[56][cite: 1]
   0x401cde:    rol    eax,0x6                             ; Bitwise circular shift of 6 bits[cite: 1]
   0x401ce1:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x401ce3:    mov    edi,ecx                             ; MD5 Operation Round 4, step 10[cite: 1]
   0x401ce5:    add    edx,DWORD PTR [esi+0x3c]             ; Add M[15][cite: 1]
   0x401ce8:    not    edi                                 ; NOT C[cite: 1]
   0x401cea:    or     edi,eax                             ; A OR (NOT C)[cite: 1]
   0x401cec:    xor    edi,ebx                             ; B XOR (A OR NOT C)[cite: 1]
   0x401cee:    lea    edx,[edi+edx*1-0x1d31920]           ; Add constant K[57][cite: 1]
   0x401cf5:    rol    edx,0xa                             ; Bitwise circular shift of 10 bits[cite: 1]
   0x401cf8:    add    edx,eax                             ; Accumulate[cite: 1]
   0x401cfa:    mov    edi,ebx                             ; MD5 Operation Round 4, step 11[cite: 1]
   0x401cfc:    add    ecx,DWORD PTR [esi+0x18]             ; Add M[6][cite: 1]
   0x401cff:    not    edi                                 ; NOT B[cite: 1]
   0x401d01:    or     edi,edx                             ; D OR (NOT B)[cite: 1]
   0x401d03:    xor    edi,eax                             ; A XOR (D OR NOT B)[cite: 1]
   0x401d05:    lea    ecx,[edi+ecx*1-0x5cfebcec]          ; Add constant K[58][cite: 1]
   0x401d0c:    rol    ecx,0xf                             ; Bitwise circular shift of 15 bits[cite: 1]
   0x401d0f:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401d11:    mov    edi,eax                             ; MD5 Operation Round 4, step 12[cite: 1]
   0x401d13:    add    ebx,DWORD PTR [esi+0x34]             ; Add M[13][cite: 1]
   0x401d16:    not    edi                                 ; NOT A[cite: 1]
   0x401d18:    or     edi,ecx                             ; C OR (NOT A)[cite: 1]
   0x401d1a:    xor    edi,edx                             ; D XOR (C OR NOT A)[cite: 1]
   0x401d1c:    lea    ebx,[edi+ebx*1+0x4e0811a1]          ; Add constant K[59][cite: 1]
   0x401d23:    rol    ebx,0x15                            ; Bitwise circular shift of 21 bits[cite: 1]
   0x401d26:    add    ebx,ecx                             ; Accumulate[cite: 1]
   0x401d28:    mov    edi,edx                             ; MD5 Operation Round 4, step 13[cite: 1]
   0x401d2a:    add    eax,DWORD PTR [esi+0x10]             ; Add M[4][cite: 1]
   0x401d2d:    not    edi                                 ; NOT D[cite: 1]
   0x401d2f:    or     edi,ebx                             ; B OR (NOT D)[cite: 1]
   0x401d31:    xor    edi,ecx                             ; C XOR (B OR NOT D)[cite: 1]
   0x401d33:    lea    eax,[edi+eax*1-0x8ac817e]           ; Add constant K[60][cite: 1]
   0x401d3a:    rol    eax,0x6                             ; Bitwise circular shift of 6 bits[cite: 1]
   0x401d3d:    add    eax,ebx                             ; Accumulate[cite: 1]
   0x401d3f:    mov    edi,ecx                             ; MD5 Operation Round 4, step 14[cite: 1]
   0x401d41:    add    edx,DWORD PTR [esi+0x2c]             ; Add M[11][cite: 1]
   0x401d44:    not    edi                                 ; NOT C[cite: 1]
   0x401d46:    or     edi,eax                             ; A OR (NOT C)[cite: 1]
   0x401d48:    xor    edi,ebx                             ; B XOR (A OR NOT C)[cite: 1]
   0x401d4a:    lea    edx,[edi+edx*1-0x42c50dcb]          ; Add constant K[61][cite: 1]
   0x401d51:    rol    edx,0xa                             ; Bitwise circular shift of 10 bits[cite: 1]
   0x401d54:    add    edx,eax                             ; Accumulate[cite: 1]
   0x401d56:    mov    edi,ebx                             ; MD5 Operation Round 4, step 15[cite: 1]
   0x401d58:    add    ecx,DWORD PTR [esi+0x8]              ; Add M[2][cite: 1]
   0x401d5b:    not    edi                                 ; NOT B[cite: 1]
   0x401d5d:    or     edi,edx                             ; D OR (NOT B)[cite: 1]
   0x401d5f:    xor    edi,eax                             ; A XOR (D OR NOT B)[cite: 1]
   0x401d61:    lea    ecx,[edi+ecx*1+0x2ad7d2bb]          ; Add constant K[62][cite: 1]
   0x401d68:    rol    ecx,0xf                             ; Bitwise circular shift of 15 bits[cite: 1]
   0x401d6b:    add    ecx,edx                             ; Accumulate[cite: 1]
   0x401d6d:    mov    edi,eax                             ; MD5 Operation Round 4, step 16[cite: 1]
   0x401d6f:    add    ebx,DWORD PTR [esi+0x24]             ; Add M[9][cite: 1]
   0x401d72:    not    edi                                 ; NOT A[cite: 1]
   0x401d74:    or     edi,ecx                             ; C OR (NOT A)[cite: 1]
   0x401d76:    xor    edi,edx                             ; D XOR (C OR NOT A)[cite: 1]
   0x401d78:    lea    ebx,[edi+ebx*1-0x14792c6f]          ; Add constant K[63][cite: 1]
   0x401d7f:    rol    ebx,0x15                            ; Bitwise circular shift of 21 bits[cite: 1]
   0x401d82:    add    ebx,ecx                             ; End of the 4 MD5 rounds[cite: 1]
   0x401d84:    add    DWORD PTR ds:0x404270,eax           ; Update accumulator state A[cite: 1]
   0x401d8a:    add    DWORD PTR ds:0x404274,ebx           ; Update accumulator state B[cite: 1]
   0x401d90:    add    DWORD PTR ds:0x404278,ecx           ; Update accumulator state C[cite: 1]
   0x401d96:    add    DWORD PTR ds:0x40427c,edx           ; Update accumulator state D[cite: 1]
   0x401d9c:    sub    DWORD PTR ds:0x404284,0x40          ; Decrement remaining size by 64 bytes[cite: 1]
   0x401da3:    add    esi,0x40                            ; Advance source pointer by 64 bytes[cite: 1]
   0x401da6:    jmp    0x401744                            ; Process next 64-byte block[cite: 1]
   0x401dab:    cmp    BYTE PTR ds:0x404288,0x0             ; Test if padding has already been applied[cite: 1]
   0x401db2:    je     0x401e10                            ; If yes, jump to fingerprint finalization[cite: 1]
   0x401db4:    mov    ecx,DWORD PTR ds:0x404284           ; Load remaining bytes of the last block[cite: 1]
   0x401dba:    mov    BYTE PTR ds:0x404288,0x0             ; Mark padding as in-progress/done[cite: 1]
   0x401dc1:    mov    DWORD PTR ds:0x404284,0x40          ; Set next processing size to 64 bytes[cite: 1]
   0x401dcb:    mov    eax,ecx                             ; Save remaining size in EAX[cite: 1]
   0x401dcd:    mov    edi,0x40428c                        ; Pointer to temporary padding buffer[cite: 1]
   0x401dd2:    test   eax,eax                             ; Are there unprocessed bytes remaining?[cite: 1]
   0x401dd4:    je     0x401dd8                            ; If not, skip copy[cite: 1]
   0x401dd6:    rep movs BYTE PTR es:[edi],BYTE PTR ds:[esi]; Copy remaining bytes into buffer[cite: 1]
   0x401dd8:    mov    ecx,eax                             ; Size restored in ECX[cite: 1]
   0x401dda:    mov    BYTE PTR [edi],0x80                 ; Append termination bit 0x80 to end of message[cite: 1]
   0x401ddd:    sub    ecx,0x37                            ; Calculate required space for size (56 bytes)[cite: 1]
   0x401de0:    inc    edi                                 ; Advance EDI past 0x80 byte[cite: 1]
   0x401de1:    neg    ecx                                 ; Invert to determine required number of zeros[cite: 1]
   0x401de3:    je     0x401df5                            ; If perfectly aligned, jump to size storage[cite: 1]
   0x401de5:    jns    0x401df1                            ; If positive, current block is sufficient[cite: 1]
   0x401de7:    add    DWORD PTR ds:0x404284,0x40          ; Otherwise, add a second padding block (64 bytes)[cite: 1]
   0x401dee:    add    ecx,0x40                            ; Adjust zero counter[cite: 1]
   0x401df1:    xor    al,al                               ; Prepare null byte (0x00)[cite: 1]
   0x401df3:    rep stos BYTE PTR es:[edi],al              ; Fill buffer with 0x00 bytes[cite: 1]
   0x401df5:    mov    edx,0x8                             ; Multiplier 8 to convert bytes to bits[cite: 1]
   0x401dfa:    mov    eax,ds:0x404280                     ; Retrieve initial message size[cite: 1]
   0x401dff:    mul    edx                                 ; EDX:EAX = size in bits[cite: 1]
   0x401e01:    mov    DWORD PTR [edi],eax                 ; Store low-order 32 bits of size[cite: 1]
   0x401e03:    mov    DWORD PTR [edi+0x4],edx             ; Store high-order 32 bits of size[cite: 1]
   0x401e06:    mov    esi,0x40428c                        ; ESI now points to prepared padding block[cite: 1]
   0x401e0b:    jmp    0x401744                            ; Execute last MD5 pass on this block[cite: 1]
   0x401e10:    mov    esi,0x404270                        ; Pointer to final hash (A, B, C, D)[cite: 1]
   0x401e15:    mov    edi,DWORD PTR [esp+0x24]            ; Retrieve destination buffer for result[cite: 1]
   0x401e19:    push   esi                                 ; Save source address on stack[cite: 1]
   0x401e1a:    mov    ecx,0x4                             ; 4 dwords = 16 bytes = 128 bits of MD5 hash[cite: 1]
   0x401e1f:    rep movs DWORD PTR es:[edi],DWORD PTR ds:[esi]; Copy final MD5 hash to destination[cite: 1]
   0x401e21:    pop    edi                                 ; Restore pointer[cite: 1]
   0x401e22:    mov    ecx,0x27                            ; Size for clearing memory area[cite: 1]
   0x401e27:    xor    eax,eax                             ; Zero internal registers[cite: 1]
   0x401e29:    rep stos DWORD PTR es:[edi],eax              ; Wipe sensitive data from MD5 context[cite: 1]
   0x401e2b:    popa                                       ; Restore all general-purpose registers[cite: 1]
   0x401e2c:    ret    0xc                                 ; Return and pop 12 bytes of parameters[cite: 1]
   0x401e2f:    int3                                       ; Alignment / Padding NOP instruction[cite: 1]
   0x401e30:    pusha                                      ; Entry point for ECC point analysis/validation function[cite: 1]
   0x401e31:    mov    esi,DWORD PTR [esp+0x24]            ; Pointer to first ECC point (Point P)[cite: 1]
   0x401e35:    mov    edi,DWORD PTR [esp+0x28]            ; Pointer to second ECC point (Point Q)[cite: 1]
   0x401e39:    mov    ebp,DWORD PTR ds:0x40409c           ; Load finite field modulo p[cite: 1]
   0x401e3f:    mov    eax,DWORD PTR [esi]                 ; Test if point P is point at infinity[cite: 1]
   0x401e41:    test   eax,eax                             ; Validate point P presence flag[cite: 1]
   0x401e43:    je     0x401f61                            ; If invalid/null, exit[cite: 1]
   0x401e49:    mov    eax,DWORD PTR [edi]                 ; Test if point Q is point at infinity[cite: 1]
   0x401e4b:    test   eax,eax                             ; Validate point Q presence flag[cite: 1]
   0x401e4d:    je     0x401f6a                            ; If Q is null, copy P to Q and terminate[cite: 1]
   0x401e53:    mov    eax,DWORD PTR [esi+0x4]              ; EAX = P.x (X coordinate of point P)[cite: 1]
   0x401e56:    mov    ecx,DWORD PTR [esi+0x8]              ; ECX = P.y (Y coordinate of point P)[cite: 1]
   0x401e59:    mov    edx,DWORD PTR [esi+0xc]              ; EDX = P.z (Z coordinate of point P)[cite: 1]
   0x401e5c:    cmp    eax,DWORD PTR [edi+0x4]              ; Compare P.x with Q.x[cite: 1]
   0x401e5f:    jne    0x401ea6                            ; If X1 != X2, jump to general point addition[cite: 1]
   0x401e61:    cmp    ecx,DWORD PTR [edi+0x8]              ; Compare P.y with Q.y[cite: 1]
   0x401e64:    jne    0x401ea6                            ; If Y1 != Y2, jump to addition[cite: 1]
   0x401e66:    cmp    edx,DWORD PTR [edi+0xc]              ; Compare P.z with Q.z[cite: 1]
   0x401e69:    jne    0x401ea6                            ; If Z1 != Z2, jump to addition[cite: 1]
   0x401e6b:    mov    eax,DWORD PTR [esi+0x10]             ; Load additional component P.x2[cite: 1]
   0x401e6e:    mov    ecx,DWORD PTR [esi+0x14]             ; Load additional component P.y2[cite: 1]
   0x401e71:    mov    edx,DWORD PTR [esi+0x18]             ; Load additional component P.z2[cite: 1]
   0x401e74:    cmp    eax,DWORD PTR [edi+0x10]             ; Compare with Q.x2[cite: 1]
   0x401e77:    jne    0x401e87                            ; Symmetry test / inverse point test[cite: 1]
   0x401e79:    cmp    ecx,DWORD PTR [edi+0x14]             ; Compare with Q.y2[cite: 1]
   0x401e7c:    jne    0x401e87                            ; Symmetry test[cite: 1]
   0x401e7e:    cmp    edx,DWORD PTR [edi+0x18]             ; Compare with Q.z2[cite: 1]
   0x401e81:    je     0x401f94                            ; If P == Q, ECC point doubling[cite: 1]
   0x401e87:    mov    ebx,ebp                             ; EBX = modulo p[cite: 1]
   0x401e89:    sub    ebx,DWORD PTR [edi+0x10]             ; EBX = p - Q.x2[cite: 1]
   0x401e8c:    cmp    ebx,eax                             ; Test if P.x2 == -Q.x2 mod p[cite: 1]
   0x401e8e:    jne    0x401ea6                            ; If not, standard geometric addition[cite: 1]
   0x401e90:    mov    ebx,ebp                             ; EBX = modulo p[cite: 1]
   0x401e92:    sub    ebx,DWORD PTR [edi+0x14]             ; EBX = p - Q.y2[cite: 1]
   0x401e95:    cmp    ebx,ecx                             ; Test if P.y2 == -Q.y2 mod p[cite: 1]
   0x401e97:    jne    0x401ea6                            ; If not, standard geometric addition[cite: 1]
   0x401e99:    mov    ebx,ebp                             ; EBX = modulo p[cite: 1]
   0x401e9b:    sub    ebx,DWORD PTR [edi+0x18]             ; EBX = p - Q.z2[cite: 1]
   0x401e9e:    cmp    ebx,edx                             ; Test if P.z2 == -Q.z2 mod p[cite: 1]
   0x401ea0:    je     0x401f65                            ; If P == -Q, result is point at infinity (0)[cite: 1]
   0x401ea6:    add    esi,0x4                             ; ESI advances to coordinates P[cite: 1]
   0x401ea9:    add    edi,0x4                             ; EDI advances to coordinates Q[cite: 1]
   0x401eac:    mov    ebx,0x404320                        ; Temporary buffer for ECC computations[cite: 1]
   0x401eb1:    xchg   edi,esi                             ; Exchange point pointers[cite: 1]
   0x401eb3:    call   0x402267                            ; Modular subtraction: EBX = P - Q mod p[cite: 1]
   0x401eb8:    add    edi,0xc                             ; Advance to next field in ECC structure[cite: 1]
   0x401ebb:    add    esi,0xc                             ; Advance to next field[cite: 1]
   0x401ebe:    sub    ebx,0x10                            ; Adjust temporary buffer pointer[cite: 1]
   0x401ec1:    call   0x402267                            ; Modular subtraction on subsequent components[cite: 1]
   0x401ec6:    lea    esi,[ebx+0x10]                      ; ESI points to intermediate result[cite: 1]
   0x401ec9:    add    ebx,0x20                            ; Allocate space in temporary buffer[cite: 1]
   0x401ecc:    call   0x402339                            ; Multiply and reduce modularly per curve constants[cite: 1]
   0x401ed1:    lea    esi,[ebx-0x20]                      ; Step back source address[cite: 1]
   0x401ed4:    mov    edi,ebx                             ; EDI = workspace area[cite: 1]
   0x401ed6:    add    ebx,0x10                            ; Advance destination pointer[cite: 1]
   0x401ed9:    call   0x402292                            ; Full modular multiplication: ESI * EDI mod p[cite: 1]
   0x401ede:    mov    esi,ebx                             ; Load intermediate product[cite: 1]
   0x401ee0:    mov    edi,ebx                             ; Source = Destination (Modular squaring)[cite: 1]
   0x401ee2:    add    ebx,0x10                            ; Advance buffer[cite: 1]
   0x401ee5:    call   0x402292                            ; Calculate power / modular squaring[cite: 1]
   0x401eea:    mov    edi,DWORD PTR [esp+0x24]            ; Restore pointer P[cite: 1]
   0x401eee:    mov    esi,ebx                             ; ESI = temporary result[cite: 1]
   0x401ef0:    add    edi,0x4                             ; Alignment on P.x[cite: 1]
   0x401ef3:    sub    ebx,0x20                            ; Reposition EBX[cite: 1]
   0x401ef6:    call   0x402267                            ; Modular subtraction to obtain new X3 coordinate[cite: 1]
   0x401efb:    mov    eax,DWORD PTR [edi]                 ; Load result X3[cite: 1]
   0x401efd:    mov    ecx,DWORD PTR [edi+0x4]              ; Load component Y3[cite: 1]
   0x401f00:    mov    edx,DWORD PTR [edi+0x8]              ; Load component Z3[cite: 1]
   0x401f03:    mov    DWORD PTR [ebx+0x20],eax            ; Store X3 in destination point[cite: 1]
   0x401f06:    mov    DWORD PTR [ebx+0x24],ecx            ; Store Y3 in destination point[cite: 1]
   0x401f09:    mov    DWORD PTR [ebx+0x28],edx            ; Store Z3 in destination point[cite: 1]
   0x401f0c:    mov    edi,DWORD PTR [esp+0x28]            ; Load point Q[cite: 1]
   0x401f10:    mov    esi,ebx                             ; Load current buffer[cite: 1]
   0x401f12:    add    edi,0x4                             ; Align on Q.x[cite: 1]
   0x401f15:    call   0x402267                            ; Calculate difference for Y3 coordinate[cite: 1]
   0x401f1a:    mov    edi,ebx                             ; EDI points to intermediate result[cite: 1]
   0x401f1c:    lea    esi,[ebx+0x20]                      ; ESI points to intermediate point[cite: 1]
   0x401f1f:    mov    ebx,esi                             ; Update EBX[cite: 1]
   0x401f21:    call   0x402267                            ; Finalize curve addition formula[cite: 1]
   0x401f26:    mov    esi,ebx                             ; ESI = computed point[cite: 1]
   0x401f28:    lea    edi,[ebx-0x10]                      ; EDI = temporary target[cite: 1]
   0x401f2b:    sub    ebx,0x30                            ; Step back EBX in work stack[cite: 1]
   0x401f2e:    call   0x402292                            ; Final multiplication of projective coordinates[cite: 1]
   0x401f33:    mov    esi,ebx                             ; ESI = sum coordinates[cite: 1]
   0x401f35:    mov    edi,DWORD PTR [esp+0x24]            ; Restore first parameter P[cite: 1]
   0x401f39:    mov    ebx,DWORD PTR [esp+0x28]            ; Restore second parameter Q (destination)[cite: 1]
   0x401f3d:    add    edi,0x10                            ; Pointer to second half of point P[cite: 1]
   0x401f40:    add    ebx,0x10                            ; Pointer to second half of point Q[cite: 1]
   0x401f43:    call   0x402267                            ; Final adjustment mod p[cite: 1]
   0x401f48:    mov    eax,DWORD PTR [esi+0x10]             ; Load final projective component X[cite: 1]
   0x401f4b:    mov    ecx,DWORD PTR [esi+0x14]             ; Load final projective component Y[cite: 1]
   0x401f4e:    mov    edx,DWORD PTR [esi+0x18]             ; Load final projective component Z[cite: 1]
   0x401f51:    mov    DWORD PTR [ebx-0x10],0x1             ; Mark receptacle point as valid (non-infinity)[cite: 1]
   0x401f58:    mov    DWORD PTR [ebx-0xc],eax             ; Store resulting X coordinate[cite: 1]
   0x401f5b:    mov    DWORD PTR [ebx-0x8],ecx             ; Store resulting Y coordinate[cite: 1]
   0x401f5e:    mov    DWORD PTR [ebx-0x4],edx             ; Store resulting Z coordinate[cite: 1]
   0x401f61:    popa                                       ; Restore registers[cite: 1]
   0x401f62:    ret    0x8                                 ; Return from ECC point addition[cite: 1]
   0x401f65:    and    DWORD PTR [edi],0x0                 ; Set resulting point to point at infinity (P + (-P) = 0)[cite: 1]
   0x401f68:    jmp    0x401f61                            ; End[cite: 1]
   0x401f6a:    mov    eax,DWORD PTR [esi]                 ; Copy P to Q (case Q = 0): load flag[cite: 1]
   0x401f6c:    mov    ebx,DWORD PTR [esi+0x4]              ; Load P.x[cite: 1]
   0x401f6f:    mov    ecx,DWORD PTR [esi+0x8]              ; Load P.y[cite: 1]
   0x401f72:    mov    edx,DWORD PTR [esi+0xc]              ; Load P.z[cite: 1]
   0x401f75:    mov    DWORD PTR [edi],eax                 ; Copy flag to Q[cite: 1]
   0x401f77:    mov    DWORD PTR [edi+0x4],ebx             ; Copy Q.x = P.x[cite: 1]
   0x401f7a:    mov    DWORD PTR [edi+0x8],ecx             ; Copy Q.y = P.y[cite: 1]
   0x401f7d:    mov    DWORD PTR [edi+0xc],edx             ; Copy Q.z = P.z[cite: 1]
   0x401f80:    mov    ebx,DWORD PTR [esi+0x10]             ; Load P.x2[cite: 1]
   0x401f83:    mov    ecx,DWORD PTR [esi+0x14]             ; Load P.y2[cite: 1]
   0x401f86:    mov    edx,DWORD PTR [esi+0x18]             ; Load P.z2[cite: 1]
   0x401f89:    mov    DWORD PTR [edi+0x10],ebx             ; Copy Q.x2 = P.x2[cite: 1]
   0x401f8c:    mov    DWORD PTR [edi+0x14],ecx             ; Copy Q.y2 = P.y2[cite: 1]
   0x401f8f:    mov    DWORD PTR [edi+0x18],edx             ; Copy Q.z2 = P.z2[cite: 1]
   0x401f92:    jmp    0x401f61                            ; End copy[cite: 1]
   0x401f94:    push   edi                                 ; Empirical point doubling (P == Q): push point Q[cite: 1]
   0x401f95:    push   esi                                 ; Push point P[cite: 1]
   0x401f96:    call   0x401f9d                            ; Call point doubling routine [2]P[cite: 1]
   0x401f9b:    jmp    0x401f61                            ; End[cite: 1]
   0x401f9d:    pusha                                      ; ECC point doubling routine [2]P[cite: 1]
   0x401f9e:    mov    esi,DWORD PTR [esp+0x24]            ; Load point P[cite: 1]
   0x402082:    and    DWORD PTR [edi],0x0                 ; Point at infinity in case of error/null point[cite: 1]
   0x402085:    jmp    0x40207e                            ; Exit[cite: 1]
   0x402087:    pusha                                      ; Coordinate conversion / projection routine[cite: 1]
   0x402088:    mov    esi,DWORD PTR [esp+0x24]            ; Pointer to source point[cite: 1]
   0x40208c:    xor    ecx,ecx                             ; ECX = 0 (Carry accumulator)[cite: 1]
   0x40208e:    add    esi,0x4                             ; Advance to X coordinate[cite: 1]
   0x402091:    xor    ebp,ebp                             ; EBP = 0 (High-order product)[cite: 1]
   0x402093:    mov    eax,DWORD PTR [esi]                 ; EAX = X.part1[cite: 1]
   0x402095:    mul    DWORD PTR ds:0x40409c               ; Multiply by field constant (p)[cite: 1]
   0x40209b:    add    eax,DWORD PTR [esi+0x4]              ; Add X.part2 to low product[cite: 1]
   0x40209e:    adc    ecx,edx                             ; Propagate carry into ECX[cite: 1]
   0x4020a0:    mul    DWORD PTR ds:0x40409c               ; Multiply again by modulo p[cite: 1]
   0x4020a6:    mov    edi,eax                             ; EDI = low-order temporary result[cite: 1]
   0x4020a8:    mov    ebx,edx                             ; EBX = high-order temporary result[cite: 1]
   0x4020aa:    mov    eax,ecx                             ; EAX = accumulated carry[cite: 1]
   0x4020ac:    mul    DWORD PTR ds:0x40409c               ; Multiply carry by p[cite: 1]
   0x4020b2:    add    eax,ebx                             ; Combine partial results[cite: 1]
   0x4020b4:    adc    ebp,edx                             ; Accumulate into EBP with carry[cite: 1]
   0x4020b6:    add    edi,DWORD PTR [esi+0x8]              ; Add X.part3[cite: 1]
   0x4020b9:    adc    eax,0x0                             ; Propagate carry[cite: 1]
   0x4020bc:    adc    ebp,0x0                             ; Propagate carry to EBP[cite: 1]
   0x4020bf:    mov    esi,DWORD PTR [esp+0x28]            ; Destination pointer[cite: 1]
   0x4020c3:    mov    DWORD PTR [esi],edi                 ; Store dword 0 of projected point[cite: 1]
   0x4020c5:    mov    DWORD PTR [esi+0x4],eax             ; Store dword 1[cite: 1]
   0x4020c8:    mov    DWORD PTR [esi+0x8],ebp             ; Store dword 2[cite: 1]
   0x4020cb:    and    DWORD PTR [esi+0xc],0x0             ; Zero out high-order dword (padding/sign)[cite: 1]
   0x4020cf:    popa                                       ; Restore registers[cite: 1]
   0x4020d0:    ret    0x8                                 ; Return from projection[cite: 1]
   0x4020d3:    int3                                       ; Alignment / Padding NOP instruction[cite: 1]




   0x402180:    pusha                                      ; 64-bit x 64-bit -&amp;gt; 128-bit multiplication routine[cite: 1]
   0x402181:    mov    esi,DWORD PTR [esp+0x24]            ; Operand A (64 bits: [ESI+4]:[ESI])[cite: 1]
   0x402185:    mov    edi,DWORD PTR [esp+0x28]            ; Operand B (64 bits: [EDI+4]:[EDI])[cite: 1]
   0x402189:    mov    eax,DWORD PTR [esi]                 ; EAX = A.low[cite: 1]
   0x40218b:    mul    DWORD PTR [edi]                     ; EDX:EAX = A.low * B.low[cite: 1]
   0x40218d:    mov    ebx,eax                             ; EBX = R0 (lowest 32 bits)[cite: 1]
   0x40218f:    mov    ebp,edx                             ; EBP = Intermediate carry[cite: 1]
   0x402191:    xor    ecx,ecx                             ; ECX = 0 (High-order accumulator)[cite: 1]
   0x402193:    mov    eax,DWORD PTR [esi]                 ; EAX = A.low[cite: 1]
   0x402195:    mul    DWORD PTR [edi+0x4]                 ; EDX:EAX = A.low * B.high[cite: 1]
   0x402198:    add    ebp,eax                             ; Accumulate into dword 1[cite: 1]
   0x40219a:    adc    ecx,edx                             ; Propagate carry to dword 2[cite: 1]
   0x40219c:    mov    eax,DWORD PTR [esi+0x4]              ; EAX = A.high[cite: 1]
   0x40219f:    mul    DWORD PTR [edi]                     ; EDX:EAX = A.high * B.low[cite: 1]
   0x4021a1:    add    ebp,eax                             ; Accumulate into dword 1[cite: 1]
   0x4021a3:    adc    ecx,edx                             ; Propagate carry to dword 2[cite: 1]
   0x4021a5:    mov    eax,DWORD PTR [esp+0x2c]            ; Destination pointer (128 bits)[cite: 1]
   0x4021a9:    mov    DWORD PTR [eax],ebx                 ; Save dword 0 (R0)[cite: 1]
   0x4021ab:    mov    ebx,ebp                             ; EBX = R1 (dword 1)[cite: 1]
   0x4021ad:    mov    eax,DWORD PTR [esi+0x4]              ; EAX = A.high[cite: 1]
   0x4021b0:    adc    ebp,ebp                             ; Save carry flag[cite: 1]
   0x4021b2:    mul    DWORD PTR [edi+0x4]                 ; EDX:EAX = A.high * B.high[cite: 1]
   0x4021b5:    and    ebp,0x1                             ; Extract carry bit[cite: 1]
   0x4021b8:    add    ecx,eax                             ; Accumulate into dword 2[cite: 1]
   0x4021ba:    adc    ebp,edx                             ; Accumulate into dword 3 (R3)[cite: 1]
   0x4021bc:    mov    eax,DWORD PTR [esp+0x2c]            ; Destination[cite: 1]
   0x4021c0:    mov    DWORD PTR [eax+0x4],ebx             ; Save dword 1 (R1)[cite: 1]
   0x4021c3:    mov    DWORD PTR [eax+0x8],ecx             ; Save dword 2 (R2)[cite: 1]
   0x4021c6:    mov    DWORD PTR [eax+0xc],ebp             ; Save dword 3 (R3)[cite: 1]
   0x4021c9:    popa                                       ; Restore registers[cite: 1]
   0x4021ca:    ret    0xc                                 ; End of 64x64-&amp;gt;128 multiplication[cite: 1]




   0x4021cd:    pusha                                      ; 128-bit mod p modular reduction routine[cite: 1]
   0x4021ce:    mov    esi,DWORD PTR [esp+0x24]            ; Pointer to 128-bit number to reduce[cite: 1]
   0x4021d2:    mov    edi,0x404360                        ; Temporary computation buffer[cite: 1]
   0x4021d7:    mov    ecx,DWORD PTR [esi]                 ; Load dword 0[cite: 1]
   0x4021d9:    mov    edx,DWORD PTR [esi+0x4]              ; Load dword 1[cite: 1]
   0x4021dc:    xor    ebx,ebx                             ; EBX = 0 (dword 2 accumulator)[cite: 1]
   0x4021de:    mov    eax,DWORD PTR [esi+0x8]              ; Load dword 2[cite: 1]
   0x4021e1:    or     eax,DWORD PTR [esi+0xc]              ; Test if high part (dwords 2 and 3) is zero[cite: 1]
   0x4021e4:    je     0x402201                            ; If high part is zero, proceed to final subtraction[cite: 1]
   0x4021e6:    lea    eax,[esi+0x8]                       ; EAX points to high part[cite: 1]
   0x4021e9:    push   edi                                 ; Product destination[cite: 1]
   0x4021ea:    push   0x4040e0                            ; Reduction constant (2^64 mod p)[cite: 1]
   0x4021ef:    push   eax                                 ; High part[cite: 1]
   0x4021f0:    call   0x402180                            ; Multiply high part by (2^64 mod p)[cite: 1]
   0x4021f5:    add    ecx,DWORD PTR [edi]                 ; Re-inject product result into dword 0[cite: 1]
   0x4021f7:    adc    edx,DWORD PTR [edi+0x4]              ; Re-inject with carry into dword 1[cite: 1]
   0x4021fa:    adc    ebx,0x0                             ; Accumulate global carry[cite: 1]
   0x4021fd:    mov    esi,edi                             ; Reduction loop[cite: 1]
   0x4021ff:    jmp    0x4021de                            ; Re-evaluate if high part is zero[cite: 1]
   0x402201:    sub    ecx,DWORD PTR ds:0x40403c           ; Subtract low part of modulo p[cite: 1]
   0x402207:    sbb    edx,DWORD PTR ds:0x404040           ; Subtract high part of modulo p with borrow[cite: 1]
   0x40220d:    sbb    ebx,0x0                             ; Subtract global borrow[cite: 1]
   0x402210:    jae    0x402201                            ; As long as result &amp;gt;= p, continue subtracting p[cite: 1]
   0x402212:    add    ecx,DWORD PTR ds:0x40403c           ; Final adjustment: add p back in case of negative underflow[cite: 1]
   0x402218:    adc    edx,DWORD PTR ds:0x404040           ; Restore exact modular value into [EDX:ECX][cite: 1]
   0x40221e:    mov    edi,DWORD PTR [esp+0x28]            ; Pointer to destination (reduced 64 bits)[cite: 1]
   0x402222:    mov    DWORD PTR [edi],ecx                 ; Store reduced dword 0[cite: 1]
   0x402224:    mov    DWORD PTR [edi+0x4],edx             ; Store reduced dword 1[cite: 1]
   0x402227:    popa                                       ; Restore registers[cite: 1]
   0x402228:    ret    0x8                                 ; End of modular reduction[cite: 1]




   0x402230:   push   eax                                 ; 3-component modular addition: [EBX] = ([ESI] + [EDI]) mod ebp
   0x402231:   push   ecx                                 ; Save ECX
   0x402232:   push   edx                                 ; Save EDX
   0x402233:   mov    eax,DWORD PTR [esi]                 ; Load component 0 of A
   0x402235:   mov    edx,DWORD PTR [esi+0x4]              ; Load component 1 of A
   0x402238:   mov    ecx,DWORD PTR [esi+0x8]              ; Load component 2 of A
   0x40223b:   add    eax,DWORD PTR [edi]                 ; A0 + B0
   0x40223d:   jb     0x402243                            ; If carry (overflow) -&amp;gt; requires mod p reduction
   0x40223f:   cmp    eax,ebp                             ; Compare result to modulo p (EBP)
   0x402241:   jb     0x402245                            ; If lower than p, no reduction required
   0x402243:   sub    eax,ebp                             ; Reduction: A0 = (A0 + B0) - p
   0x402245:   add    edx,DWORD PTR [edi+0x4]              ; A1 + B1
   0x402248:   jb     0x40224e                            ; If carry -&amp;gt; mod p reduction
   0x40224a:   cmp    edx,ebp                             ; Compare to modulo p
   0x40224c:   jb     0x402250                            ; If lower than p, continue
   0x40224e:   sub    edx,ebp                             ; Reduction: A1 = (A1 + B1) - p
   0x402250:   add    ecx,DWORD PTR [edi+0x8]              ; A2 + B2
   0x402253:   jb     0x402259                            ; If carry -&amp;gt; mod p reduction
   0x402255:   cmp    ecx,ebp                             ; Compare to modulo p
   0x402257:   jb     0x40225b                            ; If lower than p, continue
   0x402259:   sub    ecx,ebp                             ; Reduction: A2 = (A2 + B2) - p
   0x40225b:   mov    DWORD PTR [ebx],eax                 ; Store result R0 in EBX
   0x40225d:   mov    DWORD PTR [ebx+0x4],edx             ; Store result R1 in EBX+4
   0x402260:   mov    DWORD PTR [ebx+0x8],ecx             ; Store result R2 in EBX+8
   0x402263:   pop    edx                                 ; Restore EDX
   0x402264:   pop    ecx                                 ; Restore ECX
   0x402265:   pop    eax                                 ; Restore EAX
   0x402266:   ret                                        ; End of modular addition



   0x402267:   push   eax                                 ; 3-component modular subtraction: [EBX] = ([ESI] - [EDI]) mod ebp
   0x402268:   push   ecx                                 ; Save ECX
   0x402269:   push   edx                                 ; Save EDX
   0x40226a:   mov    eax,DWORD PTR [esi]                 ; Load A0
   0x40226c:   mov    edx,DWORD PTR [esi+0x4]              ; Load A1
   0x40226f:   mov    ecx,DWORD PTR [esi+0x8]              ; Load A2
   0x402272:   sub    eax,DWORD PTR [edi]                 ; A0 - B0
   0x402274:   jae    0x402278                            ; If no borrow (result &amp;gt;= 0), continue
   0x402276:   add    eax,ebp                             ; Modular compensation: if &amp;lt; 0, add p (EBP)
   0x402278:   sub    edx,DWORD PTR [edi+0x4]              ; A1 - B1
   0x40227b:   jae    0x40227f                            ; If &amp;gt;= 0, continue
   0x40227d:   add    edx,ebp                             ; Add p
   0x40227f:   sub    ecx,DWORD PTR [edi+0x8]              ; A2 - B2
   0x402282:   jae    0x402286                            ; If &amp;gt;= 0, continue
   0x402284:   add    ecx,ebp                             ; Add p
   0x402286:   mov    DWORD PTR [ebx],eax                 ; Write R0
   0x402288:   mov    DWORD PTR [ebx+0x4],edx             ; Write R1
   0x40228b:   mov    DWORD PTR [ebx+0x8],ecx             ; Write R2
   0x40228e:   pop    edx                                 ; Restore EDX
   0x40228f:   pop    ecx                                 ; Restore ECX
   0x402290:   pop    eax                                 ; Restore EAX
   0x402291:   ret                                        ; End of modular subtraction
   0x402292:   push   eax                                 ; Full 3-word modular multiplication: [EBX] = ([ESI] * [EDI]) mod ebp
   0x402293:   push   ecx                                 ; Save ECX
   0x402294:   push   edx                                 ; Save EDX
   0x402295:   mov    eax,DWORD PTR [esi]                 ; Load A0
   0x402297:   mul    DWORD PTR [edi+0x8]                 ; EDX:EAX = A0 * B2
   0x40229a:   div    ebp                                 ; Remainder in EDX = (A0 * B2) mod ebp
   0x40229c:   mov    ecx,edx                             ; ECX = Remainder 1
   0x40229e:   mov    eax,DWORD PTR [esi+0x4]              ; Load A1
   0x4022a1:   mul    DWORD PTR [edi+0x4]                 ; EDX:EAX = A1 * B1
   0x4022a4:   div    ebp                                 ; Remainder in EDX = (A1 * B1) mod ebp
   0x4022a6:   add    ecx,edx                             ; ECX = Remainder 1 + Remainder 2
   0x4022a8:   jb     0x4022ae                            ; Overflow -&amp;gt; reduction
   0x4022aa:   cmp    ecx,ebp                             ; Compare to modulo p
   0x4022ac:   jb     0x4022b0                            ; If &amp;lt; p, continue
   0x4022ae:   sub    ecx,ebp                             ; ECX = ECX - p
   0x4022b0:   mov    eax,DWORD PTR [esi+0x8]              ; Load A2
   0x4022b3:   mul    DWORD PTR [edi]                     ; EDX:EAX = A2 * B0
   0x4022b5:   div    ebp                                 ; Remainder in EDX
   0x4022b7:   add    ecx,edx                             ; Accumulate modular remainder
   0x4022b9:   jb     0x4022bf                            ; Overflow -&amp;gt; reduction
   0x4022bb:   cmp    ecx,ebp                             ; Compare to modulo p
   0x4022bd:   jb     0x4022c1                            ; If &amp;lt; p, continue
   0x4022bf:   sub    ecx,ebp                             ; ECX = ECX - p
   0x4022c1:   mov    DWORD PTR [ebx],ecx                 ; Write component R0 of product
   0x4022c3:   mov    eax,DWORD PTR [esi]                 ; Load A0
   0x4022c5:   mul    DWORD PTR [edi]                     ; EDX:EAX = A0 * B0
   0x4022c7:   div    ebp                                 ; Remainder in EDX
   0x4022c9:   mov    ecx,edx                             ; ECX = Remainder
   0x4022cb:   add    ecx,edx                             ; Doubling remainder
   0x4022cd:   jb     0x4022d3                            ; Overflow -&amp;gt; reduction
   0x4022cf:   cmp    ecx,ebp                             ; Compare to p
   0x4022d1:   jb     0x4022d5                            ; If &amp;lt; p, continue
   0x4022d3:   sub    ecx,ebp                             ; ECX = ECX - p
   0x4022d5:   mov    eax,DWORD PTR [esi+0x4]              ; Load A1
   0x4022d8:   mul    DWORD PTR [edi+0x8]                 ; EDX:EAX = A1 * B2
   0x4022db:   div    ebp                                 ; Remainder in EDX
   0x4022dd:   add    ecx,edx                             ; Accumulate remainder
   0x4022df:   jb     0x4022e5                            ; Overflow -&amp;gt; reduction
   0x4022e1:   cmp    ecx,ebp                             ; Compare to p
   0x4022e3:   jb     0x4022e7                            ; If &amp;lt; p, continue
   0x4022e5:   sub    ecx,ebp                             ; ECX = ECX - p
   0x4022e7:   mov    eax,DWORD PTR [esi+0x8]              ; Load A2
   0x4022ea:   mul    DWORD PTR [edi+0x4]                 ; EDX:EAX = A2 * B1
   0x4022ed:   div    ebp                                 ; Remainder in EDX
   0x4022ef:   add    ecx,edx                             ; Accumulate remainder
   0x4022f1:   jb     0x4022f7                            ; Overflow -&amp;gt; reduction
   0x4022f3:   cmp    ecx,ebp                             ; Compare to p
   0x4022f5:   jb     0x4022f9                            ; If &amp;lt; p, continue
   0x4022f7:   sub    ecx,ebp                             ; ECX = ECX - p
   0x4022f9:   mov    DWORD PTR [ebx+0x4],ecx             ; Write component R1 of product
   0x4022fc:   mov    eax,DWORD PTR [esi+0x4]              ; Load A1
   0x4022ff:   mul    DWORD PTR [edi]                     ; EDX:EAX = A1 * B0
   0x402301:   div    ebp                                 ; Remainder in EDX
   0x402303:   mov    ecx,edx                             ; ECX = Remainder
   0x402305:   mov    eax,DWORD PTR [esi]                 ; Load A0
   0x402307:   mul    DWORD PTR [edi+0x4]                 ; EDX:EAX = A0 * B1
   0x40230a:   div    ebp                                 ; Remainder in EDX
   0x40230c:   add    ecx,edx                             ; Accumulate
   0x40230e:   jb     0x402314                            ; Overflow -&amp;gt; reduction
   0x402310:   cmp    ecx,ebp                             ; Compare to p
   0x402312:   jb     0x402316                            ; If &amp;lt; p, continue
   0x402314:   sub    ecx,ebp                             ; ECX = ECX - p
   0x402316:   add    ecx,ecx                             ; Double result
   0x402318:   jb     0x40231e                            ; Overflow -&amp;gt; reduction
   0x40231a:   cmp    ecx,ebp                             ; Compare to p
   0x40231c:   jb     0x402320                            ; If &amp;lt; p, continue
   0x40231e:   sub    ecx,ebp                             ; ECX = ECX - p
   0x402320:   mov    eax,DWORD PTR [esi+0x8]              ; Load A2
   0x402323:   mul    DWORD PTR [edi+0x8]                 ; EDX:EAX = A2 * B2
   0x402326:   div    ebp                                 ; Remainder in EDX
   0x402328:   add    ecx,edx                             ; Accumulate
   0x40232a:   jb     0x402330                            ; Overflow -&amp;gt; reduction
   0x40232c:   cmp    ecx,ebp                             ; Compare to p
   0x40232e:   jb     0x402332                            ; If &amp;lt; p, continue
   0x402330:   sub    ecx,ebp                             ; ECX = ECX - p
   0x402332:   mov    DWORD PTR [ebx+0x8],ecx             ; Write component R2 of modular product
   0x402335:   pop    edx                                 ; Restore EDX
   0x402336:   pop    ecx                                 ; Restore ECX
   0x402337:   pop    eax                                 ; Restore EAX
   0x402338:   ret                                        ; End of modular multiplication




   0x402339:   pusha                                      ; Routine for inversion/transformation of mod p constants
   0x40233a:   mov    eax,DWORD PTR [esi]                 ; Load A0
   0x40233c:   mul    DWORD PTR ds:0x4040f4               ; Multiply by curve constant K0
   0x402342:   div    ebp                                 ; Modulo p (EBP)
   0x402344:   mov    DWORD PTR [ebx],edx                 ; Store R0 = (A0 * K0) mod p
   0x402346:   mov    eax,DWORD PTR [esi+0x4]              ; Load A1
   0x402349:   mul    DWORD PTR ds:0x4040f0               ; Multiply by curve constant K1
   0x40234f:   div    ebp                                 ; Modulo p
   0x402351:   mov    DWORD PTR [ebx+0x4],edx             ; Store R1 = (A1 * K1) mod p
   0x402354:   mov    eax,DWORD PTR [esi+0x8]              ; Load A2
   0x402357:   mov    DWORD PTR [ebx+0x8],eax             ; R2 = A2
   0x40235a:   mov    edi,ebx                             ; EDI points to the intermediate result
   0x40235c:   mov    ebx,0x404370                        ; Target buffer
   0x402361:   call   0x402292                            ; Full modular multiplication
   0x402366:   xchg   edi,ebx                             ; Swap buffer pointers
   0x402368:   mov    eax,DWORD PTR [edi]                 ; Load dword 0
   0x40236a:   mul    DWORD PTR ds:0x4040f4               ; Multiply by K0
   0x402370:   div    ebp                                 ; Modulo p
   0x402372:   mov    DWORD PTR [edi],edx                 ; Update dword 0
   0x402374:   mov    eax,DWORD PTR [edi+0x4]              ; Load dword 1
   0x402377:   mul    DWORD PTR ds:0x4040f0               ; Multiply by K1
   0x40237d:   div    ebp                                 ; Modulo p
   0x40237f:   mov    DWORD PTR [edi+0x4],edx             ; Update dword 1
   0x402382:   mov    eax,DWORD PTR [edi+0x4]              ; Load dword 1
   0x402385:   mul    DWORD PTR [esi]                     ; Multiply by A0
   0x402387:   div    ebp                                 ; Modulo p
   0x402389:   mov    ecx,edx                             ; ECX = Remainder
   0x40238b:   mov    eax,DWORD PTR [esi+0x4]              ; Load A1
   0x40238e:   mul    DWORD PTR [edi]                     ; Multiply by B0
   0x402390:   div    ebp                                 ; Modulo p
   0x402392:   add    ecx,edx                             ; Accumulate
   0x402394:   jb     0x40239a                            ; Overflow -&amp;gt; reduction
   0x402396:   cmp    ecx,ebp                             ; Compare to p
   0x402398:   jb     0x40239c                            ; If &amp;lt; p, continue
   0x40239a:   sub    ecx,ebp                             ; ECX = ECX - p
   0x40239c:   add    ecx,ecx                             ; Doubling
   0x40239e:   jb     0x4023a4                            ; Overflow -&amp;gt; reduction
   0x4023a0:   cmp    ecx,ebp                             ; Compare to p
   0x4023a2:   jb     0x4023a6                            ; If &amp;lt; p, continue
   0x4023a4:   sub    ecx,ebp                             ; ECX = ECX - p
   0x4023a6:   mov    eax,DWORD PTR [esi+0x8]              ; Load A2
   0x4023a9:   mul    DWORD PTR [edi+0x8]                 ; Multiply by B2
   0x4023ac:   div    ebp                                 ; Modulo p
   0x4023ae:   add    ecx,edx                             ; Accumulate
   0x4023b0:   jb     0x4023b6                            ; Overflow -&amp;gt; reduction
   0x4023b2:   cmp    ecx,ebp                             ; Compare to p
   0x4023b4:   jb     0x4023b8                            ; If &amp;lt; p, continue
   0x4023b6:   sub    ecx,ebp                             ; ECX = ECX - p
   0x4023b8:   mov    eax,ecx                             ; EAX = scalar value to invert
   0x4023ba:   call   0x4023dd                            ; Compute modular inverse: EAX = A^(-1) mod p
   0x4023bf:   mov    ecx,eax                             ; ECX = computed modular inverse
   0x4023c1:   mul    DWORD PTR [edi]                     ; Multiply B0 by modular inverse
   0x4023c3:   div    ebp                                 ; Modulo p
   0x4023c5:   mov    DWORD PTR [ebx],edx                 ; Store inverted dword 0
   0x4023c7:   mov    eax,DWORD PTR [edi+0x4]              ; Load B1
   0x4023ca:   mul    ecx                                 ; Multiply by modular inverse
   0x4023cc:   div    ebp                                 ; Modulo p
   0x4023ce:   mov    DWORD PTR [ebx+0x4],edx             ; Store inverted dword 1
   0x4023d1:   mov    eax,DWORD PTR [edi+0x8]              ; Load B2
   0x4023d4:   mul    ecx                                 ; Multiply by modular inverse
   0x4023d6:   div    ebp                                 ; Modulo p
   0x4023d8:   mov    DWORD PTR [ebx+0x8],edx             ; Store inverted dword 2
   0x4023db:   popa                                       ; Restore registers
   0x4023dc:   ret                                        ; End





   0x4023dd:   push   ebx                                 ; Extended Euclidean Algorithm: Modular inversion EAX^(-1) mod ebp
   0x4023de:   push   esi                                 ; Save ESI
   0x4023df:   push   edi                                 ; Save EDI
   0x4023e0:   cmp    eax,0x1                             ; Test if value is 0 or 1
   0x4023e3:   jbe    0x402413                            ; If EAX &amp;lt;= 1, inverse is the value itself (0 or 1)
   0x4023e5:   mov    esi,0x1                             ; ESI = Bézout coefficient x1 = 1
   0x4023ea:   mov    ecx,eax                             ; ECX = current value (A)
   0x4023ec:   xor    ebx,ebx                             ; EBX = Bézout coefficient x2 = 0
   0x4023ee:   mov    edi,ebp                             ; EDI = Modulo p
   0x4023f0:   mov    eax,edi                             ; EAX = EDI
   0x4023f2:   xor    edx,edx                             ; EDX = 0 for 64-bit division EDX:EAX
   0x4023f4:   div    ecx                                 ; EAX = Quotient (EDI / ECX), EDX = Remainder (EDI % ECX)
   0x4023f6:   test   edx,edx                             ; Is remainder zero? (End of Euclidean loop)
   0x4023f8:   je     0x40240b                            ; If Remainder == 0, end loop
   0x4023fa:   imul   eax,esi                             ; EAX = Quotient * x1
   0x4023fd:   sub    ebx,eax                             ; EBX = x2 - (Quotient * x1)
   0x4023ff:   mov    eax,esi                             ; EAX = x1
   0x402401:   mov    edi,ecx                             ; EDI = former divisor ECX
   0x402403:   mov    esi,ebx                             ; ESI = new coefficient x1 (EBX)
   0x402405:   mov    ecx,edx                             ; ECX = new divisor (Remainder EDX)
   0x402407:   mov    ebx,eax                             ; EBX = former x1
   0x402409:   jmp    0x4023f0                            ; Next iteration of Euclidean division
   0x40240b:   test   esi,esi                             ; Test if Bézout coefficient is negative
   0x40240d:   jge    0x402411                            ; If &amp;gt;= 0, valid result
   0x40240f:   add    esi,ebp                             ; If &amp;lt; 0, bring back to finite field: ESI = ESI + p (EBP)
   0x402411:   mov    eax,esi                             ; EAX = final computed modular inverse
   0x402413:   pop    edi                                 ; Restore EDI
   0x402414:   pop    esi                                 ; Restore ESI
   0x402415:   pop    ebx                                 ; Restore EBX
   0x402416:   ret                                        ; End of modular inversion

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  A. Summary of Key Steps of the Mechanism
&lt;/h4&gt;

&lt;p&gt;The binary does not merely compute an MD5 hash: it uses MD5 as an input block to feed an Elliptic Curve Cryptography (ECC) layer.&lt;/p&gt;

&lt;p&gt;MD5 Initialization and Hashing (block 0x401700 to 0x401e2c)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loading canonical MD5 constants (0x67452301, etc.).&lt;/li&gt;
&lt;li&gt;Splitting the message into 64-byte (0x40) chunks and executing the 4 rounds of non-linear compression (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;F&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
).&lt;/li&gt;
&lt;li&gt;Managing padding (adding the &lt;code&gt;0x80&lt;/code&gt; byte, zero-padding, and appending the total message length at the end).&lt;/li&gt;
&lt;li&gt;The resulting MD5 digest (16 bytes / 128 bits) is stored.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conversion and Validity Verification (block 0x401e30 to 0x4020d0)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The MD5 result is used to instantiate one or two points on an elliptic curve.&lt;/li&gt;
&lt;li&gt;The code extracts the 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;X&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;Y&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;Z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 coordinates of these points and performs geometric tests (checking whether the points lie on the curve or correspond to the point at infinity).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finite Field Arithmetic (underlying blocks 0x402087 to 0x402416)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is the underlying mathematical engine: it handles operations on large integers modulo 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (with the &lt;code&gt;ebp&lt;/code&gt; register acting as a pointer/modulus value).&lt;/li&gt;
&lt;li&gt;Modular Addition / Subtraction (0x402230, 0x402267).&lt;/li&gt;
&lt;li&gt;Coordinate Multiplication (0x402292).&lt;/li&gt;
&lt;li&gt;Modular Inversion via the Extended Euclidean Algorithm (0x4023dd).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Assembly Code Commentary
&lt;/h4&gt;

&lt;h5&gt;
  
  
  a. Phase 1: MD5 Implementation (0x401700 - 0x401e2c)
&lt;/h5&gt;

&lt;p&gt;0x401700 - 0x40173e: Context Setup&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Saving registers (&lt;code&gt;pusha&lt;/code&gt;), retrieving the buffer and its length. Initializing state registers 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 with canonical Little-Endian MD5 constants (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;0x401751 - 0x401d82: Compression Rounds&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Round 1 (0x401768): Computes 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;F&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∧&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∨&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;¬&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∧&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 using &lt;code&gt;not&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, adds the input word and sine constant via &lt;code&gt;lea&lt;/code&gt;, then applies a &lt;code&gt;rol&lt;/code&gt; rotation (shifts of 7, 12, 17, 22).&lt;/li&gt;
&lt;li&gt;Round 2 (0x401917): Computes 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∧&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∨&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∧&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;¬&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 with shifts of 5, 9, 14, 20.&lt;/li&gt;
&lt;li&gt;Round 3 (0x401ac6): Computes 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⊕&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⊕&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 with shifts of 4, 11, 16, 23.&lt;/li&gt;
&lt;li&gt;Round 4 (0x401c15): Computes 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;⊕&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;∨&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;¬&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 with shifts of 6, 10, 15, 21.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;0x401d84 - 0x401da6: Accumulation&lt;br&gt;
The updated values in 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;D&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 are added to the previous state variables, the input pointer advances by 64 bytes (&lt;code&gt;add esi, 0x40&lt;/code&gt;), and the loop repeats if necessary.&lt;/p&gt;

&lt;p&gt;0x401dab - 0x401e0f: Padding (MD5 Padding)&lt;br&gt;
Appending the terminator byte &lt;code&gt;0x80&lt;/code&gt; (&lt;code&gt;mov BYTE PTR [edi], 0x80&lt;/code&gt;), calculating alignment (&lt;code&gt;sub ecx, 0x37&lt;/code&gt;), filling with zeroes via &lt;code&gt;rep stos&lt;/code&gt;, and writing the 64-bit total length (&lt;code&gt;mul edx&lt;/code&gt; by 8).&lt;/p&gt;

&lt;p&gt;0x401e10 - 0x401e2c: Hash Extraction&lt;br&gt;
The 128-bit result is copied to the destination buffer passed as a parameter (&lt;code&gt;rep movs&lt;/code&gt;), and registers are restored.&lt;/p&gt;

&lt;h5&gt;
  
  
  b. Phase 2: Elliptic Curve Cryptography (0x401e30 - 0x4020d0)
&lt;/h5&gt;

&lt;p&gt;0x401e30 - 0x401ea0: Point Coordinate Verification&lt;br&gt;
Loads the coordinates of two ECC points (&lt;code&gt;esi&lt;/code&gt; and &lt;code&gt;edi&lt;/code&gt;) and compares them. It validates projective or affine coordinates (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;X&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;Y&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;Z&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
) by performing subtractions modulo 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (stored in &lt;code&gt;ebp&lt;/code&gt;, loaded from 0x40409c).&lt;/p&gt;

&lt;p&gt;0x401ea6 - 0x401f60: ECC Point Addition&lt;br&gt;
A series of &lt;code&gt;call&lt;/code&gt; instructions to mathematical subroutines executing point addition/doubling on the curve.&lt;/p&gt;

&lt;p&gt;0x401f9d - 0x40207e: Scalar Multiplication / Normalization&lt;br&gt;
Takes the computed ECC point and converts it from projective to affine coordinates.&lt;/p&gt;

&lt;h5&gt;
  
  
  c. Phase 3: Modular Arithmetic Engine (0x402087 - 0x402416)
&lt;/h5&gt;

&lt;p&gt;0x402180 - 0x4021ca: 64-bit × 64-bit multiplication with carry handling (&lt;code&gt;adc&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;0x402230 - 0x402266: Modular addition 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (if the result exceeds &lt;code&gt;ebp&lt;/code&gt;, &lt;code&gt;ebp&lt;/code&gt; is subtracted).&lt;/p&gt;

&lt;p&gt;0x402267 - 0x402291: Modular subtraction 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (if the result is negative, &lt;code&gt;ebp&lt;/code&gt; is added).&lt;/p&gt;

&lt;p&gt;0x402292 - 0x402338: Modular multiplication 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;B&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (uses the &lt;code&gt;div ebp&lt;/code&gt; instruction to reduce modulo at each step).&lt;/p&gt;

&lt;p&gt;0x4023dd - 0x402416: Modular inversion 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;−&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace allowbreak"&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathrm"&gt;mod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 based on the Extended Euclidean Algorithm (looping &lt;code&gt;div ecx&lt;/code&gt;, &lt;code&gt;imul&lt;/code&gt;, and adjusting with &lt;code&gt;add esi, ebp&lt;/code&gt; if negative).&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;
  
  
  C. Can this hash function be inverted?
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;It is mathematically and practically impossible to invert this function to recover the original input from the output result.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The function is &lt;strong&gt;one-way&lt;/strong&gt; (non-injective and irreversible) due to two major reasons:&lt;/p&gt;

&lt;h5&gt;
  
  
  a. Presence of a cryptographic hash (MD5)
&lt;/h5&gt;

&lt;p&gt;The first phase of the function (blocks &lt;code&gt;0x401700&lt;/code&gt; through &lt;code&gt;0x401e2c&lt;/code&gt;) is an exact implementation of the &lt;strong&gt;MD5&lt;/strong&gt; hashing algorithm.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Information Destruction (Overwriting):&lt;/strong&gt; The compression logical operations (
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;F&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="mpunct"&gt;,&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
) and bitwise rotations (&lt;code&gt;rol&lt;/code&gt;) scramble data, causing the loss of intermediate state values.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression/Collisions:&lt;/strong&gt; A hash function compresses input data of arbitrary size into a fixed 128-bit (16-byte) digest. Thus, an infinite number of possible inputs produce the exact same output (pigeonhole principle).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  b. Use of Elliptic Curve Cryptography (ECC)
&lt;/h5&gt;

&lt;p&gt;The second part of the code (blocks &lt;code&gt;0x401e30&lt;/code&gt; through &lt;code&gt;0x402416&lt;/code&gt;) processes the MD5 digest through elliptic curve arithmetic (scalar multiplications, operations modulo 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Elliptic Curve Discrete Logarithm Problem (ECDLP):&lt;/strong&gt; Even setting MD5 aside, if this function executes scalar multiplication of the form 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;×&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;G&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 (where 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is derived from your input and 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the resulting point on the curve), finding 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;k&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 from 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;P&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
 is the fundamental hard problem underlying modern public-key cryptography. It is considered computationally intractable in any realistic timeframe.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  c. How can the input be "recovered" then?
&lt;/h5&gt;

&lt;p&gt;Since you cannot &lt;strong&gt;invert&lt;/strong&gt; the equation mathematically, the only applicable methods are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Brute-force (or dictionary) attack:&lt;/strong&gt; Generating a massive volume of potential input candidates, running the function on each, and checking for matching outputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precomputed attack tables (e.g., Rainbow Tables):&lt;/strong&gt; Applicable only if the analyzed output relies strictly on the MD5 phase without external variable parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SMT Solvers / Symbolic Execution (e.g., Z3, angr):&lt;/strong&gt; If the input space is &lt;strong&gt;extremely short&lt;/strong&gt; (e.g., a 4 to 8 character key/serial), a logic solver may successfully solve the mathematical constraints; however, the path explosion caused by MD5 makes this very difficult.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;In summary:&lt;/strong&gt; You cannot directly compute the input via mathematical formula inversion. The only viable path is to &lt;strong&gt;guess the input and verify the match&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Epilogue
&lt;/h3&gt;

&lt;p&gt;The analysis of the hash function indicates that the easiest path to cracking this CrackMe is to solve the modular exponentiation equation by factoring the 64-bit modulus embedded in the program data. This will be covered in our next article on the topic.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>CrackMe Level 6</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Fri, 04 Sep 2026 01:55:02 +0000</pubDate>
      <link>https://dev.to/ddupard/crackme-level-6-1neb</link>
      <guid>https://dev.to/ddupard/crackme-level-6-1neb</guid>
      <description>&lt;h3&gt;
  
  
  1. Introduction
&lt;/h3&gt;

&lt;p&gt;Level 6 crackmes are the most difficult ones you can find on the crackmes.one website. If you search the site for Assembly crackmes with a difficulty of 6, you will only find 3:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhcqg32vrqckesm4oji9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhcqg32vrqckesm4oji9e.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this first example, we will take &lt;code&gt;chili_crackme_11_by_witeg&lt;/code&gt; by witeg.&lt;/p&gt;

&lt;p&gt;As usual, when approaching a crackme, we start with a &lt;code&gt;hexdump -C CrackMe11_wg.exe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00000000  4d 5a 00 00 00 00 00 00  00 00 00 00 50 45 00 00  |MZ..........PE..|
00000010  4c 01 02 00 46 53 47 21  00 00 00 00 00 00 00 00  |L...FSG!........|
00000020  e0 00 0f 01 0b 01 00 00  00 16 00 00 00 f0 00 00  |................|
00000030  00 00 00 00 54 01 00 00  00 10 00 00 0c 00 00 00  |....T...........|
00000040  00 00 40 00 00 10 00 00  00 02 00 00 04 00 00 00  |..@.............|
00000050  00 00 00 00 04 00 00 00  00 00 00 00 00 90 01 00  |................|
00000060  00 02 00 00 00 00 00 00  02 00 00 00 00 00 10 00  |................|
00000070  00 10 00 00 00 00 10 00  00 10 00 00 00 00 00 00  |................|
00000080  10 00 00 00 00 00 00 00  00 00 00 00 c4 8a 01 00  |................|
00000090  84 00 00 00 00 50 01 00  fc 09 00 00 00 00 00 00  |.....P..........|
000000a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000100  00 00 00 00 00 00 00 00  00 00 00 00 00 40 01 00  |.............@..|
00000110  00 10 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000120  00 00 00 00 00 00 00 00  e0 00 00 c0 00 00 00 00  |................|
00000130  00 00 00 00 00 40 00 00  00 50 01 00 45 3b 00 00  |.....@...P..E;..|

...

00003cb0  51 6d 9c 0a 28 c8 91 da  14 c0 ce 5c 6c 14 01 bb  |Qm..(......\l...|
00003cc0  fe f9 80 00 1c 8b 01 00  00 00 00 00 00 00 00 00  |................|
00003cd0  f2 01 00 00 1c 8b 01 00  00 00 00 00 00 00 00 00  |................|
00003ce0  00 00 00 00 00 00 00 00  00 00 00 00 00 10 40 00  |..............@.|
00003cf0  fc 59 41 00 70 30 40 00  00 00 00 00 0c 8b 41 00  |.YA.p0@.......A.|
00003d00  80 00 00 00 00 7d 00 00  ec 8a 41 00 e8 01 40 00  |.....}....A...@.|
00003d10  dc 01 40 00 de 01 40 00  00 10 40 00 26 8b 01 00  |..@...@...@.&amp;amp;...|
00003d20  34 8b 01 00 00 00 00 00  4c 6f 61 64 4c 69 62 72  |4.......LoadLibr|
00003d30  61 72 79 41 00 00 47 65  74 50 72 6f 63 41 64 64  |aryA..GetProcAdd|
00003d40  72 65 73 73 00                                    |ress.|
00003d45

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seeing immediately that it is a Windows executable, we run &lt;code&gt;readpe CrackMe11_wg.exe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DOS Header
    Magic number:                    0x5a4d (MZ)
    Bytes in last page:              0
    Pages in file:                   0
    Relocations:                     0
    Size of header in paragraphs:    0
    Minimum extra paragraphs:        0
    Maximum extra paragraphs:        17744
    Initial (relative) SS value:     0
    Initial SP value:                0x14c
    Initial IP value:                0x5346
    Initial (relative) CS value:     0x2147
    Address of relocation table:     0
    Overlay number:                  0
    OEM identifier:                  0x10b
    OEM information:                 0
    PE header offset:                0xc
COFF/File header
    Machine:                         0x14c IMAGE_FILE_MACHINE_I386
    Number of sections:              2
    Date/time stamp:                 558322502 (Fri, 11 Sep 1987 01:35:02 UTC)
    Symbol Table offset:             0
    Number of symbols:               0
    Size of optional header:         0xe0
    Characteristics:                 0x10f
    Characteristics names
                                         IMAGE_FILE_RELOCS_STRIPPED
                                         IMAGE_FILE_EXECUTABLE_IMAGE
                                         IMAGE_FILE_LINE_NUMS_STRIPPED
                                         IMAGE_FILE_LOCAL_SYMS_STRIPPED
                                         IMAGE_FILE_32BIT_MACHINE
Optional/Image header
    Magic number:                    0x10b (PE32)
    Linker major version:            0
    Linker minor version:            0
    Size of .text section:           0x1600
    Size of .data section:           0xf000
    Size of .bss section:            0
    Entrypoint:                      0x154
    Address of .text section:        0x1000
    Address of .data section:        0xc
    ImageBase:                       0x400000
    Alignment of sections:           0x1000
    Alignment factor:                0x200
    Major version of required OS:    4
    Minor version of required OS:    0
    Major version of image:          0
    Minor version of image:          0
    Major version of subsystem:      4
    Minor version of subsystem:      0
    Size of image:                   0x19000
    Size of headers:                 0x200
    Checksum:                        0
    Subsystem required:              0x2 (IMAGE_SUBSYSTEM_WINDOWS_GUI)
    DLL characteristics:             0
    DLL characteristics names
    Size of stack to reserve:        0x100000
    Size of stack to commit:         0x1000
    Size of heap space to reserve:   0x100000
    Size of heap space to commit:    0x1000

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we launch the debugger &lt;code&gt;winedbg --gdb CrackMe11_wg.exe&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;We immediately look for where the program is loaded and where its Entry Point is located:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;info sharedlibrary&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;From        To          Syms Read   Shared Object Library
0x5abb1000  0x5abb5010  Yes ()     /usr/lib/wine/wine
0xf74b6000  0xf76f08bc  Yes ()     /lib/i386-linux-gnu/libc.so.6
0xf7718000  0xf774ca18  Yes ()     /lib/ld-linux.so.2
0xf7401000  0xf74b5854  Yes ()     /usr/lib/wine/../i386-linux-gnu/wine/i386-unix/ntdll.so
0x00401000  0x00418b45  Yes (*)     /home/daniel/Desktop/LABO/CRACKME/Windows/6/1/CrackMe11_wg.exe
0x7bd11000  0x7bdbced0  Yes         /usr/lib/i386-linux-gnu/wine/i386-windows/ntdll.dll
0x7bb91000  0x7bbf43d8  Yes         /usr/lib/i386-linux-gnu/wine/i386-windows/kernel32.dll
0x7b651000  0x7b8e7cc0  Yes         /usr/lib/i386-linux-gnu/wine/i386-windows/kernelbase.dll

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;info file&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Symbols from "/home/daniel/Desktop/LABO/CRACKME/Windows/6/1/CrackMe11_wg.exe".
Remote target using gdb-specific protocol:
  `/home/daniel/Desktop/LABO/CRACKME/Windows/6/1/CrackMe11_wg.exe', file type pei-i386.
warning: Cannot find section for the entry point of /home/daniel/Desktop/LABO/CRACKME/Windows/6/1/CrackMe11_wg.exe.
  Entry point: 0x400154
  0x00401000 - 0x00415000 is 
  0x00415000 - 0x00418b45 is 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seeing that the Entry Point is at &lt;code&gt;0x400154&lt;/code&gt;, we set a breakpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;break *0x400154
continue

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which gives us the following instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   0x400154    xchg   dword ptr [0x418b08], esp
   0x40015a    popal 
   0x40015b    xchg   esp, eax                              ESP =&amp;gt; 0x31ff54, EAX =&amp;gt; 0x418b0c
   0x40015c    push   ebp
   0x40015d    movsb  byte ptr es:[edi], byte ptr [esi]
   0x40015e    mov    dh, 0x80                              DH =&amp;gt; 0x80
   0x400160    call   dword ptr [ebx]

   0x400162  ? jae    0x40015d                    &amp;lt;0x40015d&amp;gt;

   0x400164    xor    ecx, ecx            ECX =&amp;gt; 0
   0x400166    call   dword ptr [ebx]

   0x400168  ? jae    0x400180                    &amp;lt;0x400180&amp;gt;

   0x40016a    xor    eax, eax            EAX =&amp;gt; 0
   0x40016c    call   dword ptr [ebx]

   0x40016e  ? jae    0x40018f                    &amp;lt;0x40018f&amp;gt;

   0x400170    mov    dh, 0x80            DH =&amp;gt; 0x80
   0x400172    inc    ecx
   0x400173    mov    al, 0x10            AL =&amp;gt; 0x10
   0x400175    call   dword ptr [ebx]

   0x400177    adc    al, al
   0x400179  ? jae    0x400175                    &amp;lt;0x400175&amp;gt;

   0x40017b  ? jne    0x4001b7                    &amp;lt;0x4001b7&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could step through the instructions one by one, but there is often a better approach, which starts by running the program completely to see what happens.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;continue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Continuing.
0138:013c: loads DLL C:\windows\system32\GDI32.dll @7A640000 (2355200&amp;lt;7390&amp;gt;)
0138:013c: loads DLL C:\windows\system32\advapi32.dll @7B550000 (958464&amp;lt;7400&amp;gt;)
0138:013c: loads DLL C:\windows\system32\msvcrt.dll @7B2A0000 (2715648&amp;lt;8214&amp;gt;)
0138:013c: loads DLL C:\windows\system32\sechost.dll @7B200000 (565248&amp;lt;3163&amp;gt;)
0138:013c: loads DLL C:\windows\system32\ucrtbase.dll @7AEE0000 (3198976&amp;lt;11541&amp;gt;)
0138:013c: loads DLL C:\windows\system32\user32.dll @7A160000 (5005312&amp;lt;14159&amp;gt;)
0138:013c: loads DLL C:\windows\system32\zlib1.dll @7A120000 (135680&amp;lt;0&amp;gt;)
0138:013c: loads DLL C:\windows\system32\win32u.dll @7A0D0000 (221184&amp;lt;1966&amp;gt;)
0138:013c: loads DLL C:\windows\system32\imm32.dll @78010000 (401408&amp;lt;2996&amp;gt;)
0138:013c: loads DLL C:\windows\system32\COMCTL32.dll @77480000 (4870144&amp;lt;13692&amp;gt;)
0138:013c: loads DLL C:\windows\system32\winex11.drv @77E00000 (307200&amp;lt;4314&amp;gt;)
0138:013c: loads DLL C:\windows\system32\uxtheme.dll @77D40000 (671744&amp;lt;3646&amp;gt;)
0138:013c: loads DLL C:\windows\system32\ole32.dll @7A9F0000 (4440064&amp;lt;14323&amp;gt;)
0138:013c: loads DLL C:\windows\system32\combase.dll @7A890000 (1314816&amp;lt;7562&amp;gt;)
0138:013c: loads DLL C:\windows\system32\rpcrt4.dll @79EA0000 (2162688&amp;lt;9274&amp;gt;)
0138:013c: loads DLL C:\windows\system32\coml2.dll @79E40000 (262144&amp;lt;3883&amp;gt;)
0138:013c: loads DLL C:\windows\system32\msimg32.dll @78C20000 (81920&amp;lt;608&amp;gt;)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We see that the program loads libraries, and then the window below appears:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5au18nxeun4lvlvn2x13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5au18nxeun4lvlvn2x13.png" alt=" " width="346" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the libraries are not accessible when the program loads, it means they are loaded after the program starts. Furthermore, because these names do not appear in plain text in &lt;code&gt;hexdump -C&lt;/code&gt;, this indicates that an unpacking mechanism occurs prior to executing &lt;code&gt;LoadLibraryA&lt;/code&gt;. Looking at the hexdump, we see &lt;code&gt;FSG!&lt;/code&gt; at offset &lt;code&gt;0x00000014&lt;/code&gt;, and the very small header size confirms the use of the FSG v2.0 packer.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The FSG v2.0 Packer
&lt;/h3&gt;

&lt;p&gt;We will therefore look for calls to &lt;code&gt;LoadLibraryA&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;info functions LoadLibraryA&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;All functions matching regular expression "LoadLibraryA":

File dlls/kernelbase/loader.c:
499:  HMODULE LoadLibraryA@4(LPCSTR);

Non-debugging symbols:
0x7bb9cfa8  __wine_spec_imp_LoadLibraryA
0x7bbbd038  LoadLibraryA@4

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we set breakpoints:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;break *0x7bb9cfa8&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At the first breakpoint, we examine the call stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bt
#0  0x7bb9cfa8 in __wine_spec_imp_LoadLibraryA () from /usr/lib/i386-linux-gnu/wine/i386-windows/kernel32.dll
#1  0x004001c9 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is interesting is that it gives us an address inside our program's code: &lt;code&gt;0x004001c9&lt;/code&gt;.&lt;br&gt;
In fact, we find ourselves right in the middle of the decompression loop. The code of an FSG stub decompression loop typically performs dynamic API resolution (&lt;code&gt;LoadLibraryA&lt;/code&gt; and &lt;code&gt;GetProcAddress&lt;/code&gt;) to rebuild the IAT (Import Address Table) in memory, and then ends with an unconditional jump (&lt;code&gt;jmp&lt;/code&gt; or &lt;code&gt;ret&lt;/code&gt;) to the original, uncompressed code.&lt;/p&gt;

&lt;p&gt;We will disassemble around this address &lt;code&gt;0x004001c9&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;disass 0x4001b0, 0x4001e0&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   0x004001b0:  inc    ecx
   0x004001b1:  inc    ecx
   0x004001b2:  xchg   ebp,eax
   0x004001b3:  mov    eax,ebp
   0x004001b5:  mov    dh,0x0
   0x004001b7:  push   esi
   0x004001b8:  mov    esi,edi
   0x004001ba:  sub    esi,eax
   0x004001bc:  rep movs BYTE PTR es:[edi],BYTE PTR ds:[esi]
   0x004001be:  pop    esi
   0x004001bf:  jmp    0x400160


   0x004001c1:  pop    esi
   0x004001c2:  lods   eax,DWORD PTR ds:[esi]
   0x004001c3:  xchg   edi,eax
   0x004001c4:  lods   eax,DWORD PTR ds:[esi]
   0x004001c5:  push   eax
   0x004001c6:  call   DWORD PTR [ebx+0x10]     # call to LoadLibraryA
   0x004001c9:  xchg   ebp,eax
   0x004001ca:  mov    eax,DWORD PTR [edi]
   0x004001cc:  inc    eax
   0x004001cd:  js     0x4001c2
   0x004001cf:  jne    0x4001d4


   0x004001d1:  jmp    DWORD PTR [ebx+0xc]    # jump to the program's entry point


   0x004001d4:  push   eax
   0x004001d5:  push   ebp
   0x004001d6:  call   DWORD PTR [ebx+0x14]   # call to GetProcAddress
   0x004001d9:  stos   DWORD PTR es:[edi],eax
   0x004001da:  jmp    0x4001ca
   0x004001dc:  xor    ecx,ecx
   0x004001de:  inc    ecx
   0x004001df:  call   DWORD PTR [ebx]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Instruction Analysis:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LZMA/LZ77 Decompression Loop (&lt;code&gt;0x004001b0&lt;/code&gt; - &lt;code&gt;0x004001bf&lt;/code&gt;):&lt;/strong&gt;
These instructions copy decompressed data blocks via &lt;code&gt;rep movsb&lt;/code&gt; (&lt;code&gt;0x004001bc&lt;/code&gt;). Once the block is processed, an unconditional jump loops back to the core algorithm (&lt;code&gt;jmp 0x400160&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic IAT Resolution (&lt;code&gt;0x004001c1&lt;/code&gt; - &lt;code&gt;0x004001da&lt;/code&gt;):&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x004001c6&lt;/code&gt; (&lt;code&gt;call DWORD PTR [ebx+0x10]&lt;/code&gt;): This is the call to &lt;code&gt;LoadLibraryA&lt;/code&gt; (where the return address &lt;code&gt;0x004001c9&lt;/code&gt; was captured by our initial breakpoint).&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;0x004001d6&lt;/code&gt; (&lt;code&gt;call DWORD PTR [ebx+0x14]&lt;/code&gt;): This is the call to &lt;code&gt;GetProcAddress&lt;/code&gt;. The packer iterates through the imported function names and writes their resolved addresses into the real IAT using &lt;code&gt;stos dword ptr es:[edi], eax&lt;/code&gt; (&lt;code&gt;0x004001d9&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Jump to OEP (&lt;code&gt;0x004001d1&lt;/code&gt;):&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;jmp DWORD PTR [ebx+0xc]&lt;/code&gt;: When the import pointer reaches its end condition (&lt;code&gt;jne 0x4001d4&lt;/code&gt; is not taken), the packer executes an indirect jump via the &lt;code&gt;ebx+0xc&lt;/code&gt; register. This is precisely the instruction that transfers execution to the OEP (Original Entry Point).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We simply need to set a breakpoint on the &lt;code&gt;jmp&lt;/code&gt; and run to get the disassembled code that will execute the rest of the program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;break *0x004001d1
continue

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. The Disassembled Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   0x4001d1    jmp    dword ptr [ebx + 0xc]       &amp;lt;0x401000&amp;gt;
    ↓
   0x401000    push   0x4010c6
   0x401005    push   1
   0x401007    push   0
   0x401009    call   0x4014f2                    &amp;lt;0x4014f2&amp;gt;

   0x40100e    call   0x4014fe                    &amp;lt;0x4014fe&amp;gt;

   0x401013    sub    eax, 0xb7
   0x401018  ? je     0x401037                    &amp;lt;0x401037&amp;gt;

   0x40101a    push   0
   0x40101c    call   0x401504                    &amp;lt;0x401504&amp;gt;

   0x401021    mov    dword ptr [0x404160], eax
   0x401026    push   0
   0x401028    push   0x4011cb
   0x40102d    push   0
   0x40102f    push   0x64
   0x401031    push   eax
   0x401032    call   0x4014b6                    &amp;lt;0x4014b6&amp;gt;

   0x401037    push   0
   0x401039    call   0x4014f8                    &amp;lt;0x4014f8&amp;gt;

   0x40103e    call   0x4014aa                    &amp;lt;0x4014aa&amp;gt;

   0x401043    fadd   qword ptr [eax]


   0x401045:  add    BYTE PTR [eax],al
   0x401047:  (bad)
   0x401048:  (bad)
   0x401049:  (bad)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the program is unpacked, the straightforward idea is to search for the character strings visible on the window when running the executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;find 0x400000, +1000000, "Name"
find 0x400000, +1000000, "Serial"
find 0x400000, +1000000, "Witeg"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, this returns nothing. Why?&lt;/p&gt;

&lt;p&gt;The absence of these strings in a simple memory search is due to two technical reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Windows Resources (Dialog Templates):&lt;/strong&gt; In standard Win32 applications, dialog labels ("Name", "Serial", etc.) are not stored as direct ASCII/UTF-8 strings in the code section (&lt;code&gt;.text&lt;/code&gt;) or data section (&lt;code&gt;.data&lt;/code&gt;), but in the resource section (&lt;code&gt;.rsrc&lt;/code&gt;). Furthermore, these strings are encoded in UTF-16LE (Wide Characters, 2 bytes per character: &lt;code&gt;N\x00a\x00m\x00e\x00&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Encoding:&lt;/strong&gt; A classic search like &lt;code&gt;find "Name"&lt;/code&gt; searches for the ASCII byte sequence (&lt;code&gt;4e 61 6d 65&lt;/code&gt;). In UTF-16LE, the sequence becomes &lt;code&gt;4e 00 61 00 6d 00 65 00&lt;/code&gt;, explaining why the search fails if the format is not specified.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To search for our strings, we need to run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;search -w "Name"
search -w "Serial"
search -w "Witeg"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this yields no results either. In the end, it doesn't matter; what is important is retrieving the user input. To do this, we will set breakpoints on the Windows API functions that capture keyboard inputs, first finding their exact signatures and then placing the breakpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;info functions GetDlgItemText
info functions GetWindowText

hbreak GetDlgItemTextA@16
hbreak GetDlgItemTextW@16
hbreak GetWindowTextA@12
hbreak GetWindowTextW@12

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that this is done, all we have to do is resume execution. However, no &lt;code&gt;hbreak&lt;/code&gt; is triggered, which means the programmer wrote a custom Windows message handling routine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;info functions DispatchMessage

hbreak DispatchMessageA@4
hbreak DispatchMessageW@4

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We finally hit our breakpoints with the following call stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 0x7a1a8665 DispatchMessageW@4+5
   1 0x7a186559 IsDialogMessageW@8+425
   2 0x7a186dff DIALOG_DoDialogBox+319
   3 0x7a186f5e DialogBoxParamA@20+142
   4 0x401037
   5 0x3
   6 0x4
   7 0xffff

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We just need to disassemble around the return address &lt;code&gt;0x401037&lt;/code&gt;, for instance using &lt;code&gt;disass 0x401010, 0x401038&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;disass 0x401010, 0x401039
Dump of assembler code from 0x401010 to 0x401039:
   0x00401010:  add    al,0x0
   0x00401012:  add    BYTE PTR ds:0xb7,ch
   0x00401018:  je     0x401037
   0x0040101a:  push   0x0
   0x0040101c:  call   0x401504
   0x00401021:  mov    ds:0x404160,eax
   0x00401026:  push   0x0
   0x00401028:  push   0x4011cb
   0x0040102d:  push   0x0
   0x0040102f:  push   0x64
   0x00401031:  push   eax
   0x00401032:  call   0x4014b6
   0x00401037:  push   0x0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. The Windows Message Handler Routine
&lt;/h3&gt;

&lt;p&gt;The prototype of the function is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;INT_PTR&lt;/span&gt; &lt;span class="nf"&gt;DialogBoxParamA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;HINSTANCE&lt;/span&gt; &lt;span class="n"&gt;hInstance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;LPCSTR&lt;/span&gt;    &lt;span class="n"&gt;lpTemplateName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;HWND&lt;/span&gt;      &lt;span class="n"&gt;hWndParent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;DLGPROC&lt;/span&gt;   &lt;span class="n"&gt;lpDialogFunc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;lt;--- The CrackMe routine address&lt;/span&gt;
  &lt;span class="n"&gt;LPARAM&lt;/span&gt;    &lt;span class="n"&gt;dwInitParam&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We set a breakpoint on &lt;code&gt;0x4011cb&lt;/code&gt; via:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;break *0x4011cb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And we get the following disassembled code, which is a standard Windows message handler routine (&lt;code&gt;DialogProc&lt;/code&gt;). We can recognize the switch-case structure comparing &lt;code&gt;ax&lt;/code&gt; against various message types, and we just need to identify the one that interests us from the list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   0x4011cb:  push   ebp
   0x4011cc:  mov    ebp,esp
   0x4011ce:  mov    eax,DWORD PTR [ebp+0xc]
   0x4011d1:  cmp    ax,0x2
   0x4011d5:  je     0x4012a4
   0x4011db:  cmp    ax,0x10
   0x4011df:  je     0x4012a4

   0x4011e5:  cmp    ax,0x111  # This is the one we want; we set a breakpoint on 0x4012b2
   0x4011e9:  je     0x4012b2


   0x4011ef:  cmp    ax,0x110
   0x4011f3:  je     0x4012e1
   0x4011f9:  cmp    ax,0x200
   0x4011fd:  je     0x401248
   0x4011ff:  cmp    ax,0x202
   0x401203:  je     0x401221
   0x401205:  cmp    ax,0x201
   0x401209:  je     0x40122a
   0x40120b:  cmp    ax,0x214
   0x40120f:  je     0x401221
   0x401211:  cmp    ax,0x133
   0x401215:  je     0x4013fd
   0x40121b:  xor    eax,eax
   0x40121d:  leave
   0x40121e:  ret    0x10

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Analyzing this switch-case shows the typical structure of a &lt;code&gt;DialogProc&lt;/code&gt; function. The &lt;code&gt;uMsg&lt;/code&gt; argument (&lt;code&gt;[ebp+0xc]&lt;/code&gt;) is compared against several Win32 system constants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;0x110&lt;/code&gt; (&lt;code&gt;WM_INITDIALOG&lt;/code&gt;) -&amp;gt; Redirects to &lt;code&gt;0x004012e1&lt;/code&gt; (interface initialization, loading images, or hiding/displaying controls).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x111&lt;/code&gt; (&lt;code&gt;WM_COMMAND&lt;/code&gt;)  -&amp;gt; Redirects to &lt;code&gt;0x004012b2&lt;/code&gt;. This is precisely the target branch.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x02&lt;/code&gt; (&lt;code&gt;WM_DESTROY&lt;/code&gt;) and &lt;code&gt;0x10&lt;/code&gt; (&lt;code&gt;WM_CLOSE&lt;/code&gt;) -&amp;gt; Redirect to &lt;code&gt;0x004012a4&lt;/code&gt; to close the application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x200&lt;/code&gt; (&lt;code&gt;WM_MOUSEMOVE&lt;/code&gt;), &lt;code&gt;0x201&lt;/code&gt; (&lt;code&gt;WM_LBUTTONDOWN&lt;/code&gt;), &lt;code&gt;0x202&lt;/code&gt; (&lt;code&gt;WM_LBUTTONUP&lt;/code&gt;) -&amp;gt; Mouse event handlers (often used to move a borderless window or handle the visible hyperlink on the image).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0x133&lt;/code&gt; (&lt;code&gt;WM_CTLCOLOREDIT&lt;/code&gt;) -&amp;gt; Customization of text field colors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is the code found at &lt;code&gt;0x4012b2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   0x4012b2:  mov    eax,DWORD PTR [ebp+0x10]
   0x4012b5:  cmp    ax,0x3ea
   0x4012b9:  je     0x4012cd
   0x4012bb:  cmp    ax,0x3e9
   0x4012bf:  je     0x4012cd
   0x4012c1:  cmp    ax,0x2
   0x4012c5:  je     0x4012a4
   0x4012c7:  xor    eax,eax
   0x4012c9:  leave
   0x4012ca:  ret    0x10
   0x4012cd:  shr    eax,0x10
   0x4012d0:  cmp    eax,0x300
   0x4012d5:  je     0x40141f
   0x4012db:  xor    eax,eax
   0x4012dd:  leave
   0x4012de:  ret    0x10
   0x4012e1:  push   0x0
   0x4012e3:  push   0x0
   0x4012e5:  push   0x31
   0x4012e7:  push   DWORD PTR [ebp+0x8]
   0x4012ea:  call   0x4014e6
   0x4012ef:  push   0x404120
   0x4012f4:  push   0x3c
   0x4012f6:  push   eax
   0x4012f7:  call   0x40148c
   0x4012fc:  mov    DWORD PTR ds:0x404130,0x2bc
   0x401306:  push   0x404120
   0x40130b:  call   0x401486
   0x401310:  mov    ds:0x404164,eax
   0x401315:  push   0x3e9
   0x40131a:  push   DWORD PTR [ebp+0x8]
   0x40131d:  call   0x4014c8
   0x401322:  push   0x1
   0x401324:  push   DWORD PTR ds:0x404164
   0x40132a:  push   0x30
   0x40132c:  push   eax
   0x40132d:  call   0x4014e6
   0x401332:  push   0x401094
   0x401337:  push   0x3e9
   0x40133c:  push   DWORD PTR [ebp+0x8]
   0x40133f:  call   0x4010d7
   0x401344:  push   0x3ea
   0x401349:  push   DWORD PTR [ebp+0x8]
   0x40134c:  call   0x4014c8
   0x401351:  push   0x1
   0x401353:  push   DWORD PTR ds:0x404164
   0x401359:  push   0x30
   0x40135b:  push   eax
   0x40135c:  call   0x4014e6
   0x401361:  push   0x4010ac
   0x401366:  push   0x3ea
   0x40136b:  push   DWORD PTR [ebp+0x8]
   0x40136e:  call   0x4010d7
   0x401373:  push   0x0
   0x401375:  push   0x40
   0x401377:  push   0xc5
   0x40137c:  push   0x3e9
   0x401381:  push   DWORD PTR [ebp+0x8]
   0x401384:  call   0x4014e0
   0x401389:  push   0x0
   0x40138b:  push   0x18
   0x40138d:  push   0xc5
   0x401392:  push   0x3ea
   0x401397:  push   DWORD PTR [ebp+0x8]
   0x40139a:  call   0x4014e0
   0x40139f:  push   0x3e8
   0x4013a4:  push   DWORD PTR [ebp+0x8]
   0x4013a7:  push   0x40105d
   0x4013ac:  push   0x50000000
   0x4013b1:  call   0x4014a4
   0x4013b6:  mov    ds:0x404168,eax
   0x4013bb:  push   0x401043
   0x4013c0:  push   0x2
   0x4013c2:  push   0x404
   0x4013c7:  push   eax
   0x4013c8:  call   0x4014e6
   0x4013cd:  push   0x1
   0x4013cf:  push   DWORD PTR ds:0x404164
   0x4013d5:  push   0x30
   0x4013d7:  push   DWORD PTR ds:0x404168
   0x4013dd:  call   0x4014e6
   0x4013e2:  push   0x4010c6
   0x4013e7:  push   0x1
   0x4013e9:  push   0x401
   0x4013ee:  push   DWORD PTR ds:0x404168
   0x4013f4:  call   0x4014e6
   0x4013f9:  leave
   0x4013fa:  ret    0x10
   0x4013fd:  push   0x1f1fff
   0x401402:  push   DWORD PTR [ebp+0x10]
   0x401405:  call   0x40149e
   0x40140a:  push   0x2
   0x40140c:  push   DWORD PTR [ebp+0x10]
   0x40140f:  call   0x401498
   0x401414:  push   0x0
   0x401416:  call   0x401492
   0x40141b:  leave
   0x40141c:  ret    0x10
   0x40141f:  pusha
   0x401420:  mov    ebx,0x401081
   0x401425:  mov    esi,0x4041b8
   0x40142a:  push   esi
   0x40142b:  push   0x19
   0x40142d:  push   0xd
   0x40142f:  push   0x3ea
   0x401434:  push   DWORD PTR [ebp+0x8]
   0x401437:  call   0x4014e0
   0x40143c:  cmp    eax,0x18
   0x40143f:  jne    0x40146e
   0x401441:  mov    edi,0x404170
   0x401446:  push   edi
   0x401447:  push   0x41
   0x401449:  push   0xd
   0x40144b:  push   0x3e9
   0x401450:  push   DWORD PTR [ebp+0x8]
   0x401453:  call   0x4014e0
   0x401458:  cmp    eax,0x5
   0x40145b:  jl     0x40146e
   0x40145d:  push   esi
   0x40145e:  push   eax
   0x40145f:  push   edi
   0x401460:  call   0x401510
   0x401465:  test   eax,eax
   0x401467:  je     0x40146e
   0x401469:  mov    ebx,0x401064
   0x40146e:  push   ebx
   0x40146f:  push   0x0
   0x401471:  push   0x401
   0x401476:  push   DWORD PTR ds:0x404168
   0x40147c:  call   0x4014e6
   0x401481:  popa
   0x401482:  leave
   0x401483:  ret    0x10

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This piece of assembly is the core of the CrackMe. The entire application behavior resides here, from keystroke detection to the validation algorithm.&lt;/p&gt;

&lt;p&gt;First, we find:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Filtering the &lt;code&gt;WM_COMMAND&lt;/code&gt; Message (&lt;code&gt;0x004012b2&lt;/code&gt; - &lt;code&gt;0x004012d5&lt;/code&gt;)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x4012b2: mov eax, DWORD PTR [ebp+0x10] ; eax = wParam
0x4012b5: cmp ax, 0x3ea                 ; Check ID 0x3EA (Serial field) ?
0x4012b9: je  0x4012cd
0x4012bb: cmp ax, 0x3e9                 ; Check ID 0x3E9 (Name field) ?
0x4012bf: je  0x4012cd

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The program checks if the message comes from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Serial&lt;/strong&gt; field (&lt;code&gt;ID 0x3EA&lt;/code&gt; / &lt;code&gt;1002&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Name&lt;/strong&gt; field (&lt;code&gt;ID 0x3E9&lt;/code&gt; / &lt;code&gt;1001&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If so, it extracts the notification code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x4012cd: shr eax, 0x10                 ; HIWORD(wParam) = notification code
0x4012d0: cmp eax, 0x300                ; 0x300 = EN_CHANGE
0x4012d5: je  0x40141f                 ; Jump to check!

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;0x0300&lt;/code&gt; corresponds to the Win32 constant &lt;code&gt;EN_CHANGE&lt;/code&gt;. This confirms that validation runs dynamically on every character typed or deleted in either field, without waiting for the Enter key to be pressed.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Serial Verification Routine (&lt;code&gt;0x0040141f&lt;/code&gt; - &lt;code&gt;0x00401483&lt;/code&gt;)
&lt;/h4&gt;

&lt;p&gt;This is where the application checks the entered data:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step A: Extracting and checking the Serial (&lt;code&gt;0x3EA&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x401425: mov esi, 0x4041b8             ; Destination buffer for Serial
0x40142a: push esi
0x40142b: push 0x19                     ; Max size (25 bytes)
0x40142d: push 0xd                      ; Message 0x0D = WM_GETTEXT
0x40142f: push 0x3ea                    ; Serial field ID
0x401434: push DWORD PTR [ebp+0x8]      ; hwnd
0x401437: call 0x4014e0                 ; Wrapper around SendDlgItemMessageA
0x40143c: cmp eax, 0x18                 ; Serial length == 24 chars (0x18) ?
0x40143f: jne 0x40146e                  ; If != 24, immediate failure

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step B: Extracting and checking the Name (&lt;code&gt;0x3E9&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x401441: mov edi, 0x404170             ; Destination buffer for Name
0x401446: push edi
0x401447: push 0x41                     ; Max size (65 bytes)
0x401449: push 0xd                      ; WM_GETTEXT
0x40144b: push 0x3e9                    ; Name field ID
0x401450: push DWORD PTR [ebp+0x8]      ; hwnd
0x401453: call 0x4014e0
0x401458: cmp eax, 0x5                  ; Name length &amp;gt;= 5 chars ?
0x40145b: jl  0x40146e                  ; If &amp;lt; 5, failure

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step C: Comparison Algorithm (&lt;code&gt;0x00401510&lt;/code&gt;)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x40145d: push esi                      ; Pointer to entered Serial (0x4041b8)
0x40145e: push eax                      ; Length of Name
0x40145f: push edi                      ; Pointer to entered Name (0x404170)
0x401460: call 0x401510                 ; &amp;lt;--- VALIDATION ALGORITHM
0x401465: test eax, eax                 ; Returns 1 (Success) or 0 (Failure)
0x401467: je  0x40146e                  ; Jumps to failure
0x401469: mov ebx, 0x401064             ; Pointer to SUCCESS message

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, it is very simple: if the goal is to pass the check without looking into the routine, simply replacing &lt;code&gt;je 0x40146e&lt;/code&gt; with two &lt;code&gt;nop&lt;/code&gt; instructions will do the trick. However, if the goal is to provide a valid Name and correct Serial, we will need to reverse-engineer the verification routine.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Epilogue
&lt;/h3&gt;

&lt;p&gt;In this first article on Level 6 crackmes, we have smoothly progressed up to the routine that validates the Serial against the Name.&lt;br&gt;
Nothing overly complicated so far—just a packer and a message loop. When the main difficulty doesn't lie in obfuscation, it resides within the routine that verifies the Serial against the Name. That is what we will explore in a future article.&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>RV32I vs x86_32 Comparison</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Thu, 03 Sep 2026 14:05:09 +0000</pubDate>
      <link>https://dev.to/ddupard/rv32i-vs-x8632-comparison-4pd8</link>
      <guid>https://dev.to/ddupard/rv32i-vs-x8632-comparison-4pd8</guid>
      <description>&lt;h4&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;There are several major differences between a RISC processor (such as the 32-bit RISC-V executing the RV32I or RV32G instruction sets) and a CISC processor (such as the i386).&lt;/p&gt;

&lt;p&gt;The first difference that comes to mind is, of course, the size of the instruction set: between 1,000 and 1,500 instructions for the i386 compared to around 40 for a RISC-V processor running the base RV32I instruction set.&lt;/p&gt;

&lt;p&gt;However, there is another, more subtle and less obvious difference: in a CISC processor, instruction length is variable and can range from 1 byte to more than 10 bytes. In contrast, on a RISC processor, the instruction size is fixed (except when using compressed instructions) and equals exactly 4 bytes (32 bits) for an RV32I processor.&lt;/p&gt;

&lt;p&gt;Being limited to 4 bytes to encode an instruction introduces specific hardware and assembly constraints. The most immediate one leads to a simple question:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;How do you load a 32-bit immediate value into a 32-bit register on a 32-bit RISC-V processor?&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To answer this, let us first examine how this is handled on an i386 processor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.intel_syntax noprefix
.section .text               # Indicates that the following section contains executable code
.global _start              # Defines the entry point of the program

_start:
    mov eax, 0x12345678     # Loads the hexadecimal value 0x12345678 into the eax register

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After assembling with GNU &lt;code&gt;as&lt;/code&gt; and disassembling with &lt;code&gt;objdump&lt;/code&gt;, we obtain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x86_32:     file format elf32-i386


Disassembly of section .text:

08049000 &amp;lt;_start&amp;gt;:
8049000:  b8 78 56 34 12        mov    eax,0x12345678

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a direct translation of the assembly instruction: the opcode &lt;code&gt;b8&lt;/code&gt; is followed by the full 32-bit constant &lt;code&gt;0x12345678&lt;/code&gt; (encoded in little-endian as &lt;code&gt;78 56 34 12&lt;/code&gt;), producing a single 5-byte instruction.&lt;/p&gt;




&lt;p&gt;What happens on a 32-bit RISC-V processor?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.section .text             
.global _start             

_start:
    li t0, 0x12345678      # load 0x12345678 into register t0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The assembly file above is translated into a binary that disassembles into the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;riscv:     file format elf32-littleriscv


Disassembly of section .text:

00010074 &amp;lt;_start&amp;gt;:
   10074: 123452b7            lui t0,0x12345
   10078: 67828293            addi  t0,t0,1656 # 0x678 in hex

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because a 32-bit RISC-V instruction must fit within exactly 32 bits, it cannot contain a 32-bit immediate payload while simultaneously reserving bits for the opcode and the target register field. As a result, the assembler splits the operation into two hardware instructions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lui t0, 0x12345&lt;/code&gt; (&lt;strong&gt;Load Upper Immediate&lt;/strong&gt;, U-Type format): loads the upper 20 bits into &lt;code&gt;t0&lt;/code&gt; (shifted left by 12 bits).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;addi t0, t0, 1656&lt;/code&gt; (&lt;strong&gt;Add Immediate&lt;/strong&gt;, I-Type format): adds the remaining 12-bit value (&lt;code&gt;1656&lt;/code&gt; in decimal = &lt;code&gt;0x678&lt;/code&gt; in hex) to &lt;code&gt;t0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Pseudo-Instructions vs Real Instructions&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;It is important to note that &lt;code&gt;li&lt;/code&gt; (&lt;strong&gt;Load Immediate&lt;/strong&gt;) does not actually exist in the RISC-V hardware specification. It is a &lt;strong&gt;pseudo-instruction&lt;/strong&gt; provided by the assembler to simplify programming. When writing RISC-V assembly, the toolchain automatically translates high-level constructs like &lt;code&gt;li&lt;/code&gt; or &lt;code&gt;la&lt;/code&gt; (&lt;strong&gt;Load Address&lt;/strong&gt;) into standard physical instruction sequences (&lt;code&gt;lui&lt;/code&gt; + &lt;code&gt;addi&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The Sign Extension Trap&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A critical subtlety arises when loading arbitrary 32-bit values: the 12-bit immediate field in the &lt;code&gt;addi&lt;/code&gt; instruction is &lt;strong&gt;sign-extended&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If bit 11 of the lower 12-bit payload is &lt;code&gt;1&lt;/code&gt; (i.e., if the lower 12 bits fall in the range &lt;code&gt;0x800&lt;/code&gt;–&lt;code&gt;0xFFF&lt;/code&gt;), &lt;code&gt;addi&lt;/code&gt; treats it as a negative value and subtracts it from the upper value. To compensate for this arithmetic effect, a compliant assembler must automatically detect when bit 11 is set and &lt;strong&gt;add &lt;code&gt;1&lt;/code&gt; to the upper 20 bits&lt;/strong&gt; loaded by &lt;code&gt;lui&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Architectural Trade-offs: Hardware vs. Binary Size&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This structural difference highlights the core design philosophy separating CISC and RISC architectures:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;CISC (x86_32)&lt;/th&gt;
&lt;th&gt;RISC (RISC-V RV32I)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Instruction Length&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Variable (1 to 15 bytes)&lt;/td&gt;
&lt;td&gt;Fixed (4 bytes / 32 bits)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;32-bit Immediate Loading&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Single 5-byte instruction&lt;/td&gt;
&lt;td&gt;Two 4-byte instructions (8 bytes total)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hardware Decoder Complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High (must determine instruction boundaries dynamically)&lt;/td&gt;
&lt;td&gt;Very Low (fixed alignment simplifies instruction fetch and pipeline)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution Impact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Compact code, complex decoding logic&lt;/td&gt;
&lt;td&gt;Slightly larger code size, streamlined pipelining and execution&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Epilogue&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Building an assembler for a RISC-V processor may seem straightforward at first glance due to the reduced instruction set. However, subtleties arising from fixed-width instruction encodings, sign-extension compensation, and pseudo-instruction expansion introduce unexpected layers of complexity that every compiler and assembler author must carefully handle.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>hardware</category>
    </item>
    <item>
      <title>Crackmes: The Methodology</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Sun, 30 Aug 2026 11:05:02 +0000</pubDate>
      <link>https://dev.to/ddupard/crackmes-the-methodology-3ef2</link>
      <guid>https://dev.to/ddupard/crackmes-the-methodology-3ef2</guid>
      <description>&lt;h3&gt;
  
  
  1. Prologue
&lt;/h3&gt;

&lt;p&gt;Learning how to reverse-engineer crackmes is, above all, a matter of methodology and tooling.&lt;/p&gt;

&lt;p&gt;While extensive practice is necessary—if only to train your brain to recognize recurring patterns—nothing beats a solid set of tools that do 95% of the heavy lifting. The bulk of a reverse engineer's work consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mapping out the most common patterns and scenarios.&lt;/li&gt;
&lt;li&gt;Building and refining a personal toolkit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building a reliable mental map requires analyzing dozens of targets. Speed in crackmes or CTFs comes from rigorous, repetitive practice. While LLMs can streamline significant parts of the analysis, hands-on practice remains irreplaceable.&lt;/p&gt;

&lt;p&gt;Every crackme consists of two parts: what you already know (patterns encountered in previous challenges) and what you do not yet know. Recapping what we covered in the previous articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We recognize three core system calls (sys_write, sys_read, sys_exit).&lt;/li&gt;
&lt;li&gt;We are familiar with the 50 most common x86_64 assembly instructions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This foundation is more than enough to tackle basic crackmes. The goal is always to quickly isolate the known components to focus entirely on the unknown logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Step-by-Step Methodology
&lt;/h3&gt;

&lt;p&gt;Most crackmes ask you to recover a password or valid serial key. The execution flow almost always follows a predictable pattern: display a prompt, read user input, execute a validation routine, and branch toward success or failure.&lt;/p&gt;

&lt;p&gt;Here is the standard methodology to apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Execute the binary in a secure environment to observe its runtime behavior and intercept direct I/O.&lt;/li&gt;
&lt;li&gt;Identify and strip protections (packers, wrappers, obfuscated code, runtime encryption) to restore a binary suitable for static analysis.&lt;/li&gt;
&lt;li&gt;Identify I/O and entry points: Locate system calls (sys_write, sys_read) or standard API calls.&lt;/li&gt;
&lt;li&gt;Map the control flow: Identify control flow instructions (CALL, JMP, JNE, JZ, etc.) leading to success or failure branches.&lt;/li&gt;
&lt;li&gt;Isolate the validation routine: Target the exact function or loop where the input is compared to the expected result.&lt;/li&gt;
&lt;li&gt;Analyze the algorithm: Break down the arithmetic or logical transformations applied to the input (XOR, bit rotations, arithmetic shifts).&lt;/li&gt;
&lt;li&gt;Scripting &amp;amp; Solving: If the algorithm cannot be easily inverted by hand, write a Python script (or use constraint solvers like Z3) to brute-force or solve the key equations.&lt;/li&gt;
&lt;li&gt;Post-Mortem Analysis: Review the solution (What was new? Where were the bottlenecks?).&lt;/li&gt;
&lt;li&gt;Update your toolbox: Automate the process if this pattern recurs in future challenges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Golden Rule: Every domain of reverse engineering requires specialization. Reversing a Windows malware binary differs significantly from hunting vulnerabilities in an iOS application or the Linux kernel.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Different Domains of Reversing
&lt;/h3&gt;

&lt;p&gt;The vast majority of challenges on crackmes.one are written in C/C++ for Windows. In real-world software development, applications are rarely written in pure assembly; developers write in C/C++ (often using Visual Studio) and let the compiler generate the target x86_64 machine code.&lt;/p&gt;

&lt;p&gt;In CTFs, the landscape is broader and generally spans five main categories:&lt;/p&gt;

&lt;h5&gt;
  
  
  1. Classic Native Binaries
&lt;/h5&gt;

&lt;p&gt;The core of traditional reversing. Analyzing compiled machine code in platform-native formats: Windows (PE), Linux (ELF), or macOS (Mach-O).&lt;/p&gt;

&lt;h5&gt;
  
  
  2. Managed Languages &amp;amp; Bytecode
&lt;/h5&gt;

&lt;p&gt;Binaries executed by a virtual machine or runtime (.NET/C#, Java, Android APKs, compiled Python). These are typically straightforward to decompile back to near-source representation using dedicated tools (dnSpy, JADX).&lt;/p&gt;

&lt;h5&gt;
  
  
  3. Non-x86 Architectures &amp;amp; Embedded Systems (Firmware / Custom VMs)
&lt;/h5&gt;

&lt;p&gt;Reversing focused on hardware or embedded devices (ARM/ARM64, MIPS, RISC-V). This category also includes challenges featuring custom virtual machines (VMs with proprietary instruction sets).&lt;/p&gt;

&lt;h5&gt;
  
  
  4. Protections, Obfuscation &amp;amp; Anti-Analysis
&lt;/h5&gt;

&lt;p&gt;Focuses on bypassing defensive measures baked into the binary: packers (UPX, Themida), anti-debugging checks, and control-flow obfuscation (OLLVM).&lt;/p&gt;

&lt;h5&gt;
  
  
  5. Algorithmics &amp;amp; Applied Cryptography
&lt;/h5&gt;

&lt;p&gt;Challenges focused on reversing custom mathematical logic or proprietary cryptographic schemes (custom XOR, substitutions, permutations).&lt;/p&gt;

&lt;p&gt;Personal Take: Categories 1, 3, and 4 are by far the most educational and rewarding. Category 2 (Bytecode) offers less depth regarding low-level mechanics, while Category 5 leans more toward pure mathematics than systems-level reverse engineering.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Market Overview &amp;amp; Key Figures
&lt;/h3&gt;

&lt;p&gt;To provide some industry context, an estimated 25,000 professionals practice reverse engineering in the United States:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;60% focus on the x86_64 architecture (Windows and Linux).&lt;/li&gt;
&lt;li&gt;30% focus on ARM (Mobile, IoT, Apple Silicon).&lt;/li&gt;
&lt;li&gt;10% work on industrial processors and proprietary embedded systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Within that 10%, approximately 1% to 2% (between 250 and 500 specialists) work on undocumented or proprietary instruction set architectures (ISAs).&lt;/p&gt;

&lt;p&gt;Furthermore, out of those 25,000 practitioners, only 2,000 to 3,000 engineers specialize exclusively in advanced Vulnerability Research.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Epilogue
&lt;/h3&gt;

&lt;p&gt;This methodology sets the necessary framework before moving into practical analysis. In the next article, we will apply these steps to our first Linux crackme.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>learning</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Introduction to x86_64 Assembly</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Sat, 29 Aug 2026 07:25:15 +0000</pubDate>
      <link>https://dev.to/ddupard/introduction-to-x8664-assembly-23fc</link>
      <guid>https://dev.to/ddupard/introduction-to-x8664-assembly-23fc</guid>
      <description>&lt;p&gt;Before diving further into the study of crackmes, it seemed appropriate to write a short introduction to x86_64 assembly language. &lt;br&gt;
It is a complex architecture, mainly due to the vast number of instructions in its instruction set.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Registers
&lt;/h3&gt;

&lt;p&gt;On the x86_64 architecture, there are 16 general-purpose 64-bit registers. Each register has a full 64-bit name and can be divided into sub-registers to manipulate 32-bit, 16-bit, or 8-bit data.&lt;/p&gt;

&lt;h5&gt;
  
  
  The 16 General-Purpose Registers (64 bits)
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Register (64 bits)&lt;/th&gt;
&lt;th&gt;32 bits&lt;/th&gt;
&lt;th&gt;16 bits&lt;/th&gt;
&lt;th&gt;8 bits (low byte)&lt;/th&gt;
&lt;th&gt;Main Role / Usage (System V ABI Convention)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RAX&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EAX&lt;/td&gt;
&lt;td&gt;AX&lt;/td&gt;
&lt;td&gt;AL&lt;/td&gt;
&lt;td&gt;Accumulator, function/syscall return value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RBX&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EBX&lt;/td&gt;
&lt;td&gt;BX&lt;/td&gt;
&lt;td&gt;BL&lt;/td&gt;
&lt;td&gt;Base register (callee-saved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RCX&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ECX&lt;/td&gt;
&lt;td&gt;CX&lt;/td&gt;
&lt;td&gt;CL&lt;/td&gt;
&lt;td&gt;Loop counter / 4th function argument&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RDX&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EDX&lt;/td&gt;
&lt;td&gt;DX&lt;/td&gt;
&lt;td&gt;DL&lt;/td&gt;
&lt;td&gt;Data / 3rd function argument / 3rd syscall argument&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RSI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ESI&lt;/td&gt;
&lt;td&gt;SI&lt;/td&gt;
&lt;td&gt;SIL&lt;/td&gt;
&lt;td&gt;Source index / 2nd function &amp;amp; syscall argument&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RDI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EDI&lt;/td&gt;
&lt;td&gt;DI&lt;/td&gt;
&lt;td&gt;DIL&lt;/td&gt;
&lt;td&gt;Destination index / 1st function &amp;amp; syscall argument&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RBP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EBP&lt;/td&gt;
&lt;td&gt;BP&lt;/td&gt;
&lt;td&gt;BPL&lt;/td&gt;
&lt;td&gt;Base Pointer (frame pointer)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RSP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ESP&lt;/td&gt;
&lt;td&gt;SP&lt;/td&gt;
&lt;td&gt;SPL&lt;/td&gt;
&lt;td&gt;Stack Pointer (top of current stack)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;R8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;R8D&lt;/td&gt;
&lt;td&gt;R8W&lt;/td&gt;
&lt;td&gt;R8B&lt;/td&gt;
&lt;td&gt;5th function argument / 5th syscall argument&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;R9&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;R9D&lt;/td&gt;
&lt;td&gt;R9W&lt;/td&gt;
&lt;td&gt;R9B&lt;/td&gt;
&lt;td&gt;6th function argument / 6th syscall argument&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;R10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;R10D&lt;/td&gt;
&lt;td&gt;R10W&lt;/td&gt;
&lt;td&gt;R10B&lt;/td&gt;
&lt;td&gt;Temporary register / 4th syscall argument&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;R11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;R11D&lt;/td&gt;
&lt;td&gt;R11W&lt;/td&gt;
&lt;td&gt;R11B&lt;/td&gt;
&lt;td&gt;Temporary register (scratch)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;R12 to R15&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;R12D-R15D&lt;/td&gt;
&lt;td&gt;R12W-R15W&lt;/td&gt;
&lt;td&gt;R12B-R15B&lt;/td&gt;
&lt;td&gt;Callee-saved registers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Special and Control Registers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RIP (Instruction Pointer): Points to the next instruction to execute.&lt;/li&gt;
&lt;li&gt;RFLAGS: Status register containing flags:&lt;/li&gt;
&lt;li&gt;ZF (Zero Flag): Set to 1 if the result of the last operation is zero.&lt;/li&gt;
&lt;li&gt;SF (Sign Flag): Set to 1 if the result is negative.&lt;/li&gt;
&lt;li&gt;CF (Carry Flag): Unsigned arithmetic overflow.&lt;/li&gt;
&lt;li&gt;OF (Overflow Flag): Signed arithmetic overflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Vector and Floating-Point Registers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(SIMD)XMM0 to XMM15 (128 bits) / YMM0 to YMM15 (256 bits) / ZMM0 to ZMM31 (512 bits): Used for floating-point calculations (float/double) and vector processing (AVX/SSE).&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Stack Mechanics
&lt;/h3&gt;

&lt;p&gt;Understanding how the stack operates is essential for binary analysis. &lt;/p&gt;

&lt;p&gt;In the x86_64 architecture, the stack follows a &lt;strong&gt;LIFO&lt;/strong&gt; (&lt;em&gt;Last-In, First-Out&lt;/em&gt;) structure and &lt;strong&gt;grows downwards&lt;/strong&gt; toward lower memory addresses. When data is pushed onto the stack (via &lt;code&gt;PUSH&lt;/code&gt; or a &lt;code&gt;CALL&lt;/code&gt; instruction), the Stack Pointer (&lt;code&gt;RSP&lt;/code&gt;) is decremented by 8 bytes; conversely, when data is popped (via &lt;code&gt;POP&lt;/code&gt; or &lt;code&gt;RET&lt;/code&gt;), &lt;code&gt;RSP&lt;/code&gt; is incremented. &lt;/p&gt;

&lt;p&gt;The stack is heavily used by binaries to store local variables, pass function parameters beyond the 6th argument, and keep track of function return addresses.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Instructions
&lt;/h3&gt;

&lt;p&gt;There is no fixed, exact count for the x86_64 instruction set, as the architecture has continuously evolved by accumulating extensions (SSE, AVX, AVX-512, AMX, VMX, etc.).Counting basic mnemonics alone (without advanced vector variants), there are roughly 1,000 to 1,500 distinct instructions. &lt;br&gt;
Including all modern SIMD instruction sets, that number exceeds 2,000 to 3,000 opcodes.However, in reverse engineering, fewer than 50 instructions account for about 90% of the assembly code encountered in crackmes.&lt;/p&gt;

&lt;h5&gt;
  
  
  1. Data Transfer (1–7)
&lt;/h5&gt;

&lt;p&gt;MOV (Move) — Copies the source operand to the destination operand.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: mov rax, 0x1 (Copies 1 into RAX)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LEA (Load Effective Address) — Calculates the memory address of the source or performs fast arithmetic without accessing memory.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: lea rsi, &lt;a href="https://dev.toStores%20the%20address%20RBX+16%20into%20RSI"&gt;rbx + 0x10&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MOVZX (Move with Zero-Extend) — Copies a smaller register into a larger one, padding the higher bits with zeros.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: movzx eax, byte ptr &lt;a href="https://dev.toReads%201%20byte%20and%20zero-extends%20it%20to%2032%20bits"&gt;rsi&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MOVSX (Move with Sign-Extend) — Copies a smaller register into a larger one while preserving the sign bit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: movsx eax, al (Extends AL to EAX while maintaining its sign)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CMOVE / CMOVZ (Conditional Move if Equal) — Copies the source into the destination only if ZF = 1.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: cmove eax, ebx (Copies EBX to EAX if the comparison was equal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CMOVNE / CMOVNZ (Conditional Move if Not Equal) — Copies source to destination only if ZF = 0.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: cmovne ax, r8w (Copies R8W to AX if not equal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;XCHG (Exchange) — Swaps the contents of two registers or a register and a memory location.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: xchg rax, rbx (Swaps RAX and RBX)&lt;/li&gt;
&lt;/ul&gt;




&lt;h5&gt;
  
  
  2. Stack Management (8–9)
&lt;/h5&gt;

&lt;p&gt;PUSH — Places a value onto the top of the stack (RSP decreases by 8).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: push rbp (Saves RBP onto the stack)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;POP — Pops the top value from the stack into a register (RSP increases by 8).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: pop rsi (Pops the top stack value into RSI)&lt;/li&gt;
&lt;/ul&gt;




&lt;h5&gt;
  
  
  3. Basic Arithmetic (10–18)
&lt;/h5&gt;

&lt;p&gt;ADD — Adds two values.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: add rax, rbx (RAX = RAX + RBX)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SUB — Subtracts the source from the destination.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: sub rsp, 0x20 (Allocates 32 bytes on the stack)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;INC (Increment) — Adds 1 to the destination.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: inc rcx (RCX = RCX + 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DEC (Decrement) — Subtracts 1 from the destination.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: dec rcx (RCX = RCX - 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MUL (Unsigned Multiply) — Unsigned multiplication (RAX * source, result stored in RDX:RAX).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: mul rbx (RAX = RAX * RBX)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IMUL (Signed Multiply) — Signed multiplication.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: imul eax, ebx, 0x5 (EAX = EBX * 5)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DIV (Unsigned Divide) — Unsigned division of RDX:RAX by the source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: div rbx (RAX = Quotient, RDX = Remainder)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IDIV (Signed Divide) — Signed division of RDX:RAX by the source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: idiv rbx (Signed division by RBX)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NEG (Two's Complement Negation) — Inverts the sign of a number (two's complement).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: neg eax (EAX = -EAX)&lt;/li&gt;
&lt;/ul&gt;




&lt;h5&gt;
  
  
  4. Bitwise Logic &amp;amp; Masking (19–23)
&lt;/h5&gt;

&lt;p&gt;XOR — Bitwise Exclusive OR (commonly used to clear a register or for light encryption).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: xor eax, eax (Sets EAX to 0)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AND — Bitwise AND (used for masking).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: and al, 0x0f (Isolates the 4 lower bits)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OR — Bitwise OR (used to set specific bits).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: or eax, 0xa (Forces specific bits to 1)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NOT — Bitwise NOT (one's complement, flips all bits).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: not eax (Flips all 0s to 1s and vice versa)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NOP (No Operation) — Does nothing (frequently used for patching instructions).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: nop (Advances to the next instruction)&lt;/li&gt;
&lt;/ul&gt;




&lt;h5&gt;
  
  
  5. Shifts &amp;amp; Rotations (Crypto/Hash) (24–29)
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;SHL / SAL (Shift Left) — Logical left shift (multiplies by 2^n).
Example: shl rax, 4 (Multiplies RAX by 16)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SHR (Shift Right) — Logical right shift (divides unsigned integer by 2^n).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: shr eax, 4 (Shifts 4 bits to the right)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SAR (Shift Arithmetic Right) — Arithmetic right shift (preserves the sign bit).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: sar eax, 2 (Signed division by 4)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ROL (Rotate Left) — Rotates bits to the left.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: rol rbx, 8 (Rotates bits 8 positions to the left)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ROR (Rotate Right) — Rotates bits to the right.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: ror rbx, 8 (Rotates bits 8 positions to the right)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SETcc (Set Byte on Condition: SETE, SETNE, etc.) — Sets a byte to 1 or 0 based on RFLAGS.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: setz al (Sets AL to 1 if the Zero Flag is set)&lt;/li&gt;
&lt;/ul&gt;




&lt;h5&gt;
  
  
  6. Comparisons &amp;amp; Tests (30–32)
&lt;/h5&gt;

&lt;p&gt;CMP (Compare) — Subtracts the source from the destination internally and updates RFLAGS without modifying the operands.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: cmp ax, 0xf (Compares AX with 15)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TEST — Performs a bitwise AND internally and updates RFLAGS (notably setting ZF if the result is zero).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: test al, al (Checks if AL is zero or negative)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BT (Bit Test) — Copies the value of a specific bit into the Carry Flag (CF).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: bt eax, 3 (Tests the 3rd bit of EAX)&lt;/li&gt;
&lt;/ul&gt;




&lt;h5&gt;
  
  
  7. Unconditional &amp;amp; Conditional Jumps (33–44)
&lt;/h5&gt;

&lt;p&gt;JMP (Unconditional Jump) — Jumps to the specified target address unconditionally.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jmp 0x4001f9 (Jumps directly to address 0x4001f9)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JE / JZ (Jump if Equal / Zero) — Jumps if ZF = 1.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: je 0x400235 (Jumps if the previous test resulted in equality)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JNE / JNZ (Jump if Not Equal / Not Zero) — Jumps if ZF = 0.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jne 0x400235 (Jumps to the failure block if non-equal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JG / JNLE (Jump if Greater) — Signed jump if target &amp;gt; source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jg 0x401000 (Jumps if A &amp;gt; B)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JGE / JNL (Jump if Greater or Equal) — Signed jump if target &amp;gt;= source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jge 0x401000 (Jumps if A &amp;gt;= B)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JL / JNGE (Jump if Less) — Signed jump if target &amp;lt; source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jl 0x401000 (Jumps if A &amp;lt; B)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JLE / JNG (Jump if Less or Equal) — Signed jump if target &amp;lt;= source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jle 0x401000 (Jumps if A &amp;lt;= B)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JA / JNBE (Jump if Above) — Unsigned jump if target &amp;gt; source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: ja 0x40013f (Jumps if A &amp;gt; B in unsigned comparison)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JAE / JNB (Jump if Above or Equal) — Unsigned jump if target &amp;gt;= source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jae 0x40013f (Jumps if A &amp;gt;= B)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JB / JNAE (Jump if Below) — Unsigned jump if target &amp;lt; source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jb 0x40013f (Jumps if A &amp;lt; B in unsigned comparison)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JBE / JNA (Jump if Below or Equal) — Unsigned jump if target &amp;lt;= source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: jbe 0x40013f (Jumps if A &amp;lt;= B)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;JS / JNS (Jump if Sign / No Sign) — Jumps if the result is negative (SF = 1).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: js 0x400235 (Jumps if the sign flag is set)&lt;/li&gt;
&lt;/ul&gt;




&lt;h5&gt;
  
  
  8.  Function Calls &amp;amp; Control Flow (45–47)
&lt;/h5&gt;

&lt;p&gt;CALL — Pushes the return address onto the stack and jumps to the target procedure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: call 0x4000fe (Calls the validation function)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RET (Return) — Pops the return address off the stack and jumps to it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: ret (Returns from the current function)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SYSCALL — Triggers a kernel system call specified by the number in RAX.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: syscall (Executes the configured system call)&lt;/li&gt;
&lt;/ul&gt;




&lt;h5&gt;
  
  
  9. String Operations &amp;amp; Loops (48–50)
&lt;/h5&gt;

&lt;p&gt;LOOP — Decrements RCX and jumps to the target address if RCX != 0.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: loop 0x401020 (Loops until RCX reaches zero)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;REP MOVSB — Moves a block of memory from RSI to RDI for RCX bytes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: rep movsb (Copies a string byte by byte)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;STOSB — Stores the byte in AL into the memory address pointed to by RDI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: rep stosb (Fills a memory region with a constant byte / memset)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Epilogue
&lt;/h3&gt;

&lt;p&gt;In this introductory post, I aimed to provide the essential foundations needed to approach a crackme with confidence. &lt;br&gt;
As we progress through upcoming articles, you will notice that these 50 instructions are the ones that appear repeatedly.&lt;br&gt;
In the next post, we will tackle a relatively simple crackme, and I will walk you through the exact methodology I use to save time when analyzing binaries.&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Crackmes: The Basics</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Fri, 28 Aug 2026 01:52:33 +0000</pubDate>
      <link>https://dev.to/ddupard/crackmes-the-basics-hpk</link>
      <guid>https://dev.to/ddupard/crackmes-the-basics-hpk</guid>
      <description>&lt;p&gt;Crackmes are a rite of passage for anyone looking to become a reverse engineering professional. Becoming exceptionally good in this field is primarily about building solid habits and learning to recognize assembly patterns. There is no secret formula: you have to practice, practice, and practice some more.&lt;/p&gt;

&lt;p&gt;Today, I am going to introduce you to the simplest crackmes you can find on &lt;a href="https://crackmes.one" rel="noopener noreferrer"&gt;https://crackmes.one&lt;/a&gt;. This site is truly fantastic—hats off to the creators behind the idea.&lt;br&gt;
The crackmes range from Level 1 to Level 6, with Level 1 being the easiest. For the first crackmes, I will select the Assembly, x86_64, and Linux options. But for more advanced crackmes, I will choose Windows crackmes because they are much more numerous.&lt;/p&gt;

&lt;p&gt;For our example today, I will pick BitFriends' nasm_crack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsjvrax434whcnj0b2s0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsjvrax434whcnj0b2s0j.png" alt=" " width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download it into a working directory and unpack it using the password crackmes.one. Don't do what I did on my very first crackme: having skipped the FAQ, I found myself disassembly-debugging the ZIP file itself and trying to brute-force the archive password! The actual files you need to crack are inside the ZIP archive, not the archive itself.&lt;/p&gt;

&lt;p&gt;For context—even though I am a bit rusty—back in the 90s I was reversing the Windows kernel, and during the 80s I went through a phase of cracking video games, followed by a period analyzing viruses. I am not at the level of someone who does this day in and day out, but I am certainly no beginner either. Reversing some of these crackmes actually brings back memories of tricks that were already being used back in the video game era.&lt;/p&gt;

&lt;p&gt;To streamline my disassembly process, I created a Python pipeline that outputs clean disassembly files (*.objdump_clean). Combined with custom syntax highlighting rules in VS Code, I get disassembly files where the key elements to inspect jump out immediately.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqy9mvmncfif0i2goee2v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqy9mvmncfif0i2goee2v.png" alt=" " width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that I also reverse engineer binaries on other processor architectures (RISC-V, 8051, etc.), and I maintain dedicated syntax highlighting profiles for each target ISA.&lt;br&gt;
I have also built a customized GDB environment (myGDB) on top of pwndbg, enhanced with my own custom commands, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a command to query my personal local knowledge base (doc command)&lt;/li&gt;
&lt;li&gt;a command to invoke AI assistance (ia command)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuyn7xis7f7a7qhtbulgy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuyn7xis7f7a7qhtbulgy.png" alt=" " width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That said, I only fire up myGDB when strictly necessary—I vastly prefer reading the raw disassembly directly whenever possible.&lt;br&gt;
For this first example, however, we won't even need all of that tooling. My baseline rule whenever I approach a new binary is to run the following two commands first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hexdump -C XXXX&lt;/li&gt;
&lt;li&gt;readelf -a XXXX&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(where XXXX is the name of the executable to reverse).&lt;/p&gt;

&lt;p&gt;Running hexdump -C nasm_crack yields the following output, where we immediately recognize the ELF header right at the beginning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  02 00 3e 00 01 00 00 00  28 10 40 00 00 00 00 00  |..&amp;gt;.....(.@.....|
00000020  40 00 00 00 00 00 00 00  58 22 00 00 00 00 00 00  |@.......X"......|
00000030  00 00 00 00 40 00 38 00  03 00 40 00 06 00 05 00  |....@.8...@.....|
00000040  01 00 00 00 04 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  00 00 40 00 00 00 00 00  00 00 40 00 00 00 00 00  |..@.......@.....|
00000060  e8 00 00 00 00 00 00 00  e8 00 00 00 00 00 00 00  |................|
00000070  00 10 00 00 00 00 00 00  01 00 00 00 05 00 00 00  |................|
00000080  00 10 00 00 00 00 00 00  00 10 40 00 00 00 00 00  |..........@.....|
00000090  00 10 40 00 00 00 00 00  a2 00 00 00 00 00 00 00  |..@.............|
000000a0  a2 00 00 00 00 00 00 00  00 10 00 00 00 00 00 00  |................|
000000b0  01 00 00 00 06 00 00 00  00 20 00 00 00 00 00 00  |......... ......|
000000c0  00 20 40 00 00 00 00 00  00 20 40 00 00 00 00 00  |. @...... @.....|
000000d0  31 00 00 00 00 00 00 00  31 00 00 00 00 00 00 00  |1.......1.......|
000000e0  00 10 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000  b8 01 00 00 00 bf 01 00  00 00 48 be 16 20 40 00  |..........H.. @.|
00001010  00 00 00 00 ba 09 00 00  00 0f 05 b8 3c 00 00 00  |............&amp;lt;...|
00001020  bf 00 00 00 00 0f 05 c3  b8 01 00 00 00 bf 01 00  |................|
00001030  00 00 48 be 00 20 40 00  00 00 00 00 ba 16 00 00  |..H.. @.........|
00001040  00 0f 05 b8 00 00 00 00  bf 00 00 00 00 48 be 31  |.............H.1|
00001050  20 40 00 00 00 00 00 ba  10 00 00 00 0f 05 48 bf  | @............H.|
00001060  26 20 40 00 00 00 00 00  48 be 31 20 40 00 00 00  |&amp;amp; @.....H.1 @...|
00001070  00 00 b9 0b 00 00 00 f3  a6 74 85 b8 01 00 00 00  |.........t......|
00001080  bf 01 00 00 00 48 be 1f  20 40 00 00 00 00 00 ba  |.....H.. @......|
00001090  07 00 00 00 0f 05 b8 3c  00 00 00 bf 00 00 00 00  |.......&amp;lt;........|
000010a0  0f 05 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000010b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00002000  45 6e 74 65 72 20 79 6f  75 72 20 70 61 73 73 77  |Enter your passw|
00002010  6f 72 64 3a 20 00 43 6f  72 72 65 63 74 21 0a 57  |ord: .Correct!.W|
00002020  72 6f 6e 67 21 0a 73 75  70 65 72 73 65 63 72 65  |rong!.supersecre|
00002030  74 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |t...............|
00002040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00002050  00 00 00 00 03 00 01 00  00 10 40 00 00 00 00 00  |..........@.....|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting part is located at address 00002000. We can see "Enter your password: ", followed by "Correct!", then "Wrong!", and finally "supersecret".&lt;/p&gt;

&lt;p&gt;If you launch ./nasm_crack, it prompts you for your password. Entering supersecret yields the expected validation:&lt;/p&gt;

&lt;p&gt;Enter your password: supersecret&lt;br&gt;&lt;br&gt;
Correct!&lt;/p&gt;

&lt;h3&gt;
  
  
  Under the hood
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nasm_crack:     file format elf64-x86-64


Disassembly of section .text:

0000000000401000 &amp;lt;correct_func&amp;gt;:
401000:  mov    eax,0x1        # eax = 1
401005:  mov    edi,0x1        # edi = 1 
40100a:  movabs rsi,0x402016   #  Correct!
401014:  mov    edx,0x9        # we print 9 chars 
401019:  syscall                


40101b:  mov    eax,0x3c        # eax = 0x3c    
401020:  mov    edi,0x0
401025:  syscall                # sys_exit
401027:  ret

0000000000401028 &amp;lt;_start&amp;gt;:
401028:  mov    eax,0x1        # eax = 1
40102d:  mov    edi,0x1        # edi = 1
401032:  movabs rsi,0x402000   # "Enter your password: "
40103c:  mov    edx,0x16       # we print 0x16 = 22 chars  
401041:  syscall            # sys_write


401043:  mov    eax,0x0      # eax = 0    
401048:  mov    edi,0x0       
40104d:  movabs rsi,0x402031 #  0x402031 where the password will be stored
401057:  mov    edx,0x10     # no more than 0x10 = 16 chars entered   
40105c:  syscall             # sys_read   


# loop of comparison between the password which have been stored in 0x402031
# and the password stored in 0x402026 for 0xb = 11 chars 
40105e:  movabs rdi,0x402026 
401068:  movabs rsi,0x402031
401072:  mov    ecx,0xb
401077:  repz cmps BYTE PTR ds:[rsi],BYTE PTR es:[rdi]
401079:  je     401000 &amp;lt;correct_func&amp;gt; # if the password entered and the password stored we go to Correct_func 


40107b:  mov    eax,0x1
401080:  mov    edi,0x1
401085:  movabs rsi,0x40201f
40108f:  mov    edx,0x7
401094:  syscall
401096:  mov    eax,0x3c
40109b:  mov    edi,0x0
4010a0:  syscall
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most essential takeaway for a beginner crackme analysis is understanding the Linux x86_64 system call interface:&lt;/p&gt;

&lt;p&gt;sys_write&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;eax = 1&lt;/li&gt;
&lt;li&gt;edi = 1 (standard output)&lt;/li&gt;
&lt;li&gt;rsi = address of the string to print&lt;/li&gt;
&lt;li&gt;edx = byte count to print&lt;/li&gt;
&lt;li&gt;syscall&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;sys_read&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;eax = 0&lt;/li&gt;
&lt;li&gt;edi = 0 (standard input)&lt;/li&gt;
&lt;li&gt;rsi = target buffer address for entered string&lt;/li&gt;
&lt;li&gt;edx = maximum allowed byte count&lt;/li&gt;
&lt;li&gt;syscall&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;sys_exit&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;eax = 0x3c&lt;/li&gt;
&lt;li&gt;edi = exit status code&lt;/li&gt;
&lt;li&gt;syscall&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>X86_64 From Source Code to Binary: What Does GCC Actually Do ? DEP / NX</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Sun, 23 Aug 2026 22:44:04 +0000</pubDate>
      <link>https://dev.to/ddupard/x8664-from-source-code-to-binary-what-does-gcc-actually-do-dep-nx-1be7</link>
      <guid>https://dev.to/ddupard/x8664-from-source-code-to-binary-what-does-gcc-actually-do-dep-nx-1be7</guid>
      <description>&lt;p&gt;Having explained how GCC options like -fstack-protector works in my preceding article , it's time to explain how to set the stack non executable and what does that mean.&lt;/p&gt;

&lt;p&gt;To illustrate this, I will use the following program :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;arpa/inet.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define PORT 8080
#define BUFFER_SIZE 64
&lt;/span&gt;
&lt;span class="cp"&gt;#define _NOTEST 
&lt;/span&gt;

&lt;span class="cp"&gt;#ifndef _NOTEST
&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test1"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;t1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;test2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test2&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;buffer2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;strcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;buffer1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;buffer2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif
&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * handle_client: Processes incoming connections.
 * This function contains a deliberate stack-based buffer overflow 
 * vulnerability for educational purposes.
 */&lt;/span&gt;


&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;BUFFER_SIZE&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Read the incoming request from the client&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bytes_received&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes_received&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;bytes_received&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="cm"&gt;/* * THE VULNERABILITY: 
         * strcpy() does not perform bounds checking. If 'request' 
         * exceeds 64 bytes, it will overflow 'buffer' and overwrite 
         * critical data on the stack, including the saved return address.
         */&lt;/span&gt;
        &lt;span class="n"&gt;strcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="cp"&gt;#ifndef _NOTEST
&lt;/span&gt;        &lt;span class="n"&gt;test1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;test2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="cp"&gt;#endif
&lt;/span&gt;


    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;server_fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;sockaddr_in&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;htons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;INADDR_ANY&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Bind the socket to the port and start listening&lt;/span&gt;
    &lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;sockaddr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server listening on port %d...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;client_socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server_fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;handle_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This program will be compiled with GCC and the binary generated will be disassembled by objdump using the following commands&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server.objdump_clean"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fno-stack-protector&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; execstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt;  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/buffer_overflow/C/server.c"&lt;/span&gt;
    objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server.objdump"&lt;/span&gt;
    python3 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ATP&lt;/span&gt;&lt;span class="s2"&gt;/clean_objdump.py"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server.objdump"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server.objdump_clean"&lt;/span&gt;
    readelf &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server.readelf"&lt;/span&gt;
&lt;span class="k"&gt;fi

if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server_sNX.objdump_clean"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;gcc &lt;span class="nt"&gt;-g&lt;/span&gt;  &lt;span class="nt"&gt;-fno-stack-protector&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; noexecstack &lt;span class="nt"&gt;-no-pie&lt;/span&gt;  &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server_sNX"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/buffer_overflow/C/server.c"&lt;/span&gt;
    objdump &lt;span class="nt"&gt;-M&lt;/span&gt; intel &lt;span class="nt"&gt;--show-raw-insn&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server_sNX"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server_sNX.objdump"&lt;/span&gt;
    python3 &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ATP&lt;/span&gt;&lt;span class="s2"&gt;/clean_objdump.py"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server_sNX.objdump"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server_sNX.objdump_clean"&lt;/span&gt;
    readelf &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OUT&lt;/span&gt;&lt;span class="s2"&gt;/gcc_4/server-sNX.readelf"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The option ( -M intel ) forces the intel convention in the disasssembling process. I prefer the intel convetion over the ATT convention. &lt;/p&gt;

&lt;h3&gt;
  
  
  1.  The stack based buffer overflow mechanism
&lt;/h3&gt;

&lt;p&gt;A "buffer overflow" occurs when a program writes more data to a buffer than its allocated capacity, overwriting adjacent memory and resulting in the corruption of adjacent memory —most notably the saved return address on the stack. It can happen when using functions like strcpy, memcpy, ..&lt;br&gt;
Buffers can be allocated on stack so we use the term stack based buffer overflow or on heap and we use the term Heap buffer overflow.&lt;/p&gt;

&lt;p&gt;For example in our C program, we copy the information found in request (256 bytes) in a buffer containing only 64 bytes using the following line&lt;br&gt;
strcpy(buffer, request);&lt;br&gt;
This results to a corruption of the stack which normally contains the return address of the function, so an attacker by modifying the return address can change the execution flow of the program and execute an arbitrary code.&lt;br&gt;&lt;br&gt;
Since this buffer is allocated on stack using a local variable, we are creating a stack based buffer overflow.&lt;/p&gt;

&lt;p&gt;but let's start with GCC options&lt;/p&gt;
&lt;h3&gt;
  
  
  2.  -z execstack
&lt;/h3&gt;

&lt;p&gt;The GCC -z option makes the following options passed to the linker. &lt;/p&gt;

&lt;p&gt;The execstack option removes the default linker mechanism of protecting programs from executing code from the stack. This is only useful to study the stack based buffer overflow mechanism and I don't see any other reason to have this option set when compiling a program.   &lt;/p&gt;

&lt;p&gt;see the assembly below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401236 &amp;lt;handle_client&amp;gt;:
401236:  endbr64
40123a:  push   rbp
40123b:  mov    rbp,rsp
40123e:  sub    rsp,0x160
401245:  mov    DWORD PTR [rbp-0x154],edi
40124b:  lea    rsi,[rbp-0x150]
401252:  mov    eax,DWORD PTR [rbp-0x154]
401258:  mov    ecx,0x0
40125d:  mov    edx,0xff
401262:  mov    edi,eax
401264:  call   4010c0 &amp;lt;recv@plt&amp;gt;
401269:  mov    DWORD PTR [rbp-0x4],eax
40126c:  cmp    DWORD PTR [rbp-0x4],0x0
401270:  jle    4012b0 &amp;lt;handle_client+0x7a&amp;gt;
401272:  mov    eax,DWORD PTR [rbp-0x4]
401275:  cdqe
401277:  mov    BYTE PTR [rbp+rax*1-0x150],0x0
40127f:  lea    rdx,[rbp-0x150]
401286:  lea    rax,[rbp-0x50]
40128a:  mov    rsi,rdx
40128d:  mov    rdi,rax
401290:  call   4010d0 &amp;lt;strcpy@plt&amp;gt;
401295:  lea    rax,[rbp-0x50]
401299:  mov    rsi,rax
40129c:  lea    rax,[rip+0xd65]        # 402008 &amp;lt;_IO_stdin_used+0x8&amp;gt;
4012a3:  mov    rdi,rax
4012a6:  mov    eax,0x0
4012ab:  call   4010f0 &amp;lt;printf@plt&amp;gt;
4012b0:  mov    eax,DWORD PTR [rbp-0x154]
4012b6:  mov    edi,eax
4012b8:  call   401100 &amp;lt;close@plt&amp;gt;
4012bd:  nop
4012be:  leave
4012bf:  ret

00000000004012c0 &amp;lt;main&amp;gt;:
4012c0:  endbr64
4012c4:  push   rbp
4012c5:  mov    rbp,rsp
4012c8:  sub    rsp,0x20
4012cc:  mov    edx,0x0
4012d1:  mov    esi,0x1
4012d6:  mov    edi,0x2
4012db:  call   401140 &amp;lt;socket@plt&amp;gt;
4012e0:  mov    DWORD PTR [rbp-0x4],eax
4012e3:  mov    QWORD PTR [rbp-0x20],0x0
4012eb:  mov    QWORD PTR [rbp-0x18],0x0
4012f3:  mov    WORD PTR [rbp-0x20],0x2
4012f9:  mov    edi,0x1f90
4012fe:  call   4010e0 &amp;lt;htons@plt&amp;gt;
401303:  mov    WORD PTR [rbp-0x1e],ax
401307:  lea    rcx,[rbp-0x20]
40130b:  mov    eax,DWORD PTR [rbp-0x4]
40130e:  mov    edx,0x10
401313:  mov    rsi,rcx
401316:  mov    edi,eax
401318:  call   401120 &amp;lt;bind@plt&amp;gt;
40131d:  mov    eax,DWORD PTR [rbp-0x4]
401320:  mov    esi,0x3
401325:  mov    edi,eax
401327:  call   401110 &amp;lt;listen@plt&amp;gt;
40132c:  mov    esi,0x1f90
401331:  lea    rax,[rip+0xce0]        # 402018 &amp;lt;_IO_stdin_used+0x18&amp;gt;
401338:  mov    rdi,rax
40133b:  mov    eax,0x0
401340:  call   4010f0 &amp;lt;printf@plt&amp;gt;
401345:  mov    eax,DWORD PTR [rbp-0x4]
401348:  mov    edx,0x0
40134d:  mov    esi,0x0
401352:  mov    edi,eax
401354:  call   401130 &amp;lt;accept@plt&amp;gt;
401359:  mov    DWORD PTR [rbp-0x8],eax
40135c:  mov    eax,DWORD PTR [rbp-0x8]
40135f:  mov    edi,eax
401361:  call   401236 &amp;lt;handle_client&amp;gt;
401366:  nop
401367:  jmp    401345 &amp;lt;main+0x85&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the program headers&lt;/p&gt;

&lt;p&gt;Elf file type is EXEC (Executable file)&lt;br&gt;
Entry point 0x401150&lt;br&gt;
There are 13 program headers, starting at offset 64&lt;/p&gt;

&lt;p&gt;Program Headers:&lt;br&gt;
  Type           Offset             VirtAddr           PhysAddr&lt;br&gt;
                 FileSiz            MemSiz              Flags  Align&lt;br&gt;
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040&lt;br&gt;
                 0x00000000000002d8 0x00000000000002d8  R      0x8&lt;br&gt;
  INTERP         0x0000000000000318 0x0000000000400318 0x0000000000400318&lt;br&gt;
                 0x000000000000001c 0x000000000000001c  R      0x1&lt;br&gt;
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]&lt;br&gt;
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000&lt;br&gt;
                 0x00000000000006c0 0x00000000000006c0  R      0x1000&lt;br&gt;
  LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000&lt;br&gt;
                 0x0000000000000379 0x0000000000000379  R E    0x1000&lt;br&gt;
  LOAD           0x0000000000002000 0x0000000000402000 0x0000000000402000&lt;br&gt;
                 0x0000000000000138 0x0000000000000138  R      0x1000&lt;br&gt;
  LOAD           0x0000000000002df8 0x0000000000403df8 0x0000000000403df8&lt;br&gt;
                 0x0000000000000260 0x0000000000000268  RW     0x1000&lt;br&gt;
  DYNAMIC        0x0000000000002e08 0x0000000000403e08 0x0000000000403e08&lt;br&gt;
                 0x00000000000001d0 0x00000000000001d0  RW     0x8&lt;br&gt;
  NOTE           0x0000000000000338 0x0000000000400338 0x0000000000400338&lt;br&gt;
                 0x0000000000000030 0x0000000000000030  R      0x8&lt;br&gt;
  NOTE           0x0000000000000368 0x0000000000400368 0x0000000000400368&lt;br&gt;
                 0x0000000000000044 0x0000000000000044  R      0x4&lt;br&gt;
  GNU_PROPERTY   0x0000000000000338 0x0000000000400338 0x0000000000400338&lt;br&gt;
                 0x0000000000000030 0x0000000000000030  R      0x8&lt;br&gt;
  GNU_EH_FRAME   0x0000000000002038 0x0000000000402038 0x0000000000402038&lt;br&gt;
                 0x000000000000003c 0x000000000000003c  R      0x4&lt;br&gt;
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000&lt;br&gt;
                 0x0000000000000000 0x0000000000000000  RWE    0x10&lt;br&gt;
  GNU_RELRO      0x0000000000002df8 0x0000000000403df8 0x0000000000403df8&lt;br&gt;
                 0x0000000000000208 0x0000000000000208  R      0x1&lt;/p&gt;

&lt;p&gt;The GNU_STACK is set to RWE.&lt;/p&gt;

&lt;p&gt;What components do we find in an ELF ? &lt;/p&gt;

&lt;p&gt;An ELF (Executable and Linkable Format) file is structured as a series of specific components, each serving a different purpose depending on whether the file is being linked or executed.  The main components you will encounter are:  &lt;/p&gt;

&lt;p&gt;ELF Header: This is the very beginning of the file. It acts as the "ID card" of the file, containing information such as the architecture (x86_64, ARM, etc.), the entry point address, and the offsets to both the Program Header Table and the Section Header Table.  &lt;/p&gt;

&lt;p&gt;Program Header Table: This table is mandatory for execution. It contains an array of segments that tell the OS loader how to map the file into memory to create a process. Each entry defines memory permissions (R, W, X) and which sections belong to which segment.  &lt;/p&gt;

&lt;p&gt;Sections: These are logical groupings of data within the file used primarily for linking and compilation. Examples include:  .text: Contains the executable machine code instructions.  .data: Stores initialized global and static variables.  .bss: Holds uninitialized global and static variables.  .rodata: Contains read-only data, such as constant strings.  .got / .plt: Sections used for dynamic linking and resolving addresses of external library functions.  &lt;/p&gt;

&lt;p&gt;Section Header Table: This table provides an index of all sections in the file. It is primarily used by tools like ld (the linker) and readelf for debugging or analysis. It is not strictly required by the OS to execute the program.  Symbol Table: This table maps variable and function names to their corresponding addresses in the binary, which is essential for debugging and relocation.  &lt;/p&gt;

&lt;p&gt;What are program Headers ?&lt;/p&gt;

&lt;p&gt;The Program Headers in an ELF file serve as the blueprint that tells the Operating System's dynamic linker or loader exactly how to map the file's contents into memory to create an executable process.  &lt;/p&gt;

&lt;p&gt;While Section Headers are primarily for linking and debugging, Program Headers are essential for execution. &lt;/p&gt;

&lt;p&gt;Here is their core role:&lt;br&gt;&lt;br&gt;
Memory Mapping (Segments): They define "segments," which are groups of sections (like .text, .data, and .bss) that share the same memory permissions (Read, Write, Execute). The loader uses this information to map these chunks of the file into the process's virtual address space.  &lt;/p&gt;

&lt;p&gt;Defining Permissions: Program headers specify the access rights for each segment (e.g., the code segment must be R-X, while the data segment is RW-). This is how the system enforces security policies like NX/DEP.  &lt;/p&gt;

&lt;p&gt;Dynamic Linking: They contain the PT_DYNAMIC segment, which tells the loader which shared libraries (like libc) are required and where the dynamic linking information (like the GOT and PLT) is located.  &lt;/p&gt;

&lt;p&gt;Stack Configuration: As discussed, the PT_GNU_STACK header specifically instructs the kernel on whether the stack should be initialized with executable permissions.  &lt;/p&gt;

&lt;p&gt;Interpreter Specification: The PT_INTERP segment identifies the path to the program interpreter (the dynamic linker, usually /lib64/ld-linux-x86-64.so.2) that should be invoked to load the binary's dependencies.  In short, without the Program Headers, the kernel would not know where to start the program, which libraries to load, or how to protect the memory segments from being misused.  &lt;/p&gt;
&lt;h3&gt;
  
  
  3. -z noexecstack
&lt;/h3&gt;

&lt;p&gt;The GCC -z option makes the following options passed to the linker. Let see what the linker man page says about the  noexecstack option&lt;/p&gt;

&lt;p&gt;noexecstack&lt;br&gt;
    Marks the object as not requiring executable stack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0000000000401236 &amp;lt;handle_client&amp;gt;:
401236:  endbr64
40123a:  push   rbp
40123b:  mov    rbp,rsp
40123e:  sub    rsp,0x160
401245:  mov    DWORD PTR [rbp-0x154],edi
40124b:  lea    rsi,[rbp-0x150]
401252:  mov    eax,DWORD PTR [rbp-0x154]
401258:  mov    ecx,0x0
40125d:  mov    edx,0xff
401262:  mov    edi,eax
401264:  call   4010c0 &amp;lt;recv@plt&amp;gt;
401269:  mov    DWORD PTR [rbp-0x4],eax
40126c:  cmp    DWORD PTR [rbp-0x4],0x0
401270:  jle    4012b0 &amp;lt;handle_client+0x7a&amp;gt;
401272:  mov    eax,DWORD PTR [rbp-0x4]
401275:  cdqe
401277:  mov    BYTE PTR [rbp+rax*1-0x150],0x0
40127f:  lea    rdx,[rbp-0x150]
401286:  lea    rax,[rbp-0x50]
40128a:  mov    rsi,rdx
40128d:  mov    rdi,rax
401290:  call   4010d0 &amp;lt;strcpy@plt&amp;gt;
401295:  lea    rax,[rbp-0x50]
401299:  mov    rsi,rax
40129c:  lea    rax,[rip+0xd65]        # 402008 &amp;lt;_IO_stdin_used+0x8&amp;gt;
4012a3:  mov    rdi,rax
4012a6:  mov    eax,0x0
4012ab:  call   4010f0 &amp;lt;printf@plt&amp;gt;
4012b0:  mov    eax,DWORD PTR [rbp-0x154]
4012b6:  mov    edi,eax
4012b8:  call   401100 &amp;lt;close@plt&amp;gt;
4012bd:  nop
4012be:  leave
4012bf:  ret

00000000004012c0 &amp;lt;main&amp;gt;:
4012c0:  endbr64
4012c4:  push   rbp
4012c5:  mov    rbp,rsp
4012c8:  sub    rsp,0x20
4012cc:  mov    edx,0x0
4012d1:  mov    esi,0x1
4012d6:  mov    edi,0x2
4012db:  call   401140 &amp;lt;socket@plt&amp;gt;
4012e0:  mov    DWORD PTR [rbp-0x4],eax
4012e3:  mov    QWORD PTR [rbp-0x20],0x0
4012eb:  mov    QWORD PTR [rbp-0x18],0x0
4012f3:  mov    WORD PTR [rbp-0x20],0x2
4012f9:  mov    edi,0x1f90
4012fe:  call   4010e0 &amp;lt;htons@plt&amp;gt;
401303:  mov    WORD PTR [rbp-0x1e],ax
401307:  lea    rcx,[rbp-0x20]
40130b:  mov    eax,DWORD PTR [rbp-0x4]
40130e:  mov    edx,0x10
401313:  mov    rsi,rcx
401316:  mov    edi,eax
401318:  call   401120 &amp;lt;bind@plt&amp;gt;
40131d:  mov    eax,DWORD PTR [rbp-0x4]
401320:  mov    esi,0x3
401325:  mov    edi,eax
401327:  call   401110 &amp;lt;listen@plt&amp;gt;
40132c:  mov    esi,0x1f90
401331:  lea    rax,[rip+0xce0]        # 402018 &amp;lt;_IO_stdin_used+0x18&amp;gt;
401338:  mov    rdi,rax
40133b:  mov    eax,0x0
401340:  call   4010f0 &amp;lt;printf@plt&amp;gt;
401345:  mov    eax,DWORD PTR [rbp-0x4]
401348:  mov    edx,0x0
40134d:  mov    esi,0x0
401352:  mov    edi,eax
401354:  call   401130 &amp;lt;accept@plt&amp;gt;
401359:  mov    DWORD PTR [rbp-0x8],eax
40135c:  mov    eax,DWORD PTR [rbp-0x8]
40135f:  mov    edi,eax
401361:  call   401236 &amp;lt;handle_client&amp;gt;
401366:  nop
401367:  jmp    401345 &amp;lt;main+0x85&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see there is no difference in the assembly between the -z execstack and the -z noexecstack options&lt;/p&gt;

&lt;p&gt;Elf file type is EXEC (Executable file)&lt;br&gt;
Entry point 0x401150&lt;br&gt;
There are 13 program headers, starting at offset 64&lt;/p&gt;

&lt;p&gt;Program Headers:&lt;br&gt;
  Type           Offset             VirtAddr           PhysAddr&lt;br&gt;
                 FileSiz            MemSiz              Flags  Align&lt;br&gt;
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040&lt;br&gt;
                 0x00000000000002d8 0x00000000000002d8  R      0x8&lt;br&gt;
  INTERP         0x0000000000000318 0x0000000000400318 0x0000000000400318&lt;br&gt;
                 0x000000000000001c 0x000000000000001c  R      0x1&lt;br&gt;
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]&lt;br&gt;
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000&lt;br&gt;
                 0x00000000000006c0 0x00000000000006c0  R      0x1000&lt;br&gt;
  LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000&lt;br&gt;
                 0x0000000000000379 0x0000000000000379  R E    0x1000&lt;br&gt;
  LOAD           0x0000000000002000 0x0000000000402000 0x0000000000402000&lt;br&gt;
                 0x0000000000000138 0x0000000000000138  R      0x1000&lt;br&gt;
  LOAD           0x0000000000002df8 0x0000000000403df8 0x0000000000403df8&lt;br&gt;
                 0x0000000000000260 0x0000000000000268  RW     0x1000&lt;br&gt;
  DYNAMIC        0x0000000000002e08 0x0000000000403e08 0x0000000000403e08&lt;br&gt;
                 0x00000000000001d0 0x00000000000001d0  RW     0x8&lt;br&gt;
  NOTE           0x0000000000000338 0x0000000000400338 0x0000000000400338&lt;br&gt;
                 0x0000000000000030 0x0000000000000030  R      0x8&lt;br&gt;
  NOTE           0x0000000000000368 0x0000000000400368 0x0000000000400368&lt;br&gt;
                 0x0000000000000044 0x0000000000000044  R      0x4&lt;br&gt;
  GNU_PROPERTY   0x0000000000000338 0x0000000000400338 0x0000000000400338&lt;br&gt;
                 0x0000000000000030 0x0000000000000030  R      0x8&lt;br&gt;
  GNU_EH_FRAME   0x0000000000002038 0x0000000000402038 0x0000000000402038&lt;br&gt;
                 0x000000000000003c 0x000000000000003c  R      0x4&lt;br&gt;
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000&lt;br&gt;
                 0x0000000000000000 0x0000000000000000  RW     0x10&lt;br&gt;
  GNU_RELRO      0x0000000000002df8 0x0000000000403df8 0x0000000000403df8&lt;br&gt;
                 0x0000000000000208 0x0000000000000208  R      0x1&lt;/p&gt;

&lt;p&gt;With the -znoexecstack option, the GNU_STACK is set to RW.&lt;br&gt;&lt;br&gt;
With the execstack option, the GNU_STACK is set to RWE.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. What does the Linux kernel do when GNU_STACK is RW?
&lt;/h3&gt;

&lt;p&gt;When the linker marks the PT_GNU_STACK program header with RW (Read/Write) instead of RWE (Read/Write/Execute) — via the -z noexecstack option — it instructs the operating system loader that the stack memory region must not contain executable code.  &lt;/p&gt;

&lt;p&gt;During the process creation (execve and dynamic loading phases), the Linux kernel translates these ELF program header flags into actual page table permissions for the virtual memory area (VMA) allocated to the stack:&lt;/p&gt;

&lt;h4&gt;
  
  
  A. Setting Page Table Attributes:
&lt;/h4&gt;

&lt;p&gt;The kernel allocates the stack pages and configures their page table entries (PTEs) with the Read and Write bits enabled, while explicitly setting the NX (No-Execute) bit (sometimes referred to as the XD bit on Intel architectures or XN on ARM) to 1.&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Hardware-Level Enforcement:
&lt;/h4&gt;

&lt;p&gt;Modern CPUs rely on the MMU to enforce memory protection. Because the NX bit is set on the stack's page entries, any attempt by the processor's instruction pointer (RIP on x86_64) to fetch and execute an instruction located within the stack address range triggers a Page Fault exception (specifically, a protection fault with error code indicating an instruction fetch violation).&lt;/p&gt;

&lt;h4&gt;
  
  
  C. Kernel Response (Segmentation Fault):
&lt;/h4&gt;

&lt;p&gt;When this CPU exception occurs, the Linux kernel intercepts it. Recognizing that the program attempted to execute code from a non-executable memory region, the kernel steps in to terminate the offending process abruptly for security reasons, usually resulting in a Segmentation fault (Core dumped).&lt;/p&gt;

&lt;p&gt;This hardware-backed enforcement forms the core of the NX/DEP (No-Execute / Data Execution Prevention) security mitigation. Even if an attacker successfully exploits a stack-based buffer overflow to inject malicious shellcode onto the stack, the CPU refuses to execute it, effectively neutralizing classic stack-based code injection attacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Epilogue
&lt;/h3&gt;

&lt;p&gt;The -z noexecstack option changes the GNU_STACK program header flags to RW, ensuring that the Linux kernel maps the stack without execution privileges, thereby protecting the application against shellcode injection on the stack.&lt;/p&gt;

&lt;p&gt;In the next articles of this series, we will continue to study the options GCC offers to protect a binary from attackers.   &lt;/p&gt;

</description>
      <category>c</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>security</category>
    </item>
    <item>
      <title>RISC-V 32-bit: What does GCC do? (Part 1)</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Fri, 21 Aug 2026 01:06:22 +0000</pubDate>
      <link>https://dev.to/ddupard/risc-v-32-bit-what-does-gcc-do-part-1-1cg9</link>
      <guid>https://dev.to/ddupard/risc-v-32-bit-what-does-gcc-do-part-1-1cg9</guid>
      <description>&lt;h3&gt;
  
  
  1. Introduction and Problem Statement
&lt;/h3&gt;

&lt;p&gt;A good way to learn what a compiler really does when transforming C source code into a binary is to disassemble the binary and compare it with the C source code. While this was traditionally true for 8-bit microcontrollers, it is equally insightful for modern 32-bit RISC architectures like RISC-V (RV32I).&lt;/p&gt;

&lt;p&gt;To test our 32-bit toolchain (GCC / Clang-LLVM), we will use the exact same Universal Test Corpus C source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;==========================================================================&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
 &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Universal&lt;/span&gt; &lt;span class="n"&gt;Test&lt;/span&gt; &lt;span class="n"&gt;Corpus&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;Heterogeneous&lt;/span&gt; &lt;span class="n"&gt;Architecture&lt;/span&gt; &lt;span class="n"&gt;Analysis&lt;/span&gt;          &lt;span class="o"&gt;*&lt;/span&gt;
 &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;==========================================================================&lt;/span&gt; &lt;span class="err"&gt;*/&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Global variables (testing absolute/relative addressing modes)&lt;/span&gt;
&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;global_var_32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xDEADBEEF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt;  &lt;span class="n"&gt;global_var_8&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt;    &lt;span class="kt"&gt;char&lt;/span&gt;     &lt;span class="n"&gt;string_const&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"TARGET_STRING"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Function with parameter passing and local variables (stack / Frame Pointer test)&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Basic and mixed arithmetic operations (8, 16, 32 bits)&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Avoid division by zero&lt;/span&gt;

    &lt;span class="c1"&gt;// Shift tests and logical operations (highly variable depending on ISAs)&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mh"&gt;0x55AA55AA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;global_var_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;local_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Main function grouping complex control flows&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Loop test (Conditional jumps, decrement, comparison tests)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Multiple branching test (Switch / Jump Table or cascaded if-else)&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_var_8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default:&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Function call (Stack management, save registers Link Register/PC)&lt;/span&gt;
    &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Pointer and indirect memory access test&lt;/span&gt;
    &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;global_var_32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Terminal infinite loop (classic for raw binaries / microcontrollers)&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To compile this code for a bare-metal RISC-V 32-bit target (RV32I), we use the official GNU toolchain (riscv64-unknown-elf-gcc or riscv32-unknown-elf-gcc with -mabi=ilp32 -march=rv32i flags):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;riscv32-unknown-elf-gcc &lt;span class="nt"&gt;-O0&lt;/span&gt; &lt;span class="nt"&gt;-mabi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ilp32 &lt;span class="nt"&gt;-march&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rv32i &lt;span class="nt"&gt;-nostartfiles&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; link.ld &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/test1.c"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"32/test1_rv32i.elf"&lt;/span&gt;
riscv32-unknown-elf-objcopy &lt;span class="nt"&gt;-O&lt;/span&gt; binary &lt;span class="s2"&gt;"32/test1_rv32i.elf"&lt;/span&gt; &lt;span class="s2"&gt;"32/bin/test1_rv32i.bin"&lt;/span&gt;
riscv32-unknown-elf-objdump &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"32/test1_rv32i.elf"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"32/test1_rv32i.asm"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To simulate and analyze the execution step-by-step, we use QEMU for RISC-V (qemu-system-riscv32 or qemu-riscv32) linked with gdb-multiarch.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. RISC-V 32-bit (RV32I) Presentation
&lt;/h3&gt;

&lt;p&gt;Unlike legacy architectures, RISC-V is an open-standard Instruction Set Architecture (ISA) designed around strict Load-Store RISC principles. In its base 32-bit variant (RV32I), the core provides 32 general-purpose 32-bit registers, making register allocation and compiler optimizations dramatically smoother than on 8-bit systems.&lt;/p&gt;

&lt;p&gt;Here is a concise list of the core RV32I registers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;x0 (zero): Hardwired to constant 0. Any write to x0 is discarded.&lt;/li&gt;
&lt;li&gt;x1 (ra): Return Address register, set automatically by call instructions (jal/jalr).&lt;/li&gt;
&lt;li&gt;x2 (sp): Stack Pointer, pointing to the current boundary of the stack.&lt;/li&gt;
&lt;li&gt;x3 (gp) &amp;amp; x4 (tp): Global Pointer and Thread Pointer for memory/thread addressing.&lt;/li&gt;
&lt;li&gt;x5 – x7 &amp;amp; x28 – x31 (t0–t6): Temporary registers used for intermediate calculations.&lt;/li&gt;
&lt;li&gt;x8 (s0/fp) &amp;amp; x9, x18 – x27 (s1–s11): Saved registers (preserved across function calls) / Frame Pointer.&lt;/li&gt;
&lt;li&gt;x10 – x11 (a0–a1): Function arguments / Return values.&lt;/li&gt;
&lt;li&gt;x12 – x17 (a2–a7): Function arguments.&lt;/li&gt;
&lt;li&gt;PC (Program Counter): Tracks the address of the current instruction being executed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that there are no dedicated condition flag registers (like PSW in 8051 or EFLAGS in x86). In RISC-V, conditional branches directly compare two registers (beq, bne, blt, bge), eliminating hidden pipeline state dependencies.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. The RISC-V Instruction Set (RV32I)
&lt;/h3&gt;

&lt;p&gt;The base RV32I instruction set is minimalist, containing only 40 fundamental instructions, all strictly fixed at 32 bits (4 bytes) in length and aligned on 4-byte boundaries.&lt;/p&gt;

&lt;h5&gt;
  
  
  A. Data Transfer / Load-Store Instructions
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;LB / LH / LW – Load Byte / Halfword / Word from RAM into register.&lt;/li&gt;
&lt;li&gt;LBU / LHU – Load Byte / Halfword unsigned.&lt;/li&gt;
&lt;li&gt;SB / SH / SW – Store Byte / Halfword / Word from register to RAM.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  B. Arithmetic &amp;amp; Logical Instructions
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;ADD / ADDI – Add register or immediate value.&lt;/li&gt;
&lt;li&gt;SUB – Subtract registers.&lt;/li&gt;
&lt;li&gt;AND / ANDI – Bitwise AND (Register / Immediate).&lt;/li&gt;
&lt;li&gt;OR / ORI – Bitwise OR.&lt;/li&gt;
&lt;li&gt;XOR / XORI – Bitwise Exclusive-OR.&lt;/li&gt;
&lt;li&gt;SLT / SLTI / SLTU – Set on Less Than (Signed / Unsigned).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  C. Shift Instructions
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;SLL / SLLI – Shift Left Logical.&lt;/li&gt;
&lt;li&gt;SRL / SRLI – Shift Right Logical.&lt;/li&gt;
&lt;li&gt;SRA / SRAI – Shift Right Arithmetic (preserves sign bit).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  D. Upper Immediate &amp;amp; Address Generation
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;LUI – Load Upper Immediate (loads 20 bits into upper bits 31:12).&lt;/li&gt;
&lt;li&gt;AUIPC – Add Upper Immediate to PC (essential for PC-relative addressing).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  E. Program Branching &amp;amp; Control Transfer
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;JAL – Jump and Link (Unconditional jump + save return PC to ra).&lt;/li&gt;
&lt;li&gt;JALR – Jump and Link Register (Indirect jump via register).&lt;/li&gt;
&lt;li&gt;BEQ / BNE – Branch if Equal / Not Equal.&lt;/li&gt;
&lt;li&gt;BLT / BGE – Branch if Less Than / Greater Than or Equal (Signed).&lt;/li&gt;
&lt;li&gt;BLTU / BGEU – Branch if Less Than / Greater Than or Equal (Unsigned).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  F. Memory Synchronization
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;FENCE – Ordering fence for Memory and I/O accesses across threads/harts.&lt;/li&gt;
&lt;li&gt;FENCE.TSO – Total Store Ordering fence for stricter memory ordering rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  G. System &amp;amp; Control Register Access (CSR)
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;ECALL / EBREAK – Environment call (Syscall trap) / Breakpoint debugger entry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All RV32I instructions use a uniform 32-bit layout categorizable into 6 standard formats (R, I, S, B, U, J). The primary opcode is always fixed in bits [6:0], simplifying hardware instruction decoding.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Unprivileged Architecture Extensions Overview
&lt;/h3&gt;

&lt;p&gt;The modularity of the RISC-V ISA relies on fine-grained, ratified sub-extensions that complement the base integer set. Instead of monoliths, these standardized extensions allow hardware architects to tailor the processor for specific execution environments—ranging from instruction-cache management and low-power polling to fine-grained security primitives, vector cryptography, and specialized arithmetic—minimizing silicon area while maximizing domain-specific efficiency.&lt;/p&gt;

&lt;h4&gt;
  
  
  A. System, Control &amp;amp; Instruction Fetch
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zifencei&lt;/strong&gt; (Instruction-Fetch Fence) [v2.0, Ratified]:&lt;br&gt;
Domain: Instruction cache consistency and self-modifying code support.&lt;br&gt;
Instructions: 1 instruction (FENCE.I).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zicsr&lt;/strong&gt; (Control and Status Register Access) [v2.0, Ratified]:&lt;br&gt;
Domain: Access and manipulation of hardware CSRs.&lt;br&gt;
Instructions: 6 instructions (CSRRW, CSRRS, CSRRC, CSRRWI, CSRRSI, CSRRCI).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zicntr&lt;/strong&gt; (Base Counters and Timers) [v2.0, Ratified]:&lt;br&gt;
Domain: Unprivileged access to execution counters (cycle, time, instret).&lt;br&gt;
Instructions: 0 new instructions (uses CSRRS mappings to unprivileged CSR addresses).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zihintntl&lt;/strong&gt; (Non-Temporal Hints) [v1.0, Ratified]:&lt;br&gt;
Domain: Memory hierarchy hints for non-temporal access (prevents cache pollution).&lt;br&gt;
Instructions: 0 new instructions (uses NOP-encoding space).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zihintpause&lt;/strong&gt; (Pause Hint) [v2.0, Ratified]:&lt;br&gt;
Domain: Energy-efficient spin-lock loops and contention reduction.&lt;br&gt;
Instructions: 0 new instructions (encoded within the FENCE opcode space).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zimop&lt;/strong&gt; (May-Be-Operations) [v1.0, Ratified]:&lt;br&gt;
Domain: Reserved opcode space for future expansion without breaking backward compatibility.&lt;br&gt;
Instructions: 32 MOP instructions (encodings within unassigned spaces).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zicond&lt;/strong&gt; (Conditional Operations) [v1.0, Ratified]:&lt;br&gt;
Domain: Branchless conditional moves (czero.eqz, czero.nez) to eliminate branch mispredictions.&lt;br&gt;
Instructions: 2 instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zilsd &amp;amp; Zclsd&lt;/strong&gt; (Load/Store Doubleword) [v1.0, Ratified]:&lt;br&gt;
Domain: 64-bit load/store acceleration on 32-bit (RV32) architectures (and compressed variant Zclsd).&lt;br&gt;
Instructions: 2 instructions (LSD, SSD) + compressed formats.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  B. Multiplication &amp;amp; Division Sub-Extensions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;M&lt;/strong&gt; (Standard Multiplication and Division) [v2.0, Ratified]:&lt;br&gt;
Domain: Hardware integer multiply and divide.&lt;br&gt;
Instructions: 8 instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zmmul&lt;/strong&gt; (Multiply-Only Extension) [v1.0, Ratified]:&lt;br&gt;
Domain: Microcontrollers needing hardware multiplication without the area overhead of division logic.&lt;br&gt;
Instructions: 4 instructions (MUL, MULH, MULHU, MULHSU).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  C. Atomics, Synchronization &amp;amp; Memory Models
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt; (Atomic Instructions) [v2.1, Ratified]:&lt;br&gt;
Domain: Inter-processor synchronization and atomic memory operations.&lt;br&gt;
Instructions: 11 instructions (Load-Reserved / Store-Conditional &amp;amp; AMOs).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zawrs&lt;/strong&gt; (Wait-on-Reservation-Set) [v1.01, Ratified]:&lt;br&gt;
Domain: Power-efficient polling loops using wrs.nto and wrs.sto.&lt;br&gt;
Instructions: 2 instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zacas&lt;/strong&gt; (Atomic Compare-and-Swap) [v1.0, Ratified]:&lt;br&gt;
Domain: Hardware-accelerated lock-free data structures.&lt;br&gt;
Instructions: 3 instructions (AMOCAS.W, AMOCAS.D, AMOCAS.Q).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zabha&lt;/strong&gt; (Byte and Halfword Atomics) [v1.0, Ratified]:&lt;br&gt;
Domain: Atomic operations on 8-bit and 16-bit quantities.&lt;br&gt;
Instructions: ~12 instructions (AMOADD.B, AMOSWAP.H, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zalasr&lt;/strong&gt; (Load-Acquire and Store-Release) [v1.0, Ratified]:&lt;br&gt;
Domain: Direct hardware support for C11/C++11 memory orderings.&lt;br&gt;
Instructions: 2 instructions (LB.A, SB.R, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RVWMO&lt;/strong&gt; / Ztso (Memory Consistency Models) [v2.0 / v1.0, Ratified]:&lt;br&gt;
Domain: Defines Weak Memory Ordering (RVWMO) or Total Store Ordering (Ztso) consistency semantics.&lt;br&gt;
Instructions: 0 new instructions (defines memory architecture execution rules).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CMO&lt;/strong&gt; (Cache Management Operations) [v1.0, Ratified]:&lt;br&gt;
Domain: Explicit cache block management (Zicbom, Zicboz, Zicbop for flush, zero, and prefetch).&lt;br&gt;
Instructions: 5 instructions (CBO.CLEAN, CBO.FLUSH, CBO.INVAL, CBO.ZERO, PREFETCH.*).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  D. Floating-Point, Vector &amp;amp; Alternative Register Extensions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;F, D, Q&lt;/strong&gt; (Floating-Point) [v2.2, Ratified]:&lt;br&gt;
Domain: IEEE 754-2008 Single, Double, and Quad precision math.&lt;br&gt;
Instructions: 26 (F) + 26 (D) + 28 (Q) instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zfh &amp;amp; Zfhmin&lt;/strong&gt; (Half-Precision Floating-Point) [v1.0, Ratified]:&lt;br&gt;
Domain: 16-bit float (FP16) arithmetic for embedded AI/ML models.&lt;br&gt;
Instructions: ~30 instructions (Zfhmin provides conversion-only subset).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BF16&lt;/strong&gt; (Bfloat16 Extensions) [v1.0, Ratified]:&lt;br&gt;
Domain: Deep learning acceleration using 16-bit Brain Floating Point format.&lt;br&gt;
Instructions: ~6 instructions (VFNCVT.BF16.S, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zfa&lt;/strong&gt; (Additional Floating-Point Instructions) [v1.0, Ratified]:&lt;br&gt;
Domain: Extended FP operations (load immediate constants, min/max IEEE semantics).&lt;br&gt;
Instructions: ~10 instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zfinx, Zdinx, Zhinx, Zhinxmin&lt;/strong&gt; (Floating-Point in Integer Registers) [v1.0, Ratified]:&lt;br&gt;
Domain: Performs FP operations directly inside integer general-purpose registers (x0-x31), removing dedicated FP registers to reduce silicon footprint.&lt;br&gt;
Instructions: Re-encodes FP instructions to reuse integer registers (0 additional registers required).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  E. Code Compression &amp;amp; Bit Manipulation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;C&lt;/strong&gt; (Compressed Instructions) [v2.0, Ratified]:&lt;br&gt;
Domain: General 16-bit instruction encodings for code size reduction.&lt;br&gt;
Instructions: 38 compressed formats.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zce&lt;/strong&gt; (Embedded Code Size Reduction) [v1.0, Ratified]:&lt;br&gt;
Domain: Tailored code-density extensions for microcontrollers (Zca, Zcb, Zcmp, Zcmt).&lt;br&gt;
Instructions: ~15 compressed operations (push/pop sequences, table jumps).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;B&lt;/strong&gt; (Bit Manipulation) [v1.0, Ratified]:&lt;br&gt;
Domain: Advanced bitwise logic (includes Zba address generation, Zbb basic bit manipulation, Zbs single-bit actions).&lt;br&gt;
Instructions: ~42 instructions (CLZ, CTZ, CPOP, SH1ADD, BSET).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  F. Vectors, Cryptography &amp;amp; Security Primitives
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;V&lt;/strong&gt; (Vector Extension) [v1.0, Ratified]:&lt;br&gt;
Domain: Scalable SIMD vector computing for processing large data streams.&lt;br&gt;
Instructions: &amp;gt;200 instructions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalar/Vector Cryptography&lt;/strong&gt; Sub-Extensions (Zbkb, Zbkc, Zbkx, Zk, Zks, Zvbb, Zvbc, Zvkg, Zvkned, Zvknhb, Zvksed, Zvksh, Zvkt) [v1.0, Ratified]:&lt;br&gt;
Domain: Hardware acceleration for AES, SHA-2, SM3/SM4, GCM, and crossbar permutation in both scalar and vector pipelines.&lt;br&gt;
Instructions: ~80 specialized cryptographic instructions across the sub-families.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zicfiss &amp;amp; Zicfilp&lt;/strong&gt; (Control-Flow Integrity - Shadow Stack &amp;amp; Landing Pad) [v1.0, Ratified]:&lt;br&gt;
Domain: Hardware-enforced Control-Flow Integrity (CFI) to prevent Return-Oriented Programming (ROP) and Jump-Oriented Programming (JOP) exploits.&lt;br&gt;
Instructions: ~4 instructions (SSPUSH, SSPOP, LPAD).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. The RISC-V Privileged Architecture Instructions
&lt;/h3&gt;

&lt;p&gt;The RISC-V privileged architecture complements the base ISA by providing dedicated execution modes (User, Supervisor, Machine) and instructions required for operating system kernel operations, exception handling, memory protection, and hardware virtualization.&lt;/p&gt;

&lt;h5&gt;
  
  
  A. Trap &amp;amp; Interrupt Return Instructions
&lt;/h5&gt;

&lt;p&gt;MRET – Machine-mode Trap Return (Restores PC from mepc and reverts privilege level/interrupt state).&lt;br&gt;
SRET – Supervisor-mode Trap Return (Restores PC from sepc and reverts privilege level/interrupt state).&lt;br&gt;
URET – User-mode Trap Return (Optional; restores state from User-level traps).&lt;/p&gt;
&lt;h5&gt;
  
  
  B. Hypervisor &amp;amp; Virtualization Instructions
&lt;/h5&gt;

&lt;p&gt;HFENCE.VVMA – Hypervisor Guest Virtual-Memory Fence (Flushes guest virtual address translation TLBs).&lt;br&gt;
HFENCE.GVMA – Hypervisor Guest Physical-Memory Fence (Flushes second-stage physical address translation TLBs).&lt;br&gt;
HLV / HLVX – Hypervisor Load Virtual / Load Virtual Execute (Reads memory on behalf of guest VM).&lt;br&gt;
HSV – Hypervisor Store Virtual (Writes memory on behalf of guest VM).&lt;/p&gt;
&lt;h5&gt;
  
  
  C. Memory Management &amp;amp; Address Translation
&lt;/h5&gt;

&lt;p&gt;SFENCE.VMA – Supervisor Virtual-Memory Fence (Flushes local TLB entries for virtual memory page tables).&lt;/p&gt;
&lt;h5&gt;
  
  
  D. System Environment &amp;amp; State Management
&lt;/h5&gt;

&lt;p&gt;WFI – Wait for Interrupt (Suspends processor execution to reduce power until an interrupt occurs).&lt;br&gt;
MNRET – Machine Non-Maskable Interrupt Return (Restores state after handling an NMI).&lt;/p&gt;
&lt;h3&gt;
  
  
  6. GCC/LLVM: The C Startup Stub (crt0.s)
&lt;/h3&gt;

&lt;p&gt;In bare-metal embedded software, executable ELF binaries rely on a C Runtime initialization module (crt0 or reset_handler) to bridge raw chip power-on with the execution of main().&lt;/p&gt;

&lt;p&gt;Below is a typical bare-metal assembly startup stub generated or linked by the GCC RISC-V toolchain (crt0.s / start.S):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.section .text.init
.global _start
.type _start, @function

_start:
    /* 1. Clear registers to a known state */
    li  x1, 0
    li  x2, 0
    li  x3, 0
    /* ... [Clearing x4 to x31] ... */

    /* 2. Initialize Stack Pointer (sp) and Global Pointer (gp) */
    la  sp, _stack_top
    .option push
    .option norelax
    la  gp, __global_pointer$
    .option pop

    /* 3. Copy .data section from Flash/ROM to RAM */
    la  a0, _sdata
    la  a1, _edata
    la  a2, _sidata
    bgeu a0, a1, .L_bss_init
.L_copy_data:
    lw   t0, 0(a2)
    sw   t0, 0(a0)
    addi a0, a0, 4
    addi a2, a2, 4
    bltu a0, a1, .L_copy_data

.L_bss_init:
    /* 4. Zero-fill the .bss section in RAM */
    la  a0, _sbss
    la  a1, _ebss
    bgeu a0, a1, .L_main_call
.L_zero_bss:
    sw   zero, 0(a0)
    addi a0, a0, 4
    bltu a0, a1, .L_zero_bss

.L_main_call:
    /* 5. Jump to main application entry point */
    call main

.L_exit_loop:
    /* 6. Fallback infinite loop if main returns */
    j .L_exit_loop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Analysis of the Stub Overhead
&lt;/h5&gt;

&lt;p&gt;The generic CRT stub executes more than 30 to 40 instructions (120–160 bytes) before calling main().&lt;/p&gt;

&lt;p&gt;While initializing the .data and .bss sections is essential for complex C applications, a dedicated bare-metal target where variables are explicitly initialized inside main() or held in fixed locations can drastically reduce this footprint.&lt;/p&gt;

&lt;p&gt;For an ultra-lightweight environment, the entire startup routine can be optimized down to just 3 instructions (12 bytes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_start:
    la  sp, _stack_top    /* Set valid stack boundary */
    call main             /* Jump to user program */
1:  j 1b                  /* Catch unexpected exit */
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. RISC-V Today
&lt;/h3&gt;

&lt;p&gt;The RISC-V architecture is experiencing exponential growth across the entire spectrum of computing:&lt;/p&gt;

&lt;p&gt;Embedded Microcontrollers &amp;amp; IoT: Companies like Espressif (ESP32-C3/C6), SiFive, WCH (CH32V series), and Nordic Semiconductor are deploying low-power RISC-V cores to replace legacy 8-bit and 32-bit microcontrollers.&lt;/p&gt;

&lt;p&gt;Custom Accelerators &amp;amp; Coprocessors: Major tech vendors (NVIDIA, Google, Western Digital) integrate internal RISC-V cores into GPUs and storage controllers to handle power management and house security engines.&lt;/p&gt;

&lt;p&gt;Academic &amp;amp; System Research: Due to its open and royalty-free nature, RISC-V has become the global standard for teaching computer architecture, compiler design, and hardware security (such as custom ISA extensions and secure sandboxes).&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Conclusion
&lt;/h3&gt;

&lt;p&gt;This article introduced what the GCC toolchain generates for a 32-bit RISC-V target. Even in this modern 32-bit architecture, default toolchains include runtime overhead and generic stubs that can be trimmed or repurposed. &lt;br&gt;
n the next part of this series, we will disassemble the generated test1_rv32i.elf object file. Since pure RV32I lacks a hardware multiplier (which requires the 'M' extension), we will explore how GCC emits software library calls (__mulsi3, __divsi3) to execute basic arithmetic operations, and how it optimizes control flow and stack frame management.&lt;/p&gt;

</description>
      <category>c</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>8051 What does SDCC do part 3 ?</title>
      <dc:creator>ddupard</dc:creator>
      <pubDate>Sat, 15 Aug 2026 13:17:52 +0000</pubDate>
      <link>https://dev.to/ddupard/8051-what-does-sdcc-do-part-3--3111</link>
      <guid>https://dev.to/ddupard/8051-what-does-sdcc-do-part-3--3111</guid>
      <description>&lt;h3&gt;
  
  
  1. Introduction and Problem Statement
&lt;/h3&gt;

&lt;p&gt;A good way to learn what a compiler really does when transforming a C source code into a binary is to disassemble the binary and compare it with the C source code. It is especially true for 8 bits microcontrollers like the 8051.&lt;/p&gt;

&lt;p&gt;In order to test SDCC we are going to use the following C source code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* ========================================================================== *
 * Universal Test Corpus - Heterogeneous Architecture Analysis          *
 * ========================================================================== */&lt;/span&gt;


&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Global variables (testing absolute/relative addressing modes)&lt;/span&gt;
&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;global_var_32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0xDEADBEEF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt;  &lt;span class="n"&gt;global_var_8&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt;    &lt;span class="kt"&gt;char&lt;/span&gt;     &lt;span class="n"&gt;string_const&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"TARGET_STRING"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Function with parameter passing and local variables (stack / Frame Pointer test)&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Basic and mixed arithmetic operations (8, 16, 32 bits)&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Avoid division by zero&lt;/span&gt;

    &lt;span class="c1"&gt;// Shift tests and logical operations (highly variable depending on ISAs)&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mh"&gt;0x55AA55AA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;global_var_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;local_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Main function grouping complex control flows&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Loop test (Conditional jumps, decrement, comparison tests)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Multiple branching test (Switch / Jump Table or cascaded if-else)&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_var_8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mh"&gt;0x20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default:&lt;/span&gt;
            &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Function call (Stack management, save registers Link Register/PC)&lt;/span&gt;
    &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Pointer and indirect memory access test&lt;/span&gt;
    &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;global_var_32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Terminal infinite loop (classic for raw binaries / microcontrollers)&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To compile it, we will use SDCC which produces an Intel HEX file. This file will be transformed in a ROM file using either objcopy or makebin (see below).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sdcc  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SRC&lt;/span&gt;&lt;span class="s2"&gt;/test1.c"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"8/test1_8051"&lt;/span&gt; 
objcopy &lt;span class="nt"&gt;-I&lt;/span&gt; ihex &lt;span class="nt"&gt;-O&lt;/span&gt; binary &lt;span class="s2"&gt;"8/test1_8051"&lt;/span&gt; &lt;span class="s2"&gt;"8/bin/test1_8051_bin"&lt;/span&gt; 
makebin &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"8/test1_8051"&lt;/span&gt; &lt;span class="s2"&gt;"8/bin/test1_8051.rom"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover, to simulate the 8051, I use the MCU 8051 IDE (command mcu8051ide).&lt;/p&gt;

&lt;p&gt;In this final part we will study the calling mechanism and what does the callee_function do&lt;/p&gt;

&lt;p&gt;This C file is particularly interesting, because in a small source code we have a lot of different cases (for example, some of the variables have a 32 bits size).    &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Function call
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Function call (Stack management, save registers Link Register/PC)&lt;/span&gt;
    &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code is translated in the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  01F8 851382       MOV DPL, 13h
  01FB 851483       MOV DPH, 14h
  01FE 750D03       MOV 0Dh, #3h
  0201 750E00       MOV 0Eh, #0h
  0204 120071       LCALL L0013
  0207 AC82         MOV R4, DPL
  0209 AD83         MOV R5, DPH
  020B AEF0         MOV R6, B
  020D FF           MOV R7, A
  020E EC           MOV A, R4
  020F 2513         ADD A, 13h
  0211 F513         MOV 13h, A
  0213 ED           MOV A, R5
  0214 3514         ADDC A, 14h
  0216 F514         MOV 14h, A
  0218 EE           MOV A, R6
  0219 3515         ADDC A, 15h
  021B F515         MOV 15h, A
  021D EF           MOV A, R7
  021E 3516         ADDC A, 16h
  0220 F516         MOV 16h, A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how the cast of accumulator variable is done. The accumulator is stored on 4 bytes at addresses 13h,14h,15h,16h.&lt;br&gt;
Casting the 32 bits integer to a 16 bits integer is done by simply storing to DPL and DPH the value contained at address 13h and 14h by the isntructions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01F8 851382     MOV DPL, 13h
01FB 851483     MOV DPH, 14h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See how 3 is casted to a 16 bits integer because of the defintion of the callee_function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01FE 750D03     MOV 0Dh, #3h
0201 750E00     MOV 0Eh, #0h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the absence of a sophisticated native stack for function arguments in the default memory model, the compiler often uses fixed locations in internal RAM (DATA) to pass parameters to subroutines.&lt;/p&gt;

&lt;p&gt;because callee_function returns a 32 bits integer, we have the following lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  0204 120071       LCALL L0013
  0207 AC82         MOV R4, DPL
  0209 AD83         MOV R5, DPH
  020B AEF0         MOV R6, B
  020D FF           MOV R7, A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and because we have an addition of the accumulator variable with the result of callee_function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Function call (Stack management, save registers Link Register/PC)&lt;/span&gt;
    &lt;span class="n"&gt;accumulator&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we have the following lines which does a simple addition of two 32 bits integers&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  020E EC           MOV A, R4
  020F 2513         ADD A, 13h
  0211 F513         MOV 13h, A
  0213 ED           MOV A, R5
  0214 3514         ADDC A, 14h
  0216 F514         MOV 14h, A
  0218 EE           MOV A, R6
  0219 3515         ADDC A, 15h
  021B F515         MOV 15h, A
  021D EF           MOV A, R7
  021E 3516         ADDC A, 16h
  0220 F516         MOV 16h, A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Inside the function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 2. Function with parameter passing and local variables (stack / Frame Pointer test)&lt;/span&gt;
&lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="nf"&gt;callee_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int16_t&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Basic and mixed arithmetic operations (8, 16, 32 bits)&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Avoid division by zero&lt;/span&gt;

    &lt;span class="c1"&gt;// Shift tests and logical operations (highly variable depending on ISAs)&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="mh"&gt;0x55AA55AA&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;global_var_8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;local_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above function is translated into a rather complicated code requiring us to divide it in several paragraphs &lt;/p&gt;

&lt;h3&gt;
  
  
  4. Inside the function: Initialization
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;L0013:
  0071 AE82     MOV R6, DPL          ; Save lower byte of first parameter
  0073 AF83     MOV R7, DPH          ; Save higher byte of first parameter 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing done by the function when called is to store the first parameter then the C line below is translated into the assembly lines below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt; &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;int32_t&lt;/span&gt; &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  0075 E4       CLR A                ; 
  0076 F50F     MOV 0Fh, A           ; Initialize local_result to 0. 
  0078 F510     MOV 10h, A           ; Initialize local_result to 0
  007A F511     MOV 11h, A           ; Initialize local_result to 0
  007C F512     MOV 12h, A           ; Initialize local_result to 0

; local_result being a 32 bits integer, Bytes at adresses 0F,10h,11h,12h are used to store local_result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Inside the function: Arithmetic operations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt; &lt;span class="c1"&gt;// Basic and mixed arithmetic operations (8, 16, 32 bits)&lt;/span&gt;
    &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the line above is translated in the block below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; start of   local_result += (int32_t)(a * b);

  007E 850D17   MOV 17h, 0Dh         ; Copy second parameter low byte to 17h
  0081 850E18   MOV 18h, 0Eh         ; Copy second parameter high byte to 18h
  0084 8E82     MOV DPL, R6          ; Restore 'a' low byte to DPL
  0086 8F83     MOV DPH, R7          ; Restore 'a' high byte to DPH
  0088 C007     PUSH 7h              ; Save register R7 on stack
  008A C006     PUSH 6h              ; Save register R6 on stack
  008C 120248   LCALL L0015          ; Call multiplication helper routine (a * b) see below
  008F AC82     MOV R4, DPL          ; Retrieve multiplication result low byte
  0091 AD83     MOV R5, DPH          ; Retrieve multiplication result high byte
  0093 D006     POP 6h               ; Restore register R6 from stack
  0095 D007     POP 7h               ; Restore register R7 from stack

  0097 ED       MOV A, R5            ; Move high byte of result to accumulator
  0098 33       RLC A                ; Rotate left through carry for sign extension
  0099 95E0     SUBB A, ACC          ; Propagate sign bit to form 32-bit value
  009B FB       MOV R3, A            ; Store extension byte in R3
  009C FA       MOV R2, A            ; Store extension byte in R2

  ; addition of two 32 bits integer
  009D EC       MOV A, R4            ; Get low byte of multiplication result
  009E 250F     ADD A, 0Fh           ; Add to accumulated lower result bytes
  00A0 F50F     MOV 0Fh, A           ; Update local result byte 0Fh
  00A2 ED       MOV A, R5            ; Get high byte of multiplication result
  00A3 3510     ADDC A, 10h          ; Add with carry to local result byte 10h
  00A5 F510     MOV 10h, A           ; Update local result byte 10h
  00A7 EB       MOV A, R3            ; Get sign extension byte
  00A8 3511     ADDC A, 11h          ; Add with carry to local result byte 11h
  00AA F511     MOV 11h, A           ; Update local result byte 11h
  00AC EA       MOV A, R2            ; Get sign extension byte
  00AD 3512     ADDC A, 12h          ; Add with carry to local result byte 12h
  00AF F512     MOV 12h, A           ; Update local result byte 12h

; end of   local_result += (int32_t)(a * b);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the code for the multiplication subroutine is below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;L0015: ; code making the multiplication  (int32_t)(a * b);
  0248 E582         MOV A, DPL
  024A 8517F0       MOV B, 17h
  024D A4           MUL AB
  024E C582         XCH A, DPL
  0250 C0F0         PUSH B
  0252 8518F0       MOV B, 18h
  0255 A4           MUL AB
  0256 D0F0         POP B
  0258 25F0         ADD A, B
  025A C583         XCH A, DPH
  025C 8517F0       MOV B, 17h
  025F A4           MUL AB
  0260 2583         ADD A, DPH
  0262 F583         MOV DPH, A
  0264 22           RET
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;pretty straightforward&lt;/p&gt;

&lt;p&gt;Then we have the division with the line below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt; &lt;span class="n"&gt;local_result&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int32_t&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Avoid division by zero&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the above line is translated into the following assembly code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; start of  local_result -= (int32_t)(a / (b | 1)); // Avoid division by zero

  00B1 AC0D     MOV R4, 0Dh          ; Retrieve original parameter 'b' low byte
  00B3 AD0E     MOV R5, 0Eh          ; Retrieve original parameter 'b' high byte
  00B5 7401     MOV A, #1h           ; Load immediate 1 for division safety check (b | 1)
  00B7 4C       ORL A, R4            ; Bitwise OR with 'b' low byte to prevent division by zero
  00B8 F517     MOV 17h, A           ; Store safe denominator low byte
  00BA 8D18     MOV 18h, R5          ; Store safe denominator high byte
  00BC 8E82     MOV DPL, R6          ; Restore 'a' low byte into DPL for division
  00BE 8F83     MOV DPH, R7          ; Restore 'a' high byte into DPH for division
  00C0 12028E   LCALL L0016          ; Call signed division helper routine (a / (b | 1)) see below
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lines below do the following operation local_result = local_result - result of the division&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  00C3 AE82     MOV R6, DPL          ; Get division quotient low byte
  00C5 E583     MOV A, DPH           ; Get division quotient high byte
  00C7 FF       MOV R7, A            ; Store quotient high byte in R7
  00C8 33       RLC A                ; Sign extend quotient high byte
  00C9 95E0     SUBB A, ACC          ; Generate sign extension bits
  00CB FD       MOV R5, A            ; Store extension byte in R5
  00CC FC       MOV R4, A            ; Store extension byte in R4
  00CD E50F     MOV A, 0Fh           ; Load current accumulated result low byte
  00CF C3       CLR C                ; Clear carry flag for subtraction
  00D0 9E       SUBB A, R6           ; Subtract division result low byte
  00D1 F50F     MOV 0Fh, A           ; Update result byte 0Fh
  00D3 E510     MOV A, 10h           ; Load accumulated result byte 10h
  00D5 9F       SUBB A, R7           ; Subtract with borrow quotient high byte
  00D6 F510     MOV 10h, A           ; Update result byte 10h
  00D8 E511     MOV A, 11h           ; Load accumulated result byte 11h
  00DA 9D       SUBB A, R5           ; Subtract with borrow extension byte
  00DB F511     MOV 11h, A           ; Update result byte 11h
  00DD E512     MOV A, 12h           ; Load accumulated result byte 12h
  00DF 9C       SUBB A, R4           ; Subtract with borrow extension byte
  00E0 F512     MOV 12h, A           ; Update result byte 12h

; end of  local_result -= (int32_t)(a / (b | 1)); // Avoid division by zero
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see below the division subroutine is rather complicated but don't worry—a full explanation follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; all code for a / b  

L0019:
  0265 7A10         MOV R2, #10h
  0267 E4           CLR A
  0268 FB           MOV R3, A
  0269 FC           MOV R4, A
L0022:
  026A E582         MOV A, DPL
  026C 25E0         ADD A, ACC
  026E F582         MOV DPL, A
  0270 E583         MOV A, DPH
  0272 33           RLC A
  0273 F583         MOV DPH, A
  0275 EB           MOV A, R3
  0276 33           RLC A
  0277 FB           MOV R3, A
  0278 EC           MOV A, R4
  0279 33           RLC A
  027A FC           MOV R4, A
  027B EB           MOV A, R3
  027C 9517         SUBB A, 17h
  027E F5F0         MOV B, A
  0280 EC           MOV A, R4
  0281 9518         SUBB A, 18h
  0283 4006         JC L0021
  0285 FC           MOV R4, A
  0286 ABF0         MOV R3, B
  0288 438201       ORL DPL, #1h
L0021:
  028B DADD         DJNZ R2, L0022
  028D 22           RET

L0016: ; entry point of a / b 
  028E C2D5         CLR F0
  0290 E583         MOV A, DPH
  0292 30E70D       JNB ACC.7, L0017
  0295 D2D5         SETB F0
  0297 E4           CLR A
  0298 C3           CLR C
  0299 9582         SUBB A, DPL
  029B F582         MOV DPL, A
  029D E4           CLR A
  029E 9583         SUBB A, DPH
  02A0 F583         MOV DPH, A
L0017:
  02A2 E518         MOV A, 18h
  02A4 30E70D       JNB ACC.7, L0018
  02A7 B2D5         CPL F0
  02A9 E4           CLR A
  02AA C3           CLR C
  02AB 9517         SUBB A, 17h
  02AD F517         MOV 17h, A
  02AF E4           CLR A
  02B0 9518         SUBB A, 18h
  02B2 F518         MOV 18h, A
L0018:
  02B4 120265       LCALL L0019
  02B7 30D50B       JNB F0, L0020
  02BA E4           CLR A
  02BB C3           CLR C
  02BC 9582         SUBB A, DPL
  02BE F582         MOV DPL, A
  02C0 E4           CLR A
  02C1 9583         SUBB A, DPH
  02C3 F583         MOV DPH, A
L0020:
  02C5 22           RET

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This routine implements a bit-by-bit 16-bit by 16-bit signed integer division (using a shift-and-subtract binary division algorithm).Here is how it works step-by-step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign Handling and Preparation (L0016):
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The code first handles signed numbers by determining and saving the final result's sign in a flag (F0).  It then converts both the dividend (stored in DPTR) and the divisor (stored in memory addresses 17h-18h) into their absolute values.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Loop Initialization (L0019):  MOV R2, #10h sets a loop counter to 16 (since it is a 16-bit division).  The partial remainder (spread across registers R3 and R4) is initialized to zero.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Core Algorithm (Shift &amp;amp; Subtract inside L0022):  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Left Shift: On each iteration, the dividend (DPTR) and the remainder (R3:R4) are shifted left together by one bit using additions and rotations with carry (ADD A, ACC, RLC A), feeding the next highest bit of the dividend into the operation.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Divisor Subtraction: The code subtracts the divisor (17h-18h) from the partial remainder using SUBB.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test and Adjustment:If the result is greater than or equal to zero (no borrow/no jump JC L0021), the subtraction is kept: the new remainder is saved in R3:R4, and a 1 is shifted into the lowest bit of the quotient (ORL DPL, #1h).  If the result is negative (JC L0021), the subtraction is discarded (leaving a 0 bit in the quotient).  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Loop Control and Finalization:  The DJNZ R2, L0022 instruction repeats this process 16 times (once for each bit). Once finished, DPTR holds the resulting quotient, and L0016 restores the correct mathematical sign before returning.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that the arithmetic operations have been studied, it's time to study the shift operations&lt;/p&gt;

&lt;h3&gt;
  
  
  6.  Inside the function: Shift operations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;; start of    local_result = (local_result &amp;lt;&amp;lt; 2) ^ 0x55AA55AA;
  00E2 E50F     MOV A, 0Fh           ; Load result byte 0Fh for shift left operation (&amp;lt;&amp;lt; 2)
  00E4 25E0     ADD A, ACC           ; Shift left by 1 (multiply by 2)
  00E6 FC       MOV R4, A            ; Save temporary shifted byte in R4
  00E7 E510     MOV A, 10h           ; Load result byte 10h
  00E9 33       RLC A                ; Rotate left through carry
  00EA FD       MOV R5, A            ; Save temporary shifted byte in R5
  00EB E511     MOV A, 11h           ; Load result byte 11h
  00ED 33       RLC A                ; Rotate left through carry
  00EE FE       MOV R6, A            ; Save temporary shifted byte in R6
  00EF E512     MOV A, 12h           ; Load result byte 12h
  00F1 33       RLC A                ; Rotate left through carry
  00F2 FF       MOV R7, A            ; Save temporary shifted byte in R7
  00F3 EC       MOV A, R4            ; Retrieve temporary byte for second shift left (total &amp;lt;&amp;lt; 2)
  00F4 2C       ADD A, R4            ; Shift left by another 1 (total shift of 2)
  00F5 FC       MOV R4, A            ; Update R4 with final &amp;lt;&amp;lt; 2 low byte
  00F6 ED       MOV A, R5            ; Get next byte
  00F7 33       RLC A                ; Rotate left through carry
  00F8 FD       MOV R5, A            ; Update R5
  00F9 EE       MOV A, R6            ; Get next byte
  00FA 33       RLC A                ; Rotate left through carry
  00FB FE       MOV R6, A            ; Update R6
  00FC EF       MOV A, R7            ; Get highest byte
  00FD 33       RLC A                ; Rotate left through carry
  00FE FF       MOV R7, A            ; Update R7 with final &amp;lt;&amp;lt; 2 high byte
  00FF 74AA     MOV A, #0AAh         ; Load lower byte mask for XOR operation (^ 0x55AA55AA)
  0101 6C       XRL A, R4            ; Apply XOR mask to low byte
  0102 F50F     MOV 0Fh, A           ; Save back to working RAM
  0104 7455     MOV A, #55h          ; Load next byte of XOR mask (0x55)
  0106 6D       XRL A, R5            ; Apply XOR mask
  0107 F510     MOV 10h, A           ; Save back to working RAM
  0109 74AA     MOV A, #0AAh         ; Load next byte of XOR mask (0xAA)
  010B 6E       XRL A, R6            ; Apply XOR mask
  010C F511     MOV 11h, A           ; Save back to working RAM
; end of    local_result = (local_result &amp;lt;&amp;lt; 2) ^ 0x55AA55AA;


Operation Summary: 
To execute the 2-bit left shift (&amp;lt;&amp;lt; 2), the compiler emulates a 32-bit multiplication by 4 by performing two successive shifts using additions and carry rotations (ADD and RLC) byte by byte across the registers. 

Once this global shift is complete, it applies the bitwise XOR operation (XRL) with the immediate mask 0x55AA55AA by combining constants (0xAA and 0x55) injected directly into the accumulator, before writing the final result back to working RAM.





  ; start of local_result = (local_result &amp;gt;&amp;gt; 1) | (int32_t)global_var_8;
  010E 7455     MOV A, #55h          ; Load upper byte mask of XOR constant
  0110 6F       XRL A, R7            ; Apply XOR mask to high byte
  0111 F512     MOV 12h, A           ; Save back to working RAM
  0113 E512     MOV A, 12h           ; Load high byte for right shift operation (&amp;gt;&amp;gt; 1)
  0115 A2E7     MOV C, ACC.7         ; Save sign bit into Carry flag
  0117 13       RRC A                ; Shift right through carry
  0118 FF       MOV R7, A            ; Update shifted byte
  0119 E511     MOV A, 11h           ; Load next byte down
  011B 13       RRC A                ; Shift right through carry
  011C FE       MOV R6, A            ; Update shifted byte
  011D E510     MOV A, 10h           ; Load next byte down
  011F 13       RRC A                ; Shift right through carry
  0120 FD       MOV R5, A            ; Update shifted byte
  0121 E50F     MOV A, 0Fh           ; Load low byte
  0123 13       RRC A                ; Shift right through carry
  0124 FC       MOV R4, A            ; Update low shifted byte
  0125 A80C     MOV R0, 0Ch          ; Load global variable global_var_8 address into R0
  0127 E4       CLR A                ; Clear accumulator
  0128 F9       MOV R1, A            ; Clear upper bytes for zero-extension of global_var_8
  0129 FA       MOV R2, A            ; Clear upper bytes
  012A FB       MOV R3, A            ; Clear upper bytes
  012B E8       MOV A, R0            ; Retrieve global_var_8 value into accumulator
  012C 4C       ORL A, R4            ; Bitwise OR low byte with global_var_8 (| global_var_8)
  012D F50F     MOV 0Fh, A           ; Update final low result byte
  012F E9       MOV A, R1            ; Get extension byte
  0130 4D       ORL A, R5            ; Bitwise OR with second result byte
  0131 F510     MOV 10h, A           ; Update result byte
  0133 EA       MOV A, R2            ; Get extension byte
  0134 4E       ORL A, R6            ; Bitwise OR with third result byte
  0135 F511     MOV 11h, A           ; Update result byte
  0137 EB       MOV A, R3            ; Get extension byte
  0138 4F       ORL A, R7            ; Bitwise OR with high result byte
  0139 F512     MOV 12h, A           ; Update final high result byte
  ; end of local_result = (local_result &amp;gt;&amp;gt; 1) | (int32_t)global_var_8;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Operation Summary: &lt;br&gt;
To complete the sequence, the compiler finishes the previous XOR operation on the highest byte, and then performs a 32-bit arithmetic right shift (&amp;gt;&amp;gt; 1) by preserving and propagating the sign bit via the carry flag (MOV C, ACC.7 followed by successive RRC instructions across all bytes). &lt;/p&gt;

&lt;p&gt;Next, it zero-extends the 8-bit global_var_8 into a 32-bit value across temporary registers, applies a bitwise OR (ORL) operation combining it with the shifted result, and saves the final 32-bit word back to working RAM.&lt;/p&gt;

&lt;h3&gt;
  
  
  7 . Inside the function: return of the result
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  013B 850F82   MOV DPL, 0Fh         ; Prepare return value low byte into DPL
  013E 851083   MOV DPH, 10h         ; Prepare return value high byte into DPH
  0141 8511F0   MOV B, 11h           ; Prepare return value upper-middle byte into register B
  0144 E512     MOV A, 12h           ; Move return value highest byte into Accumulator
  0146 22       RET                  ; Return from function with 32-bit result split across registers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of the function is sent to the following registers DPL,DPH, B, A before a RET is called.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Conclusion
&lt;/h3&gt;

&lt;p&gt;This article finishes the series on the translation in assembly by SDCC of a small C source code. Even if the C source code was small, it had a lot of features which necessitated to be explained.&lt;/p&gt;

&lt;p&gt;This example is a textbook case demonstrating that writing standard C without regard for the target model on an 8-bit microcontroller leads to heavy and slow object code. The constant data shuttling between internal memory and registers (MOV 13h, A, etc.) illustrates why, back then, low-level developers invariably ended up bypassing the compiler to rewrite critical portions directly by hand.&lt;/p&gt;

&lt;p&gt;I hope that you have enjoyed your journey into the intricacies of the SDCC translation. See you next time for another series.  &lt;/p&gt;

&lt;h3&gt;
  
  
  9. The full disassembly code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CSEG AT 0000h
  0000 020006       LJMP L0001

L0004:
  0003 020147       LJMP L0005

L0001:
  0006 758118       MOV SP, #18h
  0009 1202C6       LCALL L0002
  000C E582         MOV A, DPL
  000E 6003         JZ L0003
  0010 020003       LJMP L0004

L0003:
  0013 7900         MOV R1, #0h
  0015 E9           MOV A, R1
  0016 4400         ORL A, #0h
  0018 601B         JZ L0025
  001A 7A00         MOV R2, #0h
  001C 9002D8       MOV DPTR, #02D8h
  001F 7801         MOV R0, #1h
  0021 75A000       MOV P2, #0h
L0027:
  0024 E4           CLR A
  0025 93           MOVC A, @A+DPTR
  0026 F2           MOVX @R0, A
  0027 A3           INC DPTR
  0028 08           INC R0
  0029 B80002       CJNE R0, #0h, L0026
  002C 05A0         INC P2
L0026:
  002E D9F4         DJNZ R1, L0027
  0030 DAF2         DJNZ R2, L0027
  0032 75A0FF       MOV P2, #0FFh
L0025:
  0035 E4           CLR A
  0036 78FF         MOV R0, #0FFh
L0028:
  0038 F6           MOV @R0, A
  0039 D8FD         DJNZ R0, L0028
  003B 7800         MOV R0, #0h
  003D E8           MOV A, R0
  003E 4400         ORL A, #0h
  0040 600A         JZ L0029
  0042 7901         MOV R1, #1h
  0044 75A000       MOV P2, #0h
  0047 E4           CLR A
L0030:
  0048 F3           MOVX @R1, A
  0049 09           INC R1
  004A D8FC         DJNZ R0, L0030
L0029:
  004C 7800         MOV R0, #0h
  004E E8           MOV A, R0
  004F 4400         ORL A, #0h
  0051 600C         JZ L0031
  0053 7900         MOV R1, #0h
  0055 900001       MOV DPTR, #0001h
  0058 E4           CLR A
L0032:
  0059 F0           MOVX @DPTR, A
  005A A3           INC DPTR
  005B D8FC         DJNZ R0, L0032
  005D D9FA         DJNZ R1, L0032
L0031:
  005F 7508EF       MOV 8h, #0EFh
  0062 7509BE       MOV 9h, #0BEh
  0065 750AAD       MOV 0Ah, #0ADh
  0068 750BDE       MOV 0Bh, #0DEh
  006B 750C42       MOV 0Ch, #42h
  006E 020003       LJMP L0004

L0013:
  0071 AE82         MOV R6, DPL
  0073 AF83         MOV R7, DPH
  0075 E4           CLR A
  0076 F50F         MOV 0Fh, A
  0078 F510         MOV 10h, A
  007A F511         MOV 11h, A
  007C F512         MOV 12h, A
  007E 850D17       MOV 17h, 0Dh
  0081 850E18       MOV 18h, 0Eh
  0084 8E82         MOV DPL, R6
  0086 8F83         MOV DPH, R7
  0088 C007         PUSH 7h
  008A C006         PUSH 6h
  008C 120248       LCALL L0015
  008F AC82         MOV R4, DPL
  0091 AD83         MOV R5, DPH
  0093 D006         POP 6h
  0095 D007         POP 7h
  0097 ED           MOV A, R5
  0098 33           RLC A
  0099 95E0         SUBB A, ACC
  009B FB           MOV R3, A
  009C FA           MOV R2, A
  009D EC           MOV A, R4
  009E 250F         ADD A, 0Fh
  00A0 F50F         MOV 0Fh, A
  00A2 ED           MOV A, R5
  00A3 3510         ADDC A, 10h
  00A5 F510         MOV 10h, A
  00A7 EB           MOV A, R3
  00A8 3511         ADDC A, 11h
  00AA F511         MOV 11h, A
  00AC EA           MOV A, R2
  00AD 3512         ADDC A, 12h
  00AF F512         MOV 12h, A
  00B1 AC0D         MOV R4, 0Dh
  00B3 AD0E         MOV R5, 0Eh
  00B5 7401         MOV A, #1h
  00B7 4C           ORL A, R4
  00B8 F517         MOV 17h, A
  00BA 8D18         MOV 18h, R5
  00BC 8E82         MOV DPL, R6
  00BE 8F83         MOV DPH, R7
  00C0 12028E       LCALL L0016
  00C3 AE82         MOV R6, DPL
  00C5 E583         MOV A, DPH
  00C7 FF           MOV R7, A
  00C8 33           RLC A
  00C9 95E0         SUBB A, ACC
  00CB FD           MOV R5, A
  00CC FC           MOV R4, A
  00CD E50F         MOV A, 0Fh
  00CF C3           CLR C
  00D0 9E           SUBB A, R6
  00D1 F50F         MOV 0Fh, A
  00D3 E510         MOV A, 10h
  00D5 9F           SUBB A, R7
  00D6 F510         MOV 10h, A
  00D8 E511         MOV A, 11h
  00DA 9D           SUBB A, R5
  00DB F511         MOV 11h, A
  00DD E512         MOV A, 12h
  00DF 9C           SUBB A, R4
  00E0 F512         MOV 12h, A
  00E2 E50F         MOV A, 0Fh
  00E4 25E0         ADD A, ACC
  00E6 FC           MOV R4, A
  00E7 E510         MOV A, 10h
  00E9 33           RLC A
  00EA FD           MOV R5, A
  00EB E511         MOV A, 11h
  00ED 33           RLC A
  00EE FE           MOV R6, A
  00EF E512         MOV A, 12h
  00F1 33           RLC A
  00F2 FF           MOV R7, A
  00F3 EC           MOV A, R4
  00F4 2C           ADD A, R4
  00F5 FC           MOV R4, A
  00F6 ED           MOV A, R5
  00F7 33           RLC A
  00F8 FD           MOV R5, A
  00F9 EE           MOV A, R6
  00FA 33           RLC A
  00FB FE           MOV R6, A
  00FC EF           MOV A, R7
  00FD 33           RLC A
  00FE FF           MOV R7, A
  00FF 74AA         MOV A, #0AAh
  0101 6C           XRL A, R4
  0102 F50F         MOV 0Fh, A
  0104 7455         MOV A, #55h
  0106 6D           XRL A, R5
  0107 F510         MOV 10h, A
  0109 74AA         MOV A, #0AAh
  010B 6E           XRL A, R6
  010C F511         MOV 11h, A
  010E 7455         MOV A, #55h
  0110 6F           XRL A, R7
  0111 F512         MOV 12h, A
  0113 E512         MOV A, 12h
  0115 A2E7         MOV C, ACC.7
  0117 13           RRC A
  0118 FF           MOV R7, A
  0119 E511         MOV A, 11h
  011B 13           RRC A
  011C FE           MOV R6, A
  011D E510         MOV A, 10h
  011F 13           RRC A
  0120 FD           MOV R5, A
  0121 E50F         MOV A, 0Fh
  0123 13           RRC A
  0124 FC           MOV R4, A
  0125 A80C         MOV R0, 0Ch
  0127 E4           CLR A
  0128 F9           MOV R1, A
  0129 FA           MOV R2, A
  012A FB           MOV R3, A
  012B E8           MOV A, R0
  012C 4C           ORL A, R4
  012D F50F         MOV 0Fh, A
  012F E9           MOV A, R1
  0130 4D           ORL A, R5
  0131 F510         MOV 10h, A
  0133 EA           MOV A, R2
  0134 4E           ORL A, R6
  0135 F511         MOV 11h, A
  0137 EB           MOV A, R3
  0138 4F           ORL A, R7
  0139 F512         MOV 12h, A
  013B 850F82       MOV DPL, 0Fh
  013E 851083       MOV DPH, 10h
  0141 8511F0       MOV B, 11h
  0144 E512         MOV A, 12h
  0146 22           RET

L0005:
  0147 E4           CLR A
  0148 F513         MOV 13h, A
  014A F514         MOV 14h, A
  014C F515         MOV 15h, A
  014E F516         MOV 16h, A
  0150 7E00         MOV R6, #0h
  0152 7F00         MOV R7, #0h
L0009:
  0154 8E04         MOV 4h, R6
  0156 8F05         MOV 5h, R7
  0158 BC051A       CJNE R4, #5h, L0006
  015B BD0017       CJNE R5, #0h, L0006
  015E 7464         MOV A, #64h
  0160 2513         ADD A, 13h
  0162 F513         MOV 13h, A
  0164 E4           CLR A
  0165 3514         ADDC A, 14h
  0167 F514         MOV 14h, A
  0169 E4           CLR A
  016A 3515         ADDC A, 15h
  016C F515         MOV 15h, A
  016E E4           CLR A
  016F 3516         ADDC A, 16h
  0171 F516         MOV 16h, A
  0173 801D         SJMP L0007

L0006:
  0175 8E02         MOV 2h, R6
  0177 EF           MOV A, R7
  0178 FB           MOV R3, A
  0179 33           RLC A
  017A 95E0         SUBB A, ACC
  017C FC           MOV R4, A
  017D FD           MOV R5, A
  017E EA           MOV A, R2
  017F 2513         ADD A, 13h
  0181 F513         MOV 13h, A
  0183 EB           MOV A, R3
  0184 3514         ADDC A, 14h
  0186 F514         MOV 14h, A
  0188 EC           MOV A, R4
  0189 3515         ADDC A, 15h
  018B F515         MOV 15h, A
  018D ED           MOV A, R5
  018E 3516         ADDC A, 16h
  0190 F516         MOV 16h, A
L0007:
  0192 0E           INC R6
  0193 BE0001       CJNE R6, #0h, L0008
  0196 0F           INC R7
L0008:
  0197 8E04         MOV 4h, R6
  0199 8F05         MOV 5h, R7
  019B C3           CLR C
  019C EC           MOV A, R4
  019D 940A         SUBB A, #0Ah
  019F ED           MOV A, R5
  01A0 6480         XRL A, #80h
  01A2 9480         SUBB A, #80h
  01A4 40AE         JC L0009
  01A6 AF0C         MOV R7, 0Ch
  01A8 BF1002       CJNE R7, #10h, L0010
  01AB 8005         SJMP L0011

L0010:
  01AD BF2030       CJNE R7, #20h, L0023
  01B0 8017         SJMP L0024

L0011:
  01B2 740A         MOV A, #0Ah
  01B4 2513         ADD A, 13h
  01B6 F513         MOV 13h, A
  01B8 E4           CLR A
  01B9 3514         ADDC A, 14h
  01BB F514         MOV 14h, A
  01BD E4           CLR A
  01BE 3515         ADDC A, 15h
  01C0 F515         MOV 15h, A
  01C2 E4           CLR A
  01C3 3516         ADDC A, 16h
  01C5 F516         MOV 16h, A
  01C7 802F         SJMP L0012

L0024:
  01C9 7414         MOV A, #14h
  01CB 2513         ADD A, 13h
  01CD F513         MOV 13h, A
  01CF E4           CLR A
  01D0 3514         ADDC A, 14h
  01D2 F514         MOV 14h, A
  01D4 E4           CLR A
  01D5 3515         ADDC A, 15h
  01D7 F515         MOV 15h, A
  01D9 E4           CLR A
  01DA 3516         ADDC A, 16h
  01DC F516         MOV 16h, A
  01DE 8018         SJMP L0012

L0023:
  01E0 E513         MOV A, 13h
  01E2 24FB         ADD A, #0FBh
  01E4 F513         MOV 13h, A
  01E6 E514         MOV A, 14h
  01E8 34FF         ADDC A, #0FFh
  01EA F514         MOV 14h, A
  01EC E515         MOV A, 15h
  01EE 34FF         ADDC A, #0FFh
  01F0 F515         MOV 15h, A
  01F2 E516         MOV A, 16h
  01F4 34FF         ADDC A, #0FFh
  01F6 F516         MOV 16h, A
L0012:
  01F8 851382       MOV DPL, 13h
  01FB 851483       MOV DPH, 14h
  01FE 750D03       MOV 0Dh, #3h
  0201 750E00       MOV 0Eh, #0h
  0204 120071       LCALL L0013
  0207 AC82         MOV R4, DPL
  0209 AD83         MOV R5, DPH
  020B AEF0         MOV R6, B
  020D FF           MOV R7, A
  020E EC           MOV A, R4
  020F 2513         ADD A, 13h
  0211 F513         MOV 13h, A
  0213 ED           MOV A, R5
  0214 3514         ADDC A, 14h
  0216 F514         MOV 14h, A
  0218 EE           MOV A, R6
  0219 3515         ADDC A, 15h
  021B F515         MOV 15h, A
  021D EF           MOV A, R7
  021E 3516         ADDC A, 16h
  0220 F516         MOV 16h, A
  0222 AC13         MOV R4, 13h
  0224 AD14         MOV R5, 14h
  0226 AE15         MOV R6, 15h
  0228 AF16         MOV R7, 16h
  022A 8C08         MOV 8h, R4
  022C 8D09         MOV 9h, R5
  022E 8E0A         MOV 0Ah, R6
  0230 8F0B         MOV 0Bh, R7
L0014:
  0232 AC08         MOV R4, 8h
  0234 AD09         MOV R5, 9h
  0236 AE0A         MOV R6, 0Ah
  0238 AF0B         MOV R7, 0Bh
  023A EC           MOV A, R4
  023B 6213         XRL 13h, A
  023D ED           MOV A, R5
  023E 6214         XRL 14h, A
  0240 EE           MOV A, R6
  0241 6215         XRL 15h, A
  0243 EF           MOV A, R7
  0244 6216         XRL 16h, A
  0246 80EA         SJMP L0014

L0015:
  0248 E582         MOV A, DPL
  024A 8517F0       MOV B, 17h
  024D A4           MUL AB
  024E C582         XCH A, DPL
  0250 C0F0         PUSH B
  0252 8518F0       MOV B, 18h
  0255 A4           MUL AB
  0256 D0F0         POP B
  0258 25F0         ADD A, B
  025A C583         XCH A, DPH
  025C 8517F0       MOV B, 17h
  025F A4           MUL AB
  0260 2583         ADD A, DPH
  0262 F583         MOV DPH, A
  0264 22           RET

L0019:
  0265 7A10         MOV R2, #10h
  0267 E4           CLR A
  0268 FB           MOV R3, A
  0269 FC           MOV R4, A
L0022:
  026A E582         MOV A, DPL
  026C 25E0         ADD A, ACC
  026E F582         MOV DPL, A
  0270 E583         MOV A, DPH
  0272 33           RLC A
  0273 F583         MOV DPH, A
  0275 EB           MOV A, R3
  0276 33           RLC A
  0277 FB           MOV R3, A
  0278 EC           MOV A, R4
  0279 33           RLC A
  027A FC           MOV R4, A
  027B EB           MOV A, R3
  027C 9517         SUBB A, 17h
  027E F5F0         MOV B, A
  0280 EC           MOV A, R4
  0281 9518         SUBB A, 18h
  0283 4006         JC L0021
  0285 FC           MOV R4, A
  0286 ABF0         MOV R3, B
  0288 438201       ORL DPL, #1h
L0021:
  028B DADD         DJNZ R2, L0022
  028D 22           RET

L0016:
  028E C2D5         CLR F0
  0290 E583         MOV A, DPH
  0292 30E70D       JNB ACC.7, L0017
  0295 D2D5         SETB F0
  0297 E4           CLR A
  0298 C3           CLR C
  0299 9582         SUBB A, DPL
  029B F582         MOV DPL, A
  029D E4           CLR A
  029E 9583         SUBB A, DPH
  02A0 F583         MOV DPH, A
L0017:
  02A2 E518         MOV A, 18h
  02A4 30E70D       JNB ACC.7, L0018
  02A7 B2D5         CPL F0
  02A9 E4           CLR A
  02AA C3           CLR C
  02AB 9517         SUBB A, 17h
  02AD F517         MOV 17h, A
  02AF E4           CLR A
  02B0 9518         SUBB A, 18h
  02B2 F518         MOV 18h, A
L0018:
  02B4 120265       LCALL L0019
  02B7 30D50B       JNB F0, L0020
  02BA E4           CLR A
  02BB C3           CLR C
  02BC 9582         SUBB A, DPL
  02BE F582         MOV DPL, A
  02C0 E4           CLR A
  02C1 9583         SUBB A, DPH
  02C3 F583         MOV DPH, A
L0020:
  02C5 22           RET

L0002:
  02C6 758200       MOV DPL, #0h
  02C9 22           RET

  02CA 54           DB 054h ; 'T'
  02CB 41           DB 041h ; 'A'
  02CC 52           DB 052h ; 'R'
  02CD 47           DB 047h ; 'G'
  02CE 45           DB 045h ; 'E'
  02CF 54           DB 054h ; 'T'
  02D0 5F           DB 05Fh ; '_'
  02D1 53           DB 053h ; 'S'
  02D2 54           DB 054h ; 'T'
  02D3 52           DB 052h ; 'R'
  02D4 49           DB 049h ; 'I'
  02D5 4E           DB 04Eh ; 'N'
  02D6 47           DB 047h ; 'G'
  02D7 00           DB 000h 
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>c</category>
      <category>code</category>
      <category>programming</category>
      <category>software</category>
    </item>
  </channel>
</rss>
