<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Retrocoding - Old Things, New Way.]]></title><description><![CDATA[Retrocoding is about discovering new knowledge by exploring old software and hardware.]]></description><link>https://retrocoding.net</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1650611780459/vq6bHghdu.png</url><title>Retrocoding - Old Things, New Way.</title><link>https://retrocoding.net</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 03:36:51 GMT</lastBuildDate><atom:link href="https://retrocoding.net/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building for DOS, OS/2, and DOS on a Macbook Apple Silicon.]]></title><description><![CDATA[I've previously written about OpenWatcom as a gateway to the ancient world. However, at that time, I focused on installing it using Docker, as OpenWatcom 1.9 only works on Windows and Linux. I'm not a full-time Windows or Linux user, so when I discov...]]></description><link>https://retrocoding.net/building-for-dos-os2-and-dos-on-a-macbook-apple-silicon</link><guid isPermaLink="true">https://retrocoding.net/building-for-dos-os2-and-dos-on-a-macbook-apple-silicon</guid><category><![CDATA[Retrocoding]]></category><category><![CDATA[legacy]]></category><category><![CDATA[DOS]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Sat, 10 Feb 2024 06:53:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707544645636/25d6651f-899f-4226-83ba-796ad85c98ce.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've previously written about <a target="_blank" href="https://retrocoding.net/openwatcom-gateway-to-ancient-world-of-x86">OpenWatcom as a gateway to the ancient world</a>. However, at that time, I focused on installing it using Docker, as OpenWatcom 1.9 only works on Windows and Linux. I'm not a full-time Windows or Linux user, so when I discovered that OpenWatcom's 2.0 series can be compiled and run on macOS, <strong>and</strong> it can run on ARM macOS, I was thrilled.</p>
<p>It's not mentioned on their website, and only in less prominent places like GitHub Issues. However, after testing it out, I believe it's worth sharing with others who share my hobby: writing old Windows (and DOS) applications but still wants to use their newest, shiniest MacBook to do so.</p>
<h2 id="heading-preparation">Preparation</h2>
<p>There are some preparations you need to do before building OpenWatcom source code on an Apple Silicon.</p>
<p><strong>First, the compiler and platform SDK</strong>. To build anything on macOS, you need their official compiler and IDE. Xcode. Recently, they tried to slim everything down, so it'll be 2 GB-ish download from developer.apple.com.</p>
<p><strong>Second, homebrew</strong>. This is optional if you know what you're doing. However, to smoothly compile OpenWatcom, you'd need DOSBOX command line and I feel the easiest way to obtain DosBox is using homebrew. Instal it from <a target="_blank" href="https://brew.sh">brew.sh</a>.</p>
<h2 id="heading-getting-dependencies">Getting Dependencies</h2>
<p>To get the dependencies, first we install DosBox. In Terminal, use this command to install dosbox.</p>
<pre><code class="lang-bash">brew install dosbox
</code></pre>
<p>That's the only dependencies you need.</p>
<h2 id="heading-compilation">Compilation</h2>
<p>Compilation is actually straightforward. You'd only to obtain the source code for "latest" OpenWatcom v2.0 series. I'm using the February 2024 archive. Go to the release page and dowload the source (.tar.gz). Extract it</p>
<pre><code class="lang-bash">tar xvzf open-watcom-v2-2024-02-02-Build.tar.gz
</code></pre>
<p>Before we do everything, now open the file <code>setenv.h</code> and search for line with <code>export OWTOOLS</code> and change it to:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> OWTOOLS=CLANG
</code></pre>
<p>This will change the compilation to clang, the compiler built into Xcode and then search for the line with <code>export OWDOSBOX</code>, uncomment and change it to.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> OWDOSBOX=dosbox
</code></pre>
<p>From this point forward you're ready. The last step is just run this</p>
<pre><code class="lang-bash">./build.sh
</code></pre>
<p>And, wait. This will compile the OpenWatcom compiler using your <code>clang</code> compiler on your ARM64 platform. If everything is finished, you can put the compiled product by using this command.</p>
<pre><code class="lang-bash">./build.sh rel
</code></pre>
<p>This will copy the resulting compilers, supporting headers for all supported platforms, as well as the libraries into <code>rel</code> directory.</p>
<h2 id="heading-using-the-compiled-compilers-and-tools">Using the Compiled Compilers and Tools</h2>
<p>I'm usually using watcom on a directory that I put on paths. For me it's on <code>/opt/watcom</code>. So if you haven't made it yet, you can run this to create a directory for your watcom installation and copy everything into that place.</p>
<pre><code class="lang-bash">mkdir -p /opt/watcom
<span class="hljs-built_in">cd</span> rel &amp;&amp; copy -a . /opt/watcom
</code></pre>
<p>To use the binary, you need to add the toolchain to <code>PATH</code>. The toolchain for Apple Silicon mac is in <code>armo64</code> subdirectory. You need to also setup the <code>WATCOM</code> environment variable. That will point to our installation directory.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> WATCOM=/opt/watcom
<span class="hljs-built_in">export</span> PATH=<span class="hljs-variable">$PATH</span>:<span class="hljs-variable">$WATCOM</span>/armo64
<span class="hljs-built_in">export</span> EDDAT=<span class="hljs-variable">$WATCOM</span>/eddat
</code></pre>
<p>For each platform (16-bit Windows, 32-bit Windows, DOS, OS2) you need to set different environment variables for <code>INCLUDE</code> and <code>LIBS</code>. Here's for 32-bit Windows platform.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> INCLUDE=<span class="hljs-variable">$WATCOM</span>/h:<span class="hljs-variable">$WATCOM</span>/h/nt:<span class="hljs-variable">$WATCOM</span>/h/nt/ddk:<span class="hljs-variable">$WATCOM</span>/h/nt/sdk:<span class="hljs-variable">$WATCOM</span>/h/nt/sdk/ntddk:<span class="hljs-variable">$WATCOM</span>/h/nt/sdk/wdm:<span class="hljs-variable">$WATCOM</span>/h/nt/sdk/wdm/dd
<span class="hljs-built_in">export</span> LIBS=<span class="hljs-variable">$WATCOM</span>/lib386:<span class="hljs-variable">$WATCOM</span>/lib386/nt:<span class="hljs-variable">$WATCOM</span>/lib386/nt/ddk:<span class="hljs-variable">$WATCOM</span>/lib386/nt/sdk:<span class="hljs-variable">$WATCOM</span>/lib386/nt/sdk/ntddk:<span class="hljs-variable">$WATCOM</span>/lib386/nt/sdk/wdm:<span class="hljs-variable">$WATCOM</span>/lib386/nt/sdk/wdm/ddk
</code></pre>
<p>Please refer to the OpenWatcom/Watcom manual on where the headers and the libs are. You can basically guess from <code>/h</code> directory and <code>/libxxx</code> directory.</p>
<p>After that you can run <code>wcl386</code> to see whether it works or not.</p>
<pre><code class="lang-bash">❯ wcl386 -h
Open Watcom C/C++ x86 32-bit Compile and Link Utility
Version 2.0 beta Feb 10 2024 00:00:59
Copyright (c) 2002-2024 The Open Watcom Contributors. All Rights Reserved.
Portions Copyright (c) 1988-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.
See https://github.com/open-watcom/open-watcom-v2<span class="hljs-comment">#readme for details.</span>
</code></pre>
<p>This means that your watcom compilers are ready to be used to target old platforms.</p>
]]></content:encoded></item><item><title><![CDATA[The 90s Developer Starter Pack]]></title><description><![CDATA[I recently found a 386 emulator called 86Box, a fork of the earlier version of PCEm. Because I'm a real programmer™, I build the master branch from its Git source on a macOS Ventura. How I build it from sources will be the subject of a new article.
B...]]></description><link>https://retrocoding.net/the-90s-developer-starter-pack</link><guid isPermaLink="true">https://retrocoding.net/the-90s-developer-starter-pack</guid><category><![CDATA[Win32]]></category><category><![CDATA[Retrocoding]]></category><category><![CDATA[Windows]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Sat, 05 Nov 2022 16:09:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/0uXzoEzYZ4I/upload/v1667641186529/NSH6ZnTeW.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently found a 386 emulator called 86Box, a fork of the earlier version of PCEm. Because I'm a real programmer™, I build the <code>master</code> branch from its Git source on a macOS Ventura. How I build it from sources will be the subject of a new article.</p>
<h1 id="heading-building-the-hardware-specifications">Building The Hardware Specifications</h1>
<p>86Box supports a breadth of selection of combinations of PC hardware components in the 90s. A real gold mine for a person like me who lives in a developing country with restricted access to old hardware. I set a goal to replicate the experience of installing a fresh Windows 95 PC from hardware available around 1990-1995. I'll limit it to something typical for developers on 95s to run on their medium-powered PC, which may have a few esoteric components. I remember my late father having AMD Am486 with 8MB of RAM. So I'll use that as a frame of reference. Also, I've found an article <a target="_blank" href="https://www.chicagotribune.com/news/ct-xpm-1995-11-03-9511030044-story.html">about buyers' guides from the Chicago Tribune explaining the spec for the holiday season in 1995</a>.</p>
<p>After mucking around the settings, these are the components that I decided to have.</p>
<h2 id="heading-cpu">CPU</h2>
<p>I'll go with <strong>AMD Am486DX4 with 100 MHz</strong> Speed with PGA 168 socket. This is how it originally looked like</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667642338455/_lMQJWFx8.jpg" alt="AMD Am486DX4 100MHz" /></p>
<p>There's "Designed for Windows 95" imprinted on the chip itself. We're going to a good start.  This chip is Intel 486 compatible. I didn't go to Pentium or Pentium Pro because I wanted pure, unextended, intel 486 instruction sets with no Pentium Pro extensions like <code>CMOVNS</code>, which I've written about in my previous posts. </p>
<h2 id="heading-motherboard">Motherboard</h2>
<p>ASUS PVI-486SP3C with SiS 496 as the Chipset. Without further ADO, please look at this beauty.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667642689155/xRlenge2K.jpg" alt="ASUS PVI-486SP3C" /></p>
<p>As depicted in the picture above, this motherboard featured a PGA168 socket. With both SIS 496 as the Northbridge chip and SIS 497 as the Southbridge chip. This features these I/O:</p>
<ul>
<li>Dual-channel IDE.</li>
<li>1 Floppy Disk Interface.</li>
<li>3 PIC slots.</li>
<li>4 ISA slots, with one of them being a VLB slot (that extension is not an AGP slot, it didn't exist back then)</li>
<li>One parallel, two serial ports, and 1 PS/2 port.</li>
</ul>
<h2 id="heading-ram-and-disks">RAM and Disks</h2>
<p>There are two EDO-RAM over there, which I'll fill with a whopping 16 MB of RAM, which is 4 times the minimum requirement for Windows 95. As for disk, we'll fill all floppy disk controllers with 2.88 MB Drives. On the IDE slot, we'll put a 2GB disk drive.</p>
<p>We'll utilise ZIP drives and CD-ROM. I'll not use IDE for these. Like a grown-up, let's use SCSI for both ZIP and CD ROM drives.</p>
<h2 id="heading-components-and-accessories">Components and Accessories</h2>
<p>I'll start with the graphics card. Because we were in 1994, and we have a VLB slot, let's use that. We're going to use the S3 Vision964 VLB Version.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667644946189/qrpXhIgT_.jpeg" alt="Elsa Winner S3 Vision 964 Card" /></p>
<p>This card is an accelerated card which allows us to decode MPEG-1 without any additional accelerator cards.</p>
<p>The next obvious accessory is the sound card. We're not going crazy this time. Let's use good ol' Sound Blaster 16-bit and fill one more of our ISA slots.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667645205759/ijBrWahzA.jpg" alt="Sound Blaster 16 bit" /></p>
<p>As we're going to use SCSI, we're going to use BusLogic PCI BT-958D for our SCSI controller, which will drive both ZIP Drive and CD ROM drives.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667645641177/Xd4rsBVyH.jpeg" alt="BusLogic" /></p>
<h1 id="heading-operating-systems-and-software-installations">Operating Systems and Software Installations</h1>
<h2 id="heading-prerequisite-microsoft-dos-622">Prerequisite: Microsoft DOS 6.22</h2>
<p>Most of the motherboard is not ready for booting from CDs, let alone SCSI. So, unlike Windows 98. To install Windows 95, you'd need Microsoft DOS 6.22. We're going to install it, and for me, I'll also enable the Dvorak keyboard. I'll gloss over this process as you might already know how to install them from diskettes. After installing MSDOS, you'll be greeted with the typical C-prompt <code>C:\</code>. I usually install the supplemental disk to be able to use Dvorak as my keyboard and add this line to <code>AUTOEXEC.BAT</code> file.</p>
<pre><code>REM Use Dvorak Keyboard
KEYB DV,,C:\DOS\DVORAK.SYS
</code></pre><p>We'd need to access our CDROM, which is attached to a SCSI card. For this we'll use the driver from BusLogic and Microsoft MSCDEX. You can find the file on the net. The name are <code>btdosm.sys</code> <code>btcdrom.sys</code> and <code>mscdex.exe</code>. To access the drive, we'll need to load them on our <code>CONFIG.SYS</code> file.</p>
<pre><code>DEVICE=BTDOSM.SYS
DEVICE=BTCDROM.SYS /D:RETROCD
</code></pre><p>And then add this line to <code>AUTOEXEC.BAT</code></p>
<pre><code>REM Mount CD ROM
MSCDEX.EXE /D:RETROCD
</code></pre><p>Reboot, and now you can access your <code>D</code> drive from DOS command prompt.</p>
<h2 id="heading-install-windows-95-osr-25">Install Windows 95 OSR 2.5</h2>
<p>Mount your Windows 95 on the CD Drive and then go to drive D.</p>
<pre><code>C:\&gt; D:
D:\&gt; SETUP
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667655529827/b5Ok_zHi2.png" alt="Setup Wizard" /></p>
<p>Follow the setup instructions, and you'll end up with a desktop. Right-click on the <strong>My Computer</strong> section and select <strong>Properties</strong>. You'll end up with something like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667655920414/6CdD0c8JD.png" alt="Desktop Machine Properties" /></p>
<p>Look at that 16 MB RAM and a proud 80486 owner with all the bells and whistles. Now time to install our development tool of choice.</p>
<h2 id="heading-development-tools">Development Tools</h2>
<p>We're "real programmers", so we're not gonna use peasants' tools like Visual Basic. No, no siree... We are going to use a real programming language like C++. So prepare your <a target="_blank" href="https://winworldpc.com/product/microsoft-visual-stu/97-5x">Visual Studio Enterprise 97</a> disks and install Visual C++.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667656275181/2WacmCqyL.png" alt="Visual C++ Advertisement of COM" />.</p>
<p>Look at that! What an amazing compiler supporting <a target="_blank" href="https://en.wikipedia.org/wiki/Component_Object_Model">COM</a>, and it supports creating COM clients and interfaces, exciting time to code in 1994.</p>
<p>If you are clueless enough, you can also install the MSDN for Visual Studio 97 if you can get the CD image from the internet. However, our next step is very simple. We won't need to use that.</p>
<h1 id="heading-coding">Coding</h1>
<p>So we have our money-making machine being set up. The next step is to write a program for the 90s. Let's give ourselves a treat of being beginners again and see what we can achieve using a 30-years-old platform with machine 1/1000 times less powerful than our typical phone in 2022.</p>
<p>Let's fire up the IDE and enjoy the developer tools created by Microsoft in the early 90s.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667661905493/wy8ZcwYb6.png" alt="Hello Win95" /></p>
<p>Proceed by selecting "Win32 Application" and then choose "Empty Project". You'll be greeted with an empty project. Add new files named <code>main.cpp</code> to the files section and let's start by building a GUI program which will show you a "Hello, Welcome to Windows95" message box.</p>
<h2 id="heading-entry-point">Entry Point</h2>
<p>A win32 project entry point is not <code>main</code> but <code>WinMain</code>. A minimal program which will start and do absolutely nothing will be as follows.</p>
<pre><code class="lang-C"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;Windows.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> APIENTRY <span class="hljs-title">WinMain</span><span class="hljs-params">(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, <span class="hljs-keyword">int</span> nCmdShow)</span>
</span>{
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>Although the program does absolutely nothing, it'll just start and immediately exit, the function signature is a mouthful and verbose. Not all of these parameters are important or even usable. This is the quirk of Windows programming as Microsoft needs to maintain the API signature for backward compatibility. </p>
<ol>
<li>Including the <code>Windows.h</code> header is mandatory for all Windows programs written this way.</li>
<li>The <code>WinMain</code> function needs to return an <code>int</code>. If there's no Windows Message Pump defined, return <code>0</code> on exist. We'll talk about Windows Message Pump in another post.</li>
<li><code>APIENTRY</code> is an alias to stdcall calling convention, which means the function itself will clean the stack.</li>
<li><code>HINSTANCE</code> is a "handle" to an application instance. A handle is an opaque value for an object within Windows operating system. Both first parameters are purely for backward compatibility. The first <code>HINSTANCE</code> is always pegged to <code>0x04</code>, and the second is always <code>0x00</code> on 32-bit protected mode Windows.</li>
<li><code>lpCmdLine</code> is the command line to invoke the program. We can use this parameter to parse the command line and its arguments when it's invoked from the command line.</li>
<li><code>nCmdShow</code> is the value which tell the window, if the Window will be shown minimised, maximised, or hidden.</li>
</ol>
<p>Try to build the application, and you'll see.. nothing. Building only validates that our syntax is correct. The message on the build window will show something like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667663069376/E8PVkXUuP.png" alt="Building Program Console" /></p>
<h2 id="heading-our-first-windows-api">Our first Windows API</h2>
<p>When we started with something new, we started with "Hello, World!" program. This can be accomplished in Win32 API by calling <code>MessageBox</code> function. The function prototype is very simple.</p>
<pre><code class="lang-C"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">MessageBox</span><span class="hljs-params">(HWND hWnd, LPSTR lpText, LPSTR lpCaption, UINT uType)</span></span>;
</code></pre>
<p>The meaning of each of the parameter are:</p>
<ul>
<li><code>hWnd</code> is the parent window of the message box window being displayed. Passing <code>0</code> means that the message box parent will be the Desktop.</li>
<li><code>lpText</code> is a zero-terminated string containing the message to be displayed.</li>
<li><code>lpCaption</code> is the caption of the message box.</li>
<li><code>uType</code> is the message box type. There are several values that you can use. The value is a bit flag. We'll use <code>MB_OK | MB_ICONINFORMATION</code> which means that we'll only show the OK button and an information icon.</li>
</ul>
<p>The full program to be run is as below:</p>
<pre><code class="lang-C"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;Windows.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> APIENTRY <span class="hljs-title">WinMain</span><span class="hljs-params">(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR lpCmdLine, <span class="hljs-keyword">int</span> nCmdShow)</span>
</span>{
  MessageBox(<span class="hljs-literal">NULL</span>, <span class="hljs-string">"Hello, Welcome to Win32 Programming"</span>, 
      <span class="hljs-string">"Hello, World"</span>, MB_OK | MB_ICONINFORMATION);
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>And the program will show a nice message box.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667664027301/s938PW0B6.png" alt="Hello World Win32" /></p>
<p>That's it! Our first GUI program using Win32 API running on typical early 90s workstation running on Windows 95. There will be more which we'll explore on next articles. Including on how to create a window and draw something there.</p>
<p>If you curious, you can build the executable to an .exe and then try to run it on modern Windows operating system like Windows 11. You'll surprise that the program still run perfectly fine.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Windows 95 is the first full 32-bit Windows that's built by Microsoft. It's a break from previous generations of Windows which brings 32-bit programming to consumer which previously was only available on Windows NT. Programming C/C++ in Windows differs with typical console-based C/C++ applications. For example, the entry point of Win32 program is <code>WinMain</code> and not <code>main</code>. In the future article we'll explore more about Window 95 and Win32 API.</p>
]]></content:encoded></item><item><title><![CDATA[Windows API is Successful Cross-Platform API.]]></title><description><![CDATA[You might find the title a little bit odd. Hold your thought for a moment and hear me out. I'm a big believer that in technology, and life, something that comes from consensus from a big, top-down standardisation body usually fails. The internet is a...]]></description><link>https://retrocoding.net/windows-api-is-successful-cross-platform-api</link><guid isPermaLink="true">https://retrocoding.net/windows-api-is-successful-cross-platform-api</guid><category><![CDATA[Windows]]></category><category><![CDATA[Linux]]></category><category><![CDATA[macOS]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Wed, 02 Nov 2022 18:03:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/T01GZhBSyMQ/upload/v1667327314282/zBSIVRbQNx.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You might find the title a little bit odd. Hold your thought for a moment and hear me out. I'm a big believer that in technology, and life, something that comes from consensus from a big, top-down standardisation body usually fails. The internet is an example of the implementation of a top-down approach when a scientist submits a paper for an RFC and <em>iterates</em> on it until it's <em>de-facto</em> protocol of the internet.</p>
<p>The keyword here is <em>iterate</em>. Most of the standard body tries to cover many use cases, primarily their members' interests. This leads to bloated, inefficient and largely unused standards. While their nimbler competition is being adopted, iterated, and expanded. In the internet protocol use cases, OSI Model is now essentially <em>just a theory</em> taught in networking training, certification, and classes. In the real world, the internet <strong>is</strong> TCP/IP, and it's TCP IP that runs on computers, phones, and other devices.</p>
<h1 id="heading-adoption-driven-by-pragmatism">Adoption Driven By Pragmatism</h1>
<p>A successful standard is driven by pragmatism. One such standard is POSIX. This standard came from the need to standardise API across UNIX variants and clones. Most modern operating systems implement this standard. From well-known operating systems kernels such as Linux and Darwin (a.k.a Apple macOS) to hobbyist operating systems like Redox and Managarm implements POSIX as their user-space API. Why did I put Windows aside, you might say? I'll talk about that later.</p>
<p>The reason they're implementing POSIX is because of the rich ecosystem it offers. All tooling from GNU, like GCC, will run on a POSIX-compliant operating system. If you build an operating system kernel and then adopt POSIX as your user-space API and decent terminal, you're off to a good start in accessing the breadth of software selections running on your operating system.</p>
<p>Apple took this path when they built Darwin, the kernel of macOS, or previously NeXTStep. NeXT built their kernel by combining Mach and BSD code and then used GCC as its compiler of choice. This way, NeXT saved tremendous time compared to if they built everything alone. They can focus on building the UI which matters to their customers. This was also true for Linux. All software built with POSIX in mind can run on top of Linux. The conformance to POSIX was born due to necessity and pragmatism.</p>
<h1 id="heading-windows-api">Windows API</h1>
<p>Unlike NeXT, Windows was written from scratch without considering POSIX compatibility. It was written as a GUI layer on top of a less powerful MS-DOS kernel. Microsoft built the API to enable programmers to create programs on top of then, just released Windows.  The early versions of Windows had their SDK in a single header called <code>&lt;Windows.h&gt;</code>. The first Windows SDK fits in seven 400KB diskettes and has only two headers: <code>STYLE.H</code> and <code>WINDOWS.H</code>. The <code>Windows.h</code> header was only 2000+ lines of code. It was a very lean SDK. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667407385104/2gTV-u67-.png" alt="The Windows 1.0 Windows Header" /></p>
<p>Windows 95 is the beginning of 32-bit computing for Microsoft, and the API is being upgraded to cater to 32-bit computing. Microsoft dubbed the new API: "Win32". Windows has grown significantly that <code>Windows.h</code> is no longer a single header. It includes other headers from other subsystems. Microsoft rewrote Windows to Windows NT with mostly unchanged API, expanded the API to 'wide-character', and made Windows <a target="_blank" href="https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows">supports early Unicode encoding</a>.</p>
<p>From that point, Windows API keeps expanding. Microsoft added a bunch of new technology that I lost count of. Sometimes, however, Microsoft did not do a good job when naming their API. <a target="_blank" href="https://learn.microsoft.com/en-us/windows/win32/dataxchg/about-dynamic-data-exchange">Dynamic Data Exchange</a>, for example, evolved to COM, which was then branded as OLE and OLE Automation. They have unintelligible names that do not explain what they do. It's a shame, tho, as COM (or OLE) is a very useful piece of technology. The branding obscured its usability despite its apparent complexity and boilerplate. The pattern has been imitated by Mozilla and even Apple in their driver framework. <a target="_blank" href="https://jeamland.net/">Beno Rice</a> explained it in this video:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/9-IWMbJXoLM?t=293">https://youtu.be/9-IWMbJXoLM?t=293</a></div>
<p>Microsoft added more APIs because they could: CryptoAPI, DirectX, and so forth. Windows becomes a rich desktop platform. They bundled all of the different APIs and renamed them to simply <strong>Windows API</strong></p>
<h1 id="heading-windows-api-as-pragmatic-cross-platform-desktop-api">Windows API as Pragmatic Cross-Platform Desktop API</h1>
<p>Windows dominates the Desktop Operating system with more than 80% market share. As Windows grows in market share, so do programs written for Windows. It's not unusual for people to only write a desktop application for Windows. Rather than writing for gazillion desktop environments like GTK or Qt, programmers prefer a predictable and stable API with many learning resources. Microsoft has done a very good job taking care of their ISV (Independent Software Vendors) by building Visual Studio, a remarkable programming IDE and forming MSDN, Microsoft Developer Network, which in my opinion, is the most comprehensive API documentation.</p>
<p>Those programs written by Windows programmers are usable, and people want to run that on systems like Linux. Hence, the <a target="_blank" href="https://www.winehq.org/">WINE project</a> was born. It loads the executable and then redirects Windows API calls to Linux (or macOS) calls. Surprisingly, this effort is successful. Most programs can run on top of Wine. A company called <a target="_blank" href="https://www.codeweavers.com/">Codeweavers</a> packages Wine and sells it for a fee for an easy-to-use version of Wine. While doing Windows Retrocoding, I use CrossOver to test my programs on macOS. It runs well and never fails on me.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1667410872784/fj6fHqIhG.png" alt="Dependency Walker 32-bit running on macOS over Crossover" /></p>
<p>Windows is also <strong>the platform</strong> for Games. Microsoft has won the API wars between Direct3D and OpenGL. Microsoft's domination in PC gaming is undisputed. However, there is still a sizeable portion of users wishing to run Windows on their Linux Desktop. Steam, the major distribution channel for games on Windows, implements their own version of Wine for gaming and names it Proton. It allows games which originally written <strong>only</strong> for Windows to run on Linux.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=vXTPyrKICkA">https://www.youtube.com/watch?v=vXTPyrKICkA</a></div>
<p>The compatibility rate of games running on Proton is also pretty good. I tried running Final Fantasy XIII on a Linux machine, and it worked. </p>
<h1 id="heading-windows-api-is-successful-desktop-runtime">Windows API is Successful Desktop Runtime</h1>
<p>Windows uses a <a target="_blank" href="https://en.wikipedia.org/wiki/Portable_Executable">Portable Executable</a> file format, which is originally only intended to be run on top of Windows. However, the format and the API are now generally available for all three major desktop operating systems using Wine, Crossover, or Proton.</p>
<p>In the 90s and early 2000s, Java was marketed as a platform in which one code (bytecode) is run on multiple platforms. It is true for non-x86-based platforms. However, in most cases, Portable Executable is "portable" as it can be executed without modification and recompilation. Now you can run desktop applications, which were originally only written only for Windows, on Linux and macOS. Even if Windows' market share is only 80% of the desktop computing market. Windows API has a 100% market share as it can run on all three major Desktop operating systems.</p>
<p>Windows API and executable format adoption are not imposed by any standard body. Heck, Windows API still has undocumented functions and behaviours, and even Microsoft has blocked the effort to standardise it to an ISO. The adoption was done out of necessity, and people find it useful.</p>
]]></content:encoded></item><item><title><![CDATA[OpenWatcom, Gateway to Ancient World of x86]]></title><description><![CDATA[In my articles in this retrocoding.net I use OpenWatcom compiler extensively. This is because this is the only compiler which allows me to program back into the ancient world. By ancient, I meant, the world of 8088, where the first PC was made. I exp...]]></description><link>https://retrocoding.net/openwatcom-gateway-to-ancient-world-of-x86</link><guid isPermaLink="true">https://retrocoding.net/openwatcom-gateway-to-ancient-world-of-x86</guid><category><![CDATA[Microsoft]]></category><category><![CDATA[C]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Sat, 21 May 2022 20:47:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1653158867043/s-SIqzNtT.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my articles in this retrocoding.net I use OpenWatcom compiler extensively. This is because this is the only compiler which allows me to program back into the ancient world. By ancient, I meant, the world of 8088, where the first PC was made. I explore the wisdom of the old world of PASCAL calling convention ubiquitous in 16-bit operating systems such as Windows 3.x.</p>
<h1 id="heading-supported-host-systems">Supported Host Systems</h1>
<p>I use primarily OpenWatcom 1.9 which you can download from <a target="_blank" href="http://openwatcom.org/download.php">OpenWatcom.org website</a> but it's largely unmaintained. The 2.x fork is hosted on <a target="_blank" href="https://github.com/open-watcom">Github</a> which is actively maintained. It supports Windows and Linux as the host OS, and you can also use macOS from the 2.x fork but you'd need to build yourselves.</p>
<p>Because it uses Linux, you're able to run it under docker. I maintain the Watcom 1.9 Linux docker. Just pull and you can use it to compile program for old systems.</p>
<pre><code>$ docker pull ykode<span class="hljs-operator">/</span>openwatcom:<span class="hljs-number">1.9</span><span class="hljs-operator">-</span>ubi
</code></pre><h1 id="heading-supported-target-systems">Supported Target Systems</h1>
<p>OpenWatcom has very extensive target system both in processors as well as the operating systems. OpenWatcom is the only compiler that I know which is able to generate code for 8088 to Pentium Pro. Watcom also supports these target systems:</p>
<ul>
<li>MS DOS Real Mode, both <a target="_blank" href="https://en.wikipedia.org/wiki/COM_file">COM</a> and <a target="_blank" href="https://en.wikipedia.org/wiki/DOS_MZ_executable">EXE</a> files.</li>
<li>MS DOS with DOS Extender.</li>
<li>16-bit Windows like Windows 3.x.</li>
<li>32-bit Windows like Windows 9x and Windows NT.</li>
<li><a target="_blank" href="https://blackberry.qnx.com/en">QNX</a></li>
<li>And many more. You can read from the <code>tools.pdf</code> file included in github or openwatcom.org website.</li>
</ul>
<p>The OpenWatcom Linker is actually pretty configurable in which you can add more systems yourself if you want. You can write </p>
<h1 id="heading-supported-programming-languages">Supported Programming Languages</h1>
<p>OpenWatcom supports C and C++ as well as <a target="_blank" href="https://en.wikipedia.org/wiki/Fortran">Fortran</a>. It also provides additional calling convention for 16 and 32 bit application called <code>WATCOM</code> which will mangle function symbol name by adding additional underscore after symbol and will pass parameters by register rather than stack.</p>
<p>OpenWatcom also provides C Runtime libraries which is able to be run on 386, 486 both for Windows and DOS which are the processors and operating systems I'm interested in exploring.</p>
<p>id Softwore used Watcom as the compiler for DOOM. Watcom is used extensively in game programming on DOS. The original DOOM uses Watcom when it was still a commercial product. You can read the full story <a target="_blank" href="https://www.filfre.net/2020/06/the-shareware-scene-part-4-doom/">here</a>.</p>
<blockquote>
<p>Carmack chose the Watcom compiler because of DOS/4GW; DOOM would quite literally have been impossible without it. In the aftermath of DOOM‘s prominent use of it, Watcom’s would become the C compiler of choice for game development, right through the remaining years of the MS-DOS-gaming era.</p>
</blockquote>
<h1 id="heading-hello-world-for-8088">Hello World, for 8088</h1>
<p>Let's say you have <a target="_blank" href="https://en.wikipedia.org/wiki/IBM_Personal_Computer">original IBM PC model 5150</a> released 40 years ago in 1981 and you want to create a program running on that computer today. What you can do is just open up text editor and write some C code as usual.</p>
<pre><code class="lang-C"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> **argv)</span> </span>{
  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Hello, World!"</span>);  
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>And of course a <code>CMakeLists.txt</code> file </p>
<pre><code class="lang-cmake">project(hello)

set(SOURCES main.c)

add_executable(hello ${SOURCES})
</code></pre>
<p>And of course we create a <code>build/dos88</code> directory to be able to build it for 8088-based MS-DOS computers like IBM XT.</p>
<pre><code><span class="hljs-operator">&gt;</span> cd build<span class="hljs-operator">/</span>dos88

<span class="hljs-operator">&gt;</span> cmake <span class="hljs-operator">-</span>DCMAKE_SYSTEM_NAME<span class="hljs-operator">=</span>DOS <span class="hljs-operator">-</span>DCMAKE_SYSTEM_PROCESSOR<span class="hljs-operator">=</span>I86 <span class="hljs-operator">-</span>DCMAKE_C_FLAGS<span class="hljs-operator">=</span><span class="hljs-string">"-0 -bt=dos -d0 -oaxt"</span> <span class="hljs-operator">-</span>G <span class="hljs-string">"Watcom WMake"</span> ../..

<span class="hljs-operator">&gt;</span> wmake
</code></pre><p>You'll get a <code>hello.exe</code> file which you can copy to a floppy image and insert or mount if you're using emulator.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653165706245/u9ud-wJ4s.png" alt="Hello, World! In 8088 IBM XT Computer running MS-DOS 1980" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>OpenWatcom is a compiler that enables us to build and run x86-based system on old platforms like MS-DOS. With CMake this task is even easier. </p>
]]></content:encoded></item><item><title><![CDATA[Secure Oldies V: Windows 3.x and Winsock 1.1]]></title><description><![CDATA[Despite the version numbering, Windows NT 3.1 is the first Windows NT released at 1993. Windows NT was the first 32-bit platform that Microsoft has free of legacy things like MS-DOS. It was complete rewrite rather than a refactor of the Windows they ...]]></description><link>https://retrocoding.net/secure-oldies-v-windows-3x-and-winsock-11</link><guid isPermaLink="true">https://retrocoding.net/secure-oldies-v-windows-3x-and-winsock-11</guid><category><![CDATA[networking]]></category><category><![CDATA[socket]]></category><category><![CDATA[Windows]]></category><category><![CDATA[General Programming]]></category><category><![CDATA[C]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Sat, 21 May 2022 13:22:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1653126370788/2Lw08bqw3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Despite the version numbering, Windows NT 3.1 is the first Windows NT released at 1993. Windows NT was the first 32-bit platform that Microsoft has free of legacy things like MS-DOS. It was complete rewrite rather than a refactor of the Windows they had before, Windows 3.1.</p>
<h1 id="heading-porting-to-windows-nt-3x">Porting to Windows NT 3.x</h1>
<p>I hesitated to target this OS due to two things:</p>
<ol>
<li>I'm unsure about the compatibility of early Winsock version before Winsock 2.0.</li>
<li>Windows NT 3.x has no CryptoAPI support which makes it lacks of cryptographically secure pseudo number generator. CryptoAPI support only available for Windows NT 4 and up.</li>
</ol>
<p>However, I managed to compile it with some caveats</p>
<ol>
<li>It will use Winsock 1.x which is only available for TCP/IP.</li>
<li>It won't be secure, as I'll use garbage memory from calling <code>malloc</code>, which I think is not random enough. But I'll use it as entropy source.</li>
<li>Only support Windows 3.51 and up.</li>
</ol>
<p><em>Warning: this port is not secure, and I advised strongly not to use this other than for entertainment and educational purposes</em></p>
<h2 id="heading-step-1-turn-off-platform-entropy-source">Step 1: Turn off platform entropy source</h2>
<p>Because mbedTLS is so portable, it also allows us to supply any custom entropy source. To avoid linking to CryptoAPI we'd need to turn off platform entropy source by opening <code>mbedtls_config.h</code>. Find a definition of <code>MBEDTLS_NO_PLATFORM_ENTROPY</code> and uncomment that line this will turn off platform entropy based on CryptoAPI.</p>
<pre><code class="lang-c"><span class="hljs-comment">/**
 * \def MBEDTLS_NO_PLATFORM_ENTROPY
 *
 * Do not use built-in platform entropy functions.
 * This is useful if your platform does not support
 * standards like the /dev/urandom or Windows CryptoAPI.
 *
 * Uncomment this macro to disable the built-in platform entropy functions.
 */</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MBEDTLS_NO_PLATFORM_ENTROPY</span>
</code></pre>
<p>If we recompile this binary, the result will be error -0x34 which weans that entropy doesn't work.</p>
<p>We'd need to <em>somehow</em> supply an entropy based on the fact that if we do <code>malloc</code>, it'll allocate a memory region filled with garbage and then we tell mbedTLS that this is a strong entropy source (which is not), otherwise mbedTLS will refuse to work.</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">weak_entropy_source_cb</span><span class="hljs-params">(<span class="hljs-keyword">void</span> *data, <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *output, <span class="hljs-keyword">size_t</span> len, <span class="hljs-keyword">size_t</span> *olen)</span> </span>{
  <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *garbage = (<span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *) <span class="hljs-built_in">malloc</span>(len);
  *olen = len; 

  <span class="hljs-built_in">memcpy</span>(output, garbage, len);

  <span class="hljs-built_in">free</span>(garbage);
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>and then add it before call to setup DRBG</p>
<pre><code class="lang-c">mbedtls_entropy_add_source(&amp;entropy, 
      weak_entropy_source_cb, 
      <span class="hljs-literal">NULL</span>, 
      <span class="hljs-number">16</span>, 
      MBEDTLS_ENTROPY_SOURCE_STRONG); <span class="hljs-comment">// we're clearly lying</span>
</code></pre>
<p>Try to compile if that's succeeded then we move to the next step by downgrading Winsock to Winsock 1.x.</p>
<h2 id="heading-step-2-downgrade-winsock-to-winsock-1x">Step 2: Downgrade Winsock to Winsock 1.x</h2>
<p>This is a easy, we just change the code for <code>WSAStartup()</code> to:</p>
<pre><code class="lang-c">WSADATA wsa;
<span class="hljs-keyword">return</span> WSAStartup(MAKEWORD(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>), &amp;wsa);
</code></pre>
<p>And then alter the line from <code>CMakeLists.txt</code> to link to <code>wsock32</code> rather than <code>ws2_32</code>.</p>
<pre><code class="lang-cmake">if (WIN32)
  target_link_libraries(binfetch PUBLIC wsock32)
endif (WIN32)
</code></pre>
<p>And then change the include by removing <code>winsock2.h</code> and replace it with plain old' <code>winsock.h</code>.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> WIN32_LEAN_AND_MEAN</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;winsock.h&gt;</span></span>
</code></pre>
<h2 id="heading-testing">Testing</h2>
<p>Recompile and rejoice! </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1653139265834/Kd8OgjNAl.png" alt="Running TLS 1.2 HTTP client on Windows NT 3.51 on top of Intel 486" /></p>
]]></content:encoded></item><item><title><![CDATA[Secure Oldies IV: Integrating mbedTLS FOR TLS 1.2 support.]]></title><description><![CDATA[We've managed to write a simple HTTP client which will do GET request using Winsock and BSD sockets API which run on as old platform as Windows 95 to a new platform like macOS and Windows 10.
However, to access the internet nowadays in 2022, encrypti...]]></description><link>https://retrocoding.net/secure-oldies-iv-integrating-mbedtls-for-tls-12-support</link><guid isPermaLink="true">https://retrocoding.net/secure-oldies-iv-integrating-mbedtls-for-tls-12-support</guid><category><![CDATA[networking]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[socket]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Thu, 19 May 2022 22:32:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652520546912/8fvs_DAH7.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We've managed to write a simple HTTP client which will do <code>GET</code> request using Winsock and BSD sockets API which run on as old platform as Windows 95 to a new platform like macOS and Windows 10.</p>
<p>However, to access the internet nowadays in 2022, encryption and server authentication is not optional anymore. A common scheme that ubiquitous now is SSL (Secure Socket Layer) or TLS (Transport Layer Security). Here's the simplistic diagram how it maps to execution context and network abstraction context</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652592122928/gXitEA_cu.png" alt="Abstraction Layer" /></p>
<p>Here's we can see that TLS/SSL is in application layer above TCP/IP which is abstracted by BSD Sockets API. It encrypts and decrypts TCP packet.</p>
<h1 id="heading-ssl-tls-and-windows-support">SSL, TLS and Windows Support</h1>
<p>SSL has been existing since Netscape Navigator. It sits on top of TCP providing a mechanism and layer of encryption and server authentication. Windows, internally supports SSL with the SChannel API existing on Windows XP and if you tried to open modern website on Internet Explorer, it will fail.</p>
<p>This includes <code>httpbin.org</code> as well. This is because most of modern website will only support TLS 1.2 and up because older SSL implementations are all vulnerable to attack like POODLE. The oldest Windows supporting TLS 1.2 is Windows 8 which was released in 2012, 16 years after our target platform, Windows 95. </p>
<p>The good news is that the so-called <em>support</em> means that it's built-in either on the platform API or SDK. As TLS is on top of BSD Sockets API, we can swap the implementation as we please. For this we'll use a library called <a target="_blank" href="https://tls.mbed.org/">mbedTLS</a></p>
<h2 id="heading-introducing-mbedtls">Introducing mbedTLS</h2>
<p>mbedTLS is an implmentation of TLS licensed with <a target="_blank" href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0 License</a> which allows us to use it on commercial, closed source applications. This makes sense as the author of mbedTLS is ARM, which you might familiar is the company who designs the ARM processors which is used by phone and tablets.</p>
<p>What does that to do with us want to bring modern TLS to old systems, then? It turns out that ARM is ubiquitous, so it needs an implementation of TLS which doesn't make any assumption of underlying platform. It doesn't even assume that we'll be using BSD sockets API as it may or may not available for small devices. Heck, they may not even have a 'proper operating system' to start with. This makes mbedTLS code is so portable and it can be compiled on Clang and GNU-based compilers. The only caveat is it's only works for 32-bit platforms or better. Intel Pentium Pro and i486 are 32-bit, so we can use this library.</p>
<p>To download, just go to their <a target="_blank" href="https://github.com/Mbed-TLS/mbedtls/releases">Github Page</a> and download their latest release. I'm using version <code>3.1.0</code>.</p>
<h2 id="heading-integrating-mbedtls">Integrating mbedTLS</h2>
<p>Actually, there's another reason why I choose mbedTLS because it supports to be embedded directly on any <code>CMake</code> based projects. We're using <code>CMake</code> so it's perfect. Just extract the mbedtls to the project below <code>main.c</code>. In my case, the subdirector is called <code>mbedtls-3.1.0</code>. We just add that to our project like so on our <code>CMakeLists.txt</code></p>
<pre><code class="lang-cmake"># ... another cmake directives

# Add mbedtls and link to the project
add_subdirectory(mbedtls-3.1.0)

# Link mbedtls libraries
target_link_libraries(binfetch
        PUBLIC mbedtls
               mbedcrypto
               mbedx509)

# Add include directory 
target_include_directories(binfetch PUBLIC "${MBEDTLS_DIR}/include")
</code></pre>
<h2 id="heading-using-mbedtls">Using mbedTLS</h2>
<p>Before we move further we'd need to add some mbedTLS headers to our program.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"mbedtls/ssl.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"mbedtls/entropy.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"mbedtls/ctr_drbg.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"mbedtls/debug.h"</span></span>
</code></pre>
<p>And then we'd need to prepare structures to be initialised for our ssl session to happen. Add this after <code>init_socket()</code>. </p>
<pre><code class="lang-c">  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Initialising MbedTLS structures....\n"</span>);
  mbedtls_ssl_config_init(&amp;ssl_config);
  mbedtls_entropy_init(&amp;entropy);
  mbedtls_ctr_drbg_init(&amp;ctr_drbg); 
  mbedtls_ssl_init(&amp;ssl); 
  mbedtls_ssl_config_init(&amp;ssl_config);
  mbedtls_x509_crt_init(&amp;certs);
</code></pre>
<p>And just before socket cleanup, we're <code>free</code>-ing mbedTLS structures.</p>
<pre><code class="lang-c"><span class="hljs-comment">// Cleaning up TLS </span>
  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Cleaning Up mbedTLS structures...\n"</span>);
  mbedtls_x509_crt_free(&amp;certs);
  mbedtls_ssl_config_free(&amp;ssl_config);
  mbedtls_ssl_free(&amp;ssl);
  mbedtls_ctr_drbg_free(&amp;ctr_drbg);
  mbedtls_entropy_free(&amp;entropy);
</code></pre>
<h3 id="heading-configure-the-ssl-session">Configure the SSL session</h3>
<p>Configuring SSL session is a little bit involved. This is because mbedTLS tries to be as portable and configurable. </p>
<ol>
<li>We configure that we're using TCP, and we're a client app. We pass <code>MBEDTLS_SSL_IS_CLIENT</code> and <code>MBEDTLS_SSL_TRANSPORT_STREAM</code> as second and third parameters respectively to <code>mbedtls_ssl_config_defaults</code>.</li>
<li>We setup the major and minor version of the SSL. We want at least TLS 1.2. We'll be using function <code>mbedtls_ssl_conf_min_version</code> and passing <code>MBEDTLS_SSL_MAJOR_VERSION_3</code> and <code>MBEDTLS_SSL_MINOR_VERSION_3</code>. It seems odd but it's how we tell mbed to use TLS 1.2. This tuple is in accordance with <a target="_blank" href="https://www.rfc-editor.org/rfc/rfc5246.html#section-6.2.1">RFC 5246 § 6.2.1</a> or [RFC 8446 § 4.2.1] (https://www.rfc-editor.org/rfc/rfc8446.html#section-4.2.1).</li>
<li>We load the certificate on current directory, assuming the name is <code>./ca_cert.pem</code> by definining it in <code>config.h</code> and using <code>mbedtls_x509_crt_parse_file()</code> and then load the chain to the ssl session by <code>mbedtls_ssl_conf_ca_chain()</code>.</li>
<li>We set the SSL hostname to match the server identity <code>mbedtls_ssl_set_hostname()</code>.</li>
<li>We ask to verify server identity by setting <code>MBEDTLS_SSL_VERIFY_REQUIRED</code> on <code>mbedtls_ssl_conf_authmode()</code> invocation.</li>
<li>We seed the <a target="_blank" href="https://csrc.nist.gov/glossary/term/Deterministic_Random_Bit_Generator">DRBG</a> with <code>mbedtls_ctr_drgb_seed()</code> and then use it to <code>ssl_config</code> by calling <code>mbedtls_ssl_conf_rng()</code>.</li>
</ol>
<p>For utilities we'll have a small static inline function called <code>is_error</code> which will check whether the result is less than <code>-1</code>. It'll result in <code>0</code> if it's  false and <code>1</code> if it's true. I'm not using C99 extension of using <code>stdbool</code>, so we'll stick with C89 for now. </p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">int</span> <span class="hljs-title">is_error</span><span class="hljs-params">(<span class="hljs-keyword">int</span> res)</span> </span>{
  <span class="hljs-keyword">return</span> res &lt; <span class="hljs-number">0</span>;
}
</code></pre>
<p>Why using static function and not macro? Because it's more readable and the resulting machine code will be similar.</p>
<p>Also we'll create a new file called <code>config.h</code> which will have most of the definition. For now it only contains the filename of the ROOT CERTIFICATES.</p>
<pre><code class="lang-C"><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> CACERTS ./cacert.pem</span>
</code></pre>
<pre><code class="lang-c"><span class="hljs-comment">// 1</span>
res = mbedtls_ssl_config_defaults(&amp;ssl_config,
      MBEDTLS_SSL_IS_CLIENT, 
      MBEDTLS_SSL_TRANSPORT_STREAM,
      MBEDTLS_SSL_PRESET_DEFAULT);

<span class="hljs-keyword">if</span> (is_error(res)) {
    <span class="hljs-keyword">goto</span> tls_cleanup;
}
 <span class="hljs-comment">// 2</span>
 mbedtls_ssl_conf_min_version(&amp;ssl_config, 
        MBEDTLS_SSL_MAJOR_VERSION_3, 
        MBEDTLS_SSL_MINOR_VERSION_3);

<span class="hljs-comment">// 3</span>
 res = mbedtls_x509_crt_parse_file(&amp;certs, CACERTS);

  <span class="hljs-keyword">if</span> (is_error(res)) {
    <span class="hljs-keyword">goto</span> tls_cleanup;
  }

mbedtls_ssl_conf_ca_chain(&amp;ssl_config, 
      &amp;certs, <span class="hljs-number">0</span>);

<span class="hljs-comment">// 4</span>
res = mbedtls_ssl_set_hostname(&amp;ssl, httpbin);

  <span class="hljs-keyword">if</span> (is_error(res)) {
    <span class="hljs-keyword">goto</span> tls_cleanup;
  }

<span class="hljs-comment">// 5</span>

mbedtls_ssl_conf_authmode(&amp;ssl_config, MBEDTLS_SSL_VERIFY_REQUIRED);

<span class="hljs-comment">// 6 </span>

<span class="hljs-comment">// Seeding random </span>
res = mbedtls_ctr_drbg_seed(&amp;ctr_drbg, mbedtls_entropy_func, &amp;entropy, <span class="hljs-literal">NULL</span>, <span class="hljs-number">0</span>); 

<span class="hljs-keyword">if</span> (is_error(res)) {
  <span class="hljs-keyword">goto</span> tls_cleanup;
}

mbedtls_ssl_conf_rng(&amp;ssl_config, mbedtls_ctr_drbg_random, &amp;ctr_drbg);
</code></pre>
<h2 id="heading-starting-tlsssl-session-and-read-and-write-the-data">Starting TLS/SSL session and read and write the data.</h2>
<p>mbedTLS is an SSL layer on top of BSD Socket and Winsock API. This layer will takes care of session, handshake and key exchange typically happen in TLS based communication. Hussein Nasser from Backend Engineering show explained the concept thoroughly in this video. </p>
<p><em>If you curious, you can also verify what hussein's explained by debug and stepping in to mbedTLS codebase. The codebase is relatively clean and easy to digest but you'd need at least fundamental of C and Cryptography</em>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/AlE5X1NlHgg">https://youtu.be/AlE5X1NlHgg</a></div>
<h3 id="heading-step-1-setting-up-context-structure-reading-and-writing-function-beginning-handshake">Step 1: Setting Up Context structure, reading and writing function, beginning handshake.</h3>
<p>To do this using mbedTLS, we'd need to supply how to write and read from the network.  Because mbedTLS is written with embedded system in mind, it doesn't know how to read and write to the network. If you're building a device you might use BSD Sockets API or any custom protocol you have. Hence, mbedTLS expect a callback function for read and write. It's also gives an option to throw in additional context data when reading and writing. <strong>Context</strong> is anything needed to do and shared during one session of reading and writing.</p>
<p>In our case, because we'd need socket to read from and write to, we need this socket to be our context data.</p>
<pre><code class="lang-c"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">tls_context_t</span> {</span>
   SOCKET sock;
}
</code></pre>
<p>And then our simple reading and writing function. </p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">tls_send_cb</span><span class="hljs-params">(<span class="hljs-keyword">void</span> *ssl_ctx, <span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *buf, <span class="hljs-keyword">size_t</span> len)</span> </span>{
  <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">tls_context_t</span> *<span class="hljs-title">ctx</span> = (<span class="hljs-title">struct</span> <span class="hljs-title">ssl_context_t</span> *)<span class="hljs-title">ssl_ctx</span>;</span>

  <span class="hljs-keyword">return</span> send(ctx-&gt;sock, buf, len, <span class="hljs-number">0</span>);
}

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">tls_recv_cb</span><span class="hljs-params">(<span class="hljs-keyword">void</span> *ssl_ctx, <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *buf, <span class="hljs-keyword">size_t</span> len)</span> </span>{
  <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">tls_context_t</span> *<span class="hljs-title">ctx</span> = (<span class="hljs-title">struct</span> <span class="hljs-title">ssl_context_t</span> *)<span class="hljs-title">ssl_ctx</span>;</span>

  <span class="hljs-keyword">return</span> recv(ctx-&gt;sock, (<span class="hljs-keyword">void</span>*) buf, len, <span class="hljs-number">0</span>);
}
</code></pre>
<p>And then setting up in the <code>main.c</code> for reading and writing after we create a socket and connect to the server.</p>
<pre><code class="lang-c"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">tls_context_t</span> <span class="hljs-title">ctx</span>;</span>

res = mbedtls_ssl_setup(&amp;ssl, &amp;ssl_config);

<span class="hljs-keyword">if</span> (is_error(res)) {
  <span class="hljs-keyword">goto</span> tls_cleanup;
}

ctx.sock = client;

<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Setting up BIO and doing handshake..\n"</span>);

mbedtls_ssl_set_bio(&amp;ssl, &amp;ctx, tls_send_cb, tls_recv_cb, <span class="hljs-literal">NULL</span>);
</code></pre>
<p>And then we start the handshake</p>
<pre><code class="lang-c">res = mbedtls_ssl_handshake(&amp;ssl);

<span class="hljs-keyword">if</span> (is_error(res)) {
  <span class="hljs-keyword">goto</span> tls_cleanup;
}
</code></pre>
<p>This will start the TLS session between client and server within the context of socket within <code>ctx</code> structure.</p>
<h3 id="heading-step-2-writing-and-reading-tls-packet">Step 2: Writing and Reading TLS packet</h3>
<p>In previous article we write directly. Here we'd need to use <code>mbedtls_ssl_write</code> and <code>mbedtls_ssl_read</code> to write and read within an TLS session. To do that, we first remove any references to <code>send</code> and <code>recv</code> because we're not dealing with plain socket anymore.</p>
<p>MbedTLS is very peculiar in how it read and write. It handles read and write as well as certificate renegotiation. So, there's a possibility that the read and write fails because of renegotiation. It doesn't mean total failure tho, because after renegotiation, you'll get your next byte ready.</p>
<h4 id="heading-writing-sending-request">Writing / Sending Request</h4>
<p>Writing is done using <code>mbedtls_ssl_write()</code> function in an infinite loop. The loop is needed because we'd need to check whether the data is ready on first try or you'd need second try due to renegotiation. Some people prefers <code>for(;;)</code> or <code>do..while(1);</code> construct. I'll be using the second construct. </p>
<p>We'll check for this condition to control the loop and break.</p>
<ol>
<li>If the return value is more than <code>0</code>, it means the write is successful, and we <code>break</code> from the loop.</li>
<li>If the return value is <code>MBEDTLS_ERR_SSL_WANT_READ</code> OR <code>MBEDTLS_ERR_SSL_WANT_WRITE</code> it means that the first call is renegotiation, we <code>continue</code> the loop to write more data.</li>
<li>If the return value is less than zero (aka <code>is_error()</code> is true), then we go to error handler.</li>
</ol>
<pre><code class="lang-c"><span class="hljs-keyword">do</span> {
    res = mbedtls_ssl_write(&amp;ssl, 
                  (<span class="hljs-keyword">const</span> <span class="hljs-keyword">unsigned</span> <span class="hljs-keyword">char</span> *) request, 
                  <span class="hljs-keyword">sizeof</span>(request) - <span class="hljs-number">1</span>); 

    <span class="hljs-comment">// write success</span>
    <span class="hljs-keyword">if</span> (res &gt; <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">break</span>;
    }

    <span class="hljs-comment">// renegotiation</span>
    <span class="hljs-keyword">if</span> (res == MBEDTLS_ERR_SSL_WANT_WRITE || res == MBEDTLS_ERR_SSL_WANT_READ) {
      <span class="hljs-keyword">continue</span>;
    }

    <span class="hljs-comment">// error</span>
    <span class="hljs-keyword">if</span> (is_error(res)) {
      <span class="hljs-built_in">printf</span>(<span class="hljs-string">"TLS Writing error! %d\n\n"</span>, res);
      <span class="hljs-keyword">goto</span> error;
    }
  } <span class="hljs-keyword">while</span>(<span class="hljs-number">1</span>);
</code></pre>
<h4 id="heading-reading-getting-response">Reading / Getting Response</h4>
<p>After sending the HTTP request above, we'll read from the socket. There's a little bit more code for reading, because we have MTU. Typical MTU for packet is 1500 byte. But we'll reduce that to half of it: <code>576</code> to accommodate TLS overhead. This is the byte of minimum IPV4 minimum packet size according to IETF RFC 791. So we use this number to be on the safe side.</p>
<blockquote>
<p>RFC 791: Every internet destination must be able to receive a datagram of 576 octets either in one piece or in fragments to be reassembled.</p>
</blockquote>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MTU 576</span>
</code></pre>
<p>To receive we'll use <code>mbedtls_ssl_read()</code> function inside an infinite loop too. The structure is the same with how we write packet, but we have one more condition <code>MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY</code> which means that we're notified that our peer (server) closes the socket gracefully. So the condition of exiting and continuing the loop is the same as writing with two more condition</p>
<ol>
<li>When the error is <code>MBEDTLS_ERR_SSL_PEER_NOTIFY</code>.</li>
<li>When the buffer is overflowing to avoid segmentation fault.</li>
<li>When the result is zero which means that the socket is closed.</li>
</ol>
<pre><code class="lang-c">i = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">do</span> {
    res = mbedtls_ssl_read(&amp;ssl, buf, MTU);

    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Received %d bytes\n"</span>, res);

    <span class="hljs-keyword">if</span> (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE ) {
      <span class="hljs-keyword">continue</span>;
    }

    <span class="hljs-keyword">if</span> (res == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
      <span class="hljs-keyword">break</span>;
    }

    <span class="hljs-keyword">if</span> (is_error(res)) {
      <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Read error... -0x%X\n"</span>, res);
      <span class="hljs-keyword">goto</span> tls_cleanup;
    }

    <span class="hljs-keyword">if</span> (i + res &gt; BUF_MAX_SIZE) {
      <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Buffer overflowing..  : %lu\n"</span>, i + res);
      <span class="hljs-keyword">break</span>;
    }

    <span class="hljs-keyword">if</span> (res == <span class="hljs-number">0</span>) {
      <span class="hljs-built_in">printf</span>(<span class="hljs-string">"EOF from server \n"</span>);
      <span class="hljs-keyword">break</span>; 
    }

    <span class="hljs-built_in">memcpy</span>(response + i, buf, res);
    i += res;
  } <span class="hljs-keyword">while</span> (<span class="hljs-number">1</span>);
</code></pre>
<p>And that's it! We can recompile and test our executable.</p>
<h2 id="heading-test-run">Test Run</h2>
<p>We're finished creating a simple TLS 1.2 HTTP client calling <code>httpbin.org</code> on their HTTPS port (443). So let's test.</p>
<h3 id="heading-testing-on-modern-windows-macos-or-linux">Testing on modern Windows, macOS, or Linux</h3>
<p>Let's run our binary built by MinGW in Windows 10 x64, and it runs well.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652994389309/8XC_Nr7Xl.png" alt="Windows 10 mbedTLS testing" /></p>
<p>Testing using clang and GCC on macOS and Linux terminal should yield similar result.</p>
<h3 id="heading-testing-on-32-bit-older-windows">Testing on 32-bit older Windows</h3>
<p>Bet we're not here to build for modern system, we want to run it on old system right? So, let's get back to our 32-bit Windows. We start with Windows XP. Unfortunately, we'll be faced by this error:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652994728579/5MnzqPULT.png" alt="vsnprintf_s error" /></p>
<p>This is because MinGW and mbedTLS assumes that it's using the updated version of <code>msvcrt.dll</code> which has <code>vsnprintf_s</code> defined and it's unavailable on built-in <code>mscvrt.dll</code> in Windows XP. This leads to our first patch to mbedTLS. Search a file called <code>library/platform.c</code> and find <code>vsnprintf_s</code>. You'll find a line like this.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> defined(_TRUNCATE)</span>
    ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg );
<span class="hljs-meta">#<span class="hljs-meta-keyword">else</span></span>
    ret = vsnprintf( s, n, fmt, arg );
</code></pre>
<p>Add one more condition to the first preprocessor</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> defined(_TRUNCATE) &amp;&amp; !defined(__MINGW32__)</span>
    ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg );
<span class="hljs-meta">#<span class="hljs-meta-keyword">else</span></span>
    ret = vsnprintf( s, n, fmt, arg );
</code></pre>
<p>This will make mingw compiles using <code>vsnprintf</code> instead. Recompile this and then compile using i686 MingW toolchain. It'll be able to be run on any machine running Pentium Pro and above from Windows 95. Here's the collage of my testing both using VMWare and 86Box emulator.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652996839037/NKOP7cNrd.jpg" alt="TLS 1.2 HTTP client running on Windows 95, Windows NT 4.0, Windows 2000, and Windows XP" /></p>
<h3 id="heading-patching-mbedtls-for-openwatcom-in-i486">Patching mbedTLS for OpenWatcom in i486</h3>
<p>But there's one question left: how about our target machine: <strong>Intel 486</strong>. If we run our executable, built directly in an intel 486 machine, there's a problem similar to what we face before. It contains invalid instruction:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652997149341/2qeKCSmz2.png" alt="Invalid Instruciton on i486" /></p>
<p>We see the bytes at <code>CS:EIP</code> is <code>0f 49 45 94</code> which is, again the opcode for <code>cmovns -0x6c(%ebp), %eax</code> which is a conditional mov if the sign flag is off. It will move a 32-bit value 108 byte from base pointer register <code>EBP</code> to <code>EAX</code>. This is most likely a startup code because it crashes before anything starts.</p>
<p>We'd need to use openwatcom to build mbedTLS and our program to be able to run on 486. The problem is if we just run <code>cmake</code> and compile, OpenWatcom will throw a bunch of syntax errors because OpenWatcom is not C99 compliant compilers.</p>
<p>I have created a patch that will help us compile mbedTLS for OpenWatcom. Which can be downloaded from <a target="_blank" href="https://gist.githubusercontent.com/lynxluna/bbc54ca894d57b81b8e2ebbc37fcceb7/raw/953befa3e1fb9118bba0a81674922b01fb2a6d18/watcom_mbed.patch">my github gist</a>.</p>
<p>Apply the patch by entering the directory of <code>mbedtls-3.1.0</code> within your project.</p>
<pre><code class="lang-sh"><span class="hljs-built_in">cd</span> mbedtls-3.1.0

patch -p1 &lt; /location/to/watcom_mbed.patch
</code></pre>
<p>This will patch the mbedtls source code by fixing its syntax as well some adaptation for watcom, e.g. not using <code>gmtime_s</code> for verification.</p>
<p>Run the <code>cmake</code> script for watcom</p>
<pre><code>cmake \
<span class="hljs-operator">-</span>DCMAKE_C_FLAGS<span class="hljs-operator">=</span><span class="hljs-string">"-4r  -d2 -oaxt -fo=.obj -bt=nt"</span> \
<span class="hljs-operator">-</span>DCMAKE_SYSTEM_NAME<span class="hljs-operator">=</span>Windows \
<span class="hljs-operator">-</span>DCMAKE_BUILD_TYPE<span class="hljs-operator">=</span>Release \
<span class="hljs-operator">-</span>DENABLE_TESTING<span class="hljs-operator">=</span>Off \
<span class="hljs-operator">-</span>DENABLE_PROGRAMS<span class="hljs-operator">=</span>Off \
<span class="hljs-operator">-</span>G <span class="hljs-string">"Watcom WMake"</span> ../..

wmake
</code></pre><p>This will build mbedtls and our program to use Watcom's register call on 486. This will create a single executable. Let's run it on Windows 95.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652998883514/4TaEjXwVE.png" alt="TLS 1.2 running on Windows 95 in Intel 486 DX2" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>This article becomes rather mbedTLS tutorial because the closest platform similar to an old computer is embedded platforms. I just surprised how mbedTLS code is so clean and easy to patch and make sense even if on a platform that's totally unsupported (OpenWatcom, Windows 95, and Intel 486). The complete code with patched mbedTLS is on my repository.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/retrocodingnet/otls">https://github.com/retrocodingnet/otls</a></div>
<p>Thankfully, we're also using CMake which makes our build system portable too. The only limitation mbedTLS officially says is that it needs 32-bit platform to work with. I wonder if we're able to run a protected-mode DOS extender HTTPS TLS 1.2 client 😉.</p>
]]></content:encoded></item><item><title><![CDATA[Secure Oldies III: Compiling for Windows 9x Using OpenWatcom]]></title><description><![CDATA[We're able to compile our executable an run it on Windows NT 5 based operating systems (Windows 2000 and Up) as well as Unix (in this case macOS and Linux). That's cool and dandy. But can we push our app to be even older operating system. I'm talking...]]></description><link>https://retrocoding.net/secure-oldies-iii-compiling-for-windows-9x-using-openwatcom</link><guid isPermaLink="true">https://retrocoding.net/secure-oldies-iii-compiling-for-windows-9x-using-openwatcom</guid><category><![CDATA[networking]]></category><category><![CDATA[Windows]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Fri, 13 May 2022 14:22:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652411078503/S0NyGydRN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We're able to compile our executable an run it on Windows NT 5 based operating systems (Windows 2000 and Up) as well as Unix (in this case macOS and Linux). That's cool and dandy. But can we push our app to be <strong>even older</strong> operating system. I'm talking about Windows 95.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652411845059/8ltChmEzW.jpeg" alt="Windows 95 Flag" /></p>
<h1 id="heading-running-it-on-windows-95">Running it on Windows 95</h1>
<p>For that to happen we'd need an emulator. I choose <a target="_blank" href="https://86box.net/">86box</a> as this is the most usable x86 emulator. I created 2 GB of hard drive and install Windows 95 OSR 2.5 (with Winsock 2 update) with Intel i486 DX2 66 Mhz with whopping 8 MB of RAM as the machine. For your information this processor was launched in 1989, a frickin <strong>33 Years Ago</strong> on a machine with this look:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652412411216/-bCT7aNCt.jpeg" alt="486 DX2 Computer" /></p>
<p><em>Note: Winsock 2 Update is needed to be able to run our program</em></p>
<p>I transferred our executable there and run on it and bummer, I got this error:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652412438243/7simdDjGt.png" alt="Invalid Instructions" /></p>
<h2 id="heading-invalid-instructions-what">Invalid instructions, what?</h2>
<p>What does it mean? Thankfully, Windows gave us the hint on <strong>bytes at CS:EIP</strong> part which is.</p>
<pre><code><span class="hljs-attribute">0f</span> <span class="hljs-number">49</span> <span class="hljs-number">45</span> <span class="hljs-number">94</span> <span class="hljs-number">89</span> <span class="hljs-number">35</span> <span class="hljs-number">20</span> <span class="hljs-number">90</span> <span class="hljs-number">00</span> c<span class="hljs-number">7</span> <span class="hljs-number">04</span> <span class="hljs-number">86</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span> <span class="hljs-number">00</span>
</code></pre><p>After using a disassembler like <a target="_blank" href="https://onlinedisassembler.com/odaweb/">ODA Web</a>, we know that the first few bytes <code>0f 49 45 94</code> is an opcode for <code>cmovns -0x6c(%ebp), %eax</code>. The problem is <code>CMOVNS</code> is only available for <strong>Pentium Pro</strong> while our computer is an old i486.</p>
<h2 id="heading-lets-just-upgrade">Let's just upgrade</h2>
<p>To make this easier to work with, let's just upgrade our board to Pentium Pro with 32 MB Memory and run the program.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652435823042/7Zw2c3k8a.png" alt="Jepretan Layar 2022-05-13 pukul 15.53.49.png" /></p>
<p>And then, let's run the same executable on this Pentium Pro.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652436273897/_l4_YA4PV.gif" alt="Windows 95 on Pentium Pro" /></p>
<p>Nice! We're able to run our HTTP client on Windows 95 with Pentium Pro. <strong>However</strong> we cannot run that on older processors because modern GNU GCC will insist to build the binary for <code>i686</code> architecture which is a pentium pro architecture. </p>
<h1 id="heading-openwatcom-makes-our-software-even-more-backward-compatible">OpenWatcom makes our software even more backward compatible.</h1>
<p>To be able to run on i486 architecture, which is our aim. We'd need a compiler which is able to produce strictly 32-bit code i486 architecture. I used Windows 95 as it's the operating systems which can still run on i386 machine. Surely, there's a way to do that.</p>
<p>The answer is OpenWatcom. A classic compiler, known for its performance when they are closed source and used by Quake to produce their game. Let's see a quote from their wiki retrieved in 2011 about this compiler:</p>
<blockquote>
<p>Around 1993-1996, nearly all DOS games were developed with Watcom C, including famous titles such as DOOM, Descent or Duke Nukem 3D. </p>
</blockquote>
<p>So, we'll use this compiler to produce a working executable for Windows 95 on i486. You can download it from <a target="_blank" href="https://openwatcom.org">their site</a>. They alse have a version which runs on Linux. If you're using macOS, I've created a docker image based on Red Hat's <code>ubi8</code> image. For Windows, just install their installer and run <code>owsetenv.bat</code>.</p>
<p>For docker, you can run and mount your source code on docker volume. For example, all of my projects are in <code>~/Projects</code>, therefore I mount it to <code>/projects</code>.</p>
<pre><code>docker <span class="hljs-operator">-</span>v $(pwd):<span class="hljs-operator">/</span>projects <span class="hljs-operator">-</span>it ykode<span class="hljs-operator">/</span>openwatcom:<span class="hljs-number">1.9</span><span class="hljs-operator">-</span>ubi
</code></pre><p>After that we're setting up the build environment.</p>
<pre><code>export WATCOM<span class="hljs-operator">=</span><span class="hljs-operator">/</span>usr<span class="hljs-operator">/</span>local<span class="hljs-operator">/</span>watcom

source <span class="hljs-operator">/</span>usr<span class="hljs-operator">/</span>local<span class="hljs-operator">/</span>watcom<span class="hljs-operator">/</span>owsetenv.sh
</code></pre><p>And then we're generating the <code>Makefile</code> for Watcom's <code>wmake</code> tool.</p>
<pre><code>cd build<span class="hljs-operator">/</span>watcom

cmake \
  <span class="hljs-operator">-</span>DCMAKE_C_FLAGS<span class="hljs-operator">=</span><span class="hljs-string">"-bt=nt -4r -oaxt -d2"</span> \
  <span class="hljs-operator">-</span>DCMAKE_SYSTEM_NAME<span class="hljs-operator">=</span>Windows \ 
  <span class="hljs-operator">-</span>G <span class="hljs-string">"Watcom WMake"</span> ../..
</code></pre><p>Which means:</p>
<ul>
<li><p><code>CMAKE_C_FLAGS</code> will set the compiler flags. The meaning of each flags is:</p>
<ul>
<li><code>-bt=nt</code> we're compiling for Win32 environment (NT/Win9x).</li>
<li><code>-4r</code> we're targeting 486 architecture with Watcom's Register calling convention.</li>
<li><p><code>-oaxt</code> this is a compiler options which means:</p>
<ul>
<li><code>a</code> relax <a target="_blank" href="https://cvw.cac.cornell.edu/vector/coding_aliasing">aliasing</a> constraint </li>
<li><code>x</code> similar to <code>-obmiler -s</code> which means : <code>b</code> enable branch prediction, <code>m</code> inline math functions, <code>i</code>expand intrinsict functiion, <code>l</code> enable loop optimisation, <code>e</code> expand user function inline,<code>r</code>rearrange instruction for optimal pipeline usage. and <code>-s</code> means that remove stack overflow checking.</li>
<li><code>t</code> favour speed (executing time) over code size.</li>
<li><code>d2</code> means generate debugging information.</li>
</ul>
</li>
</ul>
</li>
<li><code>CMAKE_SYSTEM_NAME=Windows</code> we're targeting Windows (instead of DOS).</li>
<li><code>-G "Watcom WMake"</code> generate a Makefile applicable for Watcom <code>wmake</code> tool.</li>
</ul>
<p>And then we run <code>wmake</code></p>
<pre><code>wmake
</code></pre><p>You might run on the wall of text of compilation errors like I did.</p>
<pre><code>Open Watcom Make Version <span class="hljs-number">1.9</span>
Portions Copyright (c) <span class="hljs-number">1988</span><span class="hljs-number">-2002</span> Sybase, Inc. All Rights Reserved.
Source code <span class="hljs-keyword">is</span> available under the Sybase Open Watcom Public License.
See http:<span class="hljs-comment">//www.openwatcom.org/ for details.</span>
Scanning dependencies of target binfetch
[ <span class="hljs-number">50</span><span class="hljs-operator">%</span>] Building C object CMakeFiles<span class="hljs-operator">/</span>binfetch.dir/main.c.obj
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>platform.h(<span class="hljs-number">20</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1091: <span class="hljs-string">"Unsupported platform"</span>
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>platform.h(<span class="hljs-number">46</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1011: Symbol <span class="hljs-string">'errno'</span> has not been declared
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">23</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1011: Symbol <span class="hljs-string">'SOCKET'</span> has not been declared
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">23</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1009: Expecting <span class="hljs-string">';'</span> but found <span class="hljs-string">'client'</span>
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">23</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1063: Missing operand
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">23</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1011: Symbol <span class="hljs-string">'INVALID_SOCKET'</span> has not been declared
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">24</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1058: Cannot use typedef <span class="hljs-string">'size_t'</span> <span class="hljs-keyword">as</span> a variable
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">24</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1009: Expecting <span class="hljs-string">';'</span> but found <span class="hljs-string">'i'</span>
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">24</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1063: Missing operand
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">26</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1058: Cannot use typedef <span class="hljs-string">'uint8_t'</span> <span class="hljs-keyword">as</span> a variable
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">26</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1009: Expecting <span class="hljs-string">';'</span> but found <span class="hljs-string">'buf'</span>
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">26</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1063: Missing operand
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">26</span>): Warning<span class="hljs-operator">!</span> W111: Meaningless use of an expression
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">26</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1009: Expecting <span class="hljs-string">';'</span> but found <span class="hljs-string">']'</span>
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">27</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1077: Missing <span class="hljs-string">'}'</span>
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">11</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1044: Variable <span class="hljs-string">'addr_item'</span> has incomplete <span class="hljs-keyword">type</span>
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">12</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1044: Variable <span class="hljs-string">'addr'</span> has incomplete <span class="hljs-keyword">type</span>
<span class="hljs-operator">/</span>projects<span class="hljs-operator">/</span>retrocoding.net/programs<span class="hljs-operator">/</span>old_tls<span class="hljs-operator">/</span>main.c(<span class="hljs-number">27</span>): Warning<span class="hljs-operator">!</span> W107: Missing <span class="hljs-keyword">return</span> value <span class="hljs-keyword">for</span> <span class="hljs-function"><span class="hljs-keyword">function</span> '<span class="hljs-title">main</span>'
/<span class="hljs-title">projects</span>/<span class="hljs-title">retrocoding</span>.<span class="hljs-title">net</span>/<span class="hljs-title">programs</span>/<span class="hljs-title">old_tls</span>/<span class="hljs-title">main</span>.<span class="hljs-title">c</span>(<span class="hljs-params"><span class="hljs-number">29</span></span>): <span class="hljs-title"><span class="hljs-built_in">Error</span></span>! <span class="hljs-title">E1009</span>: <span class="hljs-title">Expecting</span> ')' <span class="hljs-title">but</span> <span class="hljs-title">found</span> '<span class="hljs-title">Starting</span> <span class="hljs-title">Up</span>...\<span class="hljs-title">n</span>'
/<span class="hljs-title">projects</span>/<span class="hljs-title">retrocoding</span>.<span class="hljs-title">net</span>/<span class="hljs-title">programs</span>/<span class="hljs-title">old_tls</span>/<span class="hljs-title">main</span>.<span class="hljs-title">c</span>(<span class="hljs-params"><span class="hljs-number">29</span></span>): <span class="hljs-title"><span class="hljs-built_in">Error</span></span>! <span class="hljs-title">E1026</span>: <span class="hljs-title">Invalid</span> <span class="hljs-title">declarator</span>
/<span class="hljs-title">projects</span>/<span class="hljs-title">retrocoding</span>.<span class="hljs-title">net</span>/<span class="hljs-title">programs</span>/<span class="hljs-title">old_tls</span>/<span class="hljs-title">main</span>.<span class="hljs-title">c</span>(<span class="hljs-params"><span class="hljs-number">29</span></span>): <span class="hljs-title"><span class="hljs-built_in">Error</span></span>! <span class="hljs-title">E1009</span>: <span class="hljs-title">Expecting</span> ',' <span class="hljs-title">but</span> <span class="hljs-title">found</span> '<span class="hljs-title">Starting</span> <span class="hljs-title">Up</span>...\<span class="hljs-title">n</span>'
/<span class="hljs-title">projects</span>/<span class="hljs-title">retrocoding</span>.<span class="hljs-title">net</span>/<span class="hljs-title">programs</span>/<span class="hljs-title">old_tls</span>/<span class="hljs-title">main</span>.<span class="hljs-title">c</span>(<span class="hljs-params"><span class="hljs-number">29</span></span>): <span class="hljs-title"><span class="hljs-built_in">Error</span></span>! <span class="hljs-title">E1026</span>: <span class="hljs-title">Invalid</span> <span class="hljs-title">declarator</span>
/<span class="hljs-title">projects</span>/<span class="hljs-title">retrocoding</span>.<span class="hljs-title">net</span>/<span class="hljs-title">programs</span>/<span class="hljs-title">old_tls</span>/<span class="hljs-title">main</span>.<span class="hljs-title">c</span>(<span class="hljs-params"><span class="hljs-number">29</span></span>): <span class="hljs-title"><span class="hljs-built_in">Error</span></span>! <span class="hljs-title">E1147</span>: <span class="hljs-title">Too</span> <span class="hljs-title">many</span> <span class="hljs-title">errors</span>: <span class="hljs-title">compilation</span> <span class="hljs-title">aborted</span>
<span class="hljs-title"><span class="hljs-built_in">Error</span></span>: <span class="hljs-title">Compiler</span> <span class="hljs-title">returned</span> <span class="hljs-title">a</span> <span class="hljs-title">bad</span> <span class="hljs-title">status</span> <span class="hljs-title">compiling</span> '/<span class="hljs-title">projects</span>/<span class="hljs-title">retrocoding</span>.<span class="hljs-title">net</span>/<span class="hljs-title">programs</span>/<span class="hljs-title">old_tls</span>/<span class="hljs-title">main</span>.<span class="hljs-title">c</span>'
<span class="hljs-title"><span class="hljs-built_in">Error</span></span>(<span class="hljs-params">E42</span>): <span class="hljs-title">Last</span> <span class="hljs-title">command</span> <span class="hljs-title">making</span> (<span class="hljs-params">CMakeFiles/binfetch.dir/main.c.obj</span>) <span class="hljs-title">returned</span> <span class="hljs-title">a</span> <span class="hljs-title">bad</span> <span class="hljs-title">status</span>
<span class="hljs-title"><span class="hljs-built_in">Error</span></span>(<span class="hljs-params">E02</span>): <span class="hljs-title">Make</span> <span class="hljs-title">execution</span> <span class="hljs-title">terminated</span>
<span class="hljs-title"><span class="hljs-built_in">Error</span></span>(<span class="hljs-params">E42</span>): <span class="hljs-title">Last</span> <span class="hljs-title">command</span> <span class="hljs-title">making</span> (<span class="hljs-params">CMakeFiles/binfetch.dir/all</span>) <span class="hljs-title">returned</span> <span class="hljs-title">a</span> <span class="hljs-title">bad</span> <span class="hljs-title">status</span>
<span class="hljs-title"><span class="hljs-built_in">Error</span></span>(<span class="hljs-params">E02</span>): <span class="hljs-title">Make</span> <span class="hljs-title">execution</span> <span class="hljs-title">terminated</span>
<span class="hljs-title"><span class="hljs-built_in">Error</span></span>(<span class="hljs-params">E42</span>): <span class="hljs-title">Last</span> <span class="hljs-title">command</span> <span class="hljs-title">making</span> (<span class="hljs-params">all</span>) <span class="hljs-title">returned</span> <span class="hljs-title">a</span> <span class="hljs-title">bad</span> <span class="hljs-title">status</span>
<span class="hljs-title"><span class="hljs-built_in">Error</span></span>(<span class="hljs-params">E02</span>): <span class="hljs-title">Make</span> <span class="hljs-title">execution</span> <span class="hljs-title">terminated</span></span>
</code></pre><p>This is because we're using different compiler which define different predefined macros. OpenWatcom doesn't define <code>WIN32</code>, it defines <code>__NT__</code>. So we'd need to add this line on the top.</p>
<pre><code><span class="hljs-selector-id">#if</span> <span class="hljs-selector-tag">defined</span>(__NT__) <span class="hljs-selector-tag">&amp;</span><span class="hljs-selector-tag">&amp;</span> !<span class="hljs-selector-tag">defined</span>(WIN32)
<span class="hljs-selector-id">#define</span> <span class="hljs-selector-tag">WIN32</span> <span class="hljs-selector-tag">1</span>
<span class="hljs-selector-id">#endif</span>
</code></pre><p>If we run <code>wmake</code> again, there will be error similar to this:</p>
<pre><code>main.c(<span class="hljs-number">32</span>): <span class="hljs-built_in">Error</span><span class="hljs-operator">!</span> E1077: Missing <span class="hljs-string">'}'</span>
</code></pre><p>The error is not really clear. This error is caused by OpenWatcom not supporting variable definition in the middle of statement because it's the feature of C99 which OpenWatcom not really support.</p>
<pre><code><span class="hljs-comment">// line 32</span>
<span class="hljs-keyword">int</span> res <span class="hljs-operator">=</span> init_socket();
</code></pre><p>To make the compiler happy we'd need to move the definition of <code>res</code> to the top. And for completeness, before <code>return</code>-ing we'll call <code>getchar();</code> so it will stop execution and waiting for your input.</p>
<pre><code><span class="hljs-comment">// just after main()</span>
<span class="hljs-keyword">int</span> res <span class="hljs-operator">=</span> <span class="hljs-number">-1</span>;

<span class="hljs-comment">//.... some code</span>

<span class="hljs-comment">// change in line 32</span>
res <span class="hljs-operator">=</span> init_socket();

<span class="hljs-comment">// just before return</span>
getchar();

<span class="hljs-keyword">return</span> res
</code></pre><p>Once you change it you can compile using <code>wmake</code> again and you'll get the <code>binfetch.exe</code> which will be compatible with Windows 95 on 486 processor.</p>
<pre><code><span class="hljs-operator">&gt;</span> wmake

Open Watcom Make Version <span class="hljs-number">1.9</span>
Portions Copyright (c) <span class="hljs-number">1988</span><span class="hljs-number">-2002</span> Sybase, Inc. All Rights Reserved.
Source code <span class="hljs-keyword">is</span> available under the Sybase Open Watcom Public License.
See http:<span class="hljs-comment">//www.openwatcom.org/ for details.</span>
Scanning dependencies of target binfetch
[ <span class="hljs-number">50</span><span class="hljs-operator">%</span>] Building C object CMakeFiles<span class="hljs-operator">/</span>binfetch.dir/main.c.obj
[<span class="hljs-number">100</span><span class="hljs-operator">%</span>] Linking C executable binfetch.exe
[<span class="hljs-number">100</span><span class="hljs-operator">%</span>] Built target binfetch
</code></pre><p>Then we can copy the resulting <code>binfetch.exe</code> to the emulator. And run it by double clicking it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652449716451/saidb59TH.gif" alt="Windows 95 with Watcom" /></p>
<p>As you can see in this side-by-side comparison of dependencies. It looks like MinGW has <strong>hard dependency</strong> on <code>MSVCRT.DLL</code> which maybe in turn calls the invalid instructions. OpenWatcom has its own CRT (C-Runtime) in which it will statically link it with the executable. And with <code>-4r</code> flag it won't produce anything above 486. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652449863164/U-a0zFKjH.png" alt="Side by Side dependency comparison" /></p>
<p>If we try the binary back on Windows 10 on 64-bits x86_64. It'll still run as it is.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652451576024/vp3fFuNZb.gif" alt="Windows Amazing Compatibility" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>We're able to build a decent plain-text HTTP client which run on Windows 10 64-bit to Windows 95 running on i486. It shows that the amazing compatibility Microsoft has creatid for Win32 API. The executable runs smoothly from an OS from 30+ years ago to recent OS. </p>
<p>In future installment, we'll integrate mbedtls. First using MinGW on Pentium Pro, and then we'll try to downgrade it to 486 like we do in this article.</p>
]]></content:encoded></item><item><title><![CDATA[Secure Oldies II: Refactoring and Make it Compile on macOS and Linux.]]></title><description><![CDATA[This second article is an continuation of my first article about building a simple HTTP client which runs on Windows 2000 onwards. 
Before going backward to the like of Windows 9x, Me, and NT 4.0 we're going lateral first. We'd try to make our code w...]]></description><link>https://retrocoding.net/secure-oldies-ii-refactoring-and-make-it-compile-on-macos-and-linux</link><guid isPermaLink="true">https://retrocoding.net/secure-oldies-ii-refactoring-and-make-it-compile-on-macos-and-linux</guid><category><![CDATA[networking]]></category><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Thu, 12 May 2022 01:05:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652278413234/Mp4eWHMje.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This second article is an continuation of my first article about building a simple HTTP client which runs on Windows 2000 onwards. </p>
<p>Before going <em>backward</em> to the like of Windows 9x, Me, and NT 4.0 we're going lateral first. We'd try to make our code works on latest MacOS and Linux.</p>
<h1 id="heading-the-tale-of-portability">The Tale of Portability</h1>
<p>A <em>portable code</em> is a code that can be compiled and run on many different platforms. For now, our code only runs on Windows only. Specifically Windows NT 5.0 onwards. As I've said on my first article on this series, Sockets API is everywhere including macOS and Linux. So let's make it happen.</p>
<p>Windows implementations of Winsock is largely based on BSD socket. However, there are some difference between it and BSD socket usually used in Unix or Unix-like operating systems like Linux and macOS.</p>
<ol>
<li>The most visible is that the existence of <code>WSAStartup()</code> and <code>WSACleanup()</code> function which is mandatory on Windows.</li>
<li>Windows uses <code>closesocket()</code> to close a socket rather than typical <code>close()</code> function available on POSIX compatible operating systems.</li>
<li><code>SOCKET</code> on Windows is not file descriptor, it's private data structure specific to Windows and must be used by WinSock functions only and is not interchangeable with file descriptors with <code>int</code> data type.</li>
<li><code>WSAGetLastError()</code> is used to get last error on Winsock code rather than <code>errno</code> typical in Unix systems.</li>
</ol>
<p>Because of those differences, we'd need to isolate platform specific codes.</p>
<h2 id="heading-isolating-platform-specific-codes">Isolating Platform specific codes.</h2>
<p>First of all we'd need to refactor out the header inclusion between Windows and Unix Headers. For that I'd create a file with <code>#ifdef</code> for each platform. I'll name it <code>platform.h</code>. The contents of this header is only platform specific header inclusion.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> OTLS_PLATFORM_H</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> OTLS_PLATFORM_H 1 </span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> defined (WIN32)</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> WIN32_LEAN_AND_MEAN <span class="hljs-comment">// (1)</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;winsock2.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;ws2tcpip.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">elif</span> defined(__linux__) || defined (__unix__) || defined (__APPLE__) </span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> closesocket close <span class="hljs-comment">// (2)</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SOCKET int</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> INVALID_SOCKET -1</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SOCKET_ERROR -1</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;errno.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;netdb.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;netinet/in.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;arpa/inet.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;unistd.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">else</span> </span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">error</span> <span class="hljs-meta-string">"Unsupported platform"</span> </span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>

<span class="hljs-comment">// .. more code here ..</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
</code></pre>
<p>We add needed headers and add <code>#ifdef</code> for WIN32 :</p>
<ol>
<li>This part will be compiled if we're targeting Windows</li>
<li>This part will be compiled if we're targeting Unix/Linux/macOS<ul>
<li>We redefine <code>SOCKET</code> to <code>int</code> because in Unix, socket is file descriptor.</li>
<li><code>INVALID_SOCKET</code> and <code>SOCKET_ERROR</code> will be <code>-1</code> as this is  the value on POSIX API for failure.</li>
<li><code>&lt;errno.h&gt;</code> provides <code>errno</code> variable which similar to <code>WSAGetLastError()</code>.</li>
<li><code>&lt;netdb.h&gt;</code> provides <code>struct in_addr</code> and function <code>gethostbyname()</code>.</li>
<li><code>&lt;netinet/in.h&gt;</code> provides <code>struct sockaddr_in</code> and constants for internet protocol families.</li>
<li><code>&lt;arpa/inet.h&gt;</code> provides <code>inet_ntoa</code> function which we're using to convert an address to human-readable address.</li>
<li><code>&lt;unistd.h&gt;</code> provides <code>close()</code> function.</li>
</ul>
</li>
</ol>
<p>Also we're defining startup, cleanup and error code function which will call <code>WSAStartup</code>, <code>WSACleanup</code> in Windows and will be no-op in Unix. And will call <code>WSAGetLastError</code> in Windows and return <code>errno</code> in Unix.</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">int</span> <span class="hljs-title">init_socket</span><span class="hljs-params">()</span> </span>{
<span class="hljs-meta">#<span class="hljs-meta-keyword">ifdef</span> WIN32</span>
  WSADATA wsa;
  <span class="hljs-keyword">return</span> WSAStartup(MAKEWORD(<span class="hljs-number">2</span>, <span class="hljs-number">0</span>), &amp;wsa);
<span class="hljs-meta">#<span class="hljs-meta-keyword">else</span> </span>
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
}

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">int</span> <span class="hljs-title">cleanup_socket</span><span class="hljs-params">()</span> </span>{
<span class="hljs-meta">#<span class="hljs-meta-keyword">ifdef</span> WIN32</span>
  WSADATA wsa;
  <span class="hljs-keyword">return</span> WSAStartup(MAKEWORD(<span class="hljs-number">2</span>, <span class="hljs-number">0</span>), &amp;wsa);
<span class="hljs-meta">#<span class="hljs-meta-keyword">else</span> </span>
  <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>

}

<span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">inline</span> <span class="hljs-keyword">int</span> <span class="hljs-title">get_last_socket_error</span><span class="hljs-params">()</span> </span>{
<span class="hljs-meta">#<span class="hljs-meta-keyword">ifdef</span> WIN32</span>
  <span class="hljs-keyword">return</span> WSAGetLastError(); 
<span class="hljs-meta">#<span class="hljs-meta-keyword">else</span></span>
  <span class="hljs-keyword">return</span> errno;
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
}
</code></pre>
<p>With code isolated and some redefined to fit the target platform, we can just replace any occurence of <code>WSAStartup</code> to <code>init_socket()</code> <code>WSACleanup</code> to <code>cleanup_socket()</code> and <code>WSAGetLastError</code> to <code>get_last_socket_error()</code>. And the include part will be like so:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdint.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string.h&gt;</span></span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"config.h"</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">"platform.h"</span> <span class="hljs-comment">// include this </span></span>

<span class="hljs-comment">// ... more code below</span>
</code></pre>
<p>And also, you may see there's new other header <code>config.h</code>. I move every configuration to this file like MTU and maximum buffer size.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">ifndef</span> OTLS_CONFIG_H </span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> OTLS_CONFIG_H 1 </span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MTU 1500 </span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> BUF_MAX_SIZE (8 * 2014)</span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span> <span class="hljs-comment">/* OTLS_CONFIG_H */</span></span>
</code></pre>
<p>With this sorted out, all we need to do is just revise <code>CMakeLists.txt</code> a little bit so it only link to <code>ws2_32.dll</code> on Windows and not doing anything else on Linux or macOS.</p>
<pre><code class="lang-cmake">if (WIN32)
  target_link_libraries(binfetch ws2_32)
endif (WIN32)
</code></pre>
<h2 id="heading-rebuild-and-run">Rebuild and Run</h2>
<p>The step on macOS and linux is the same. Prepare a directory for building and then use these commands.</p>
<pre><code class="lang-sh"><span class="hljs-built_in">cd</span> build

cmake ..

make

./binfetch
</code></pre>
<p>The command is short because I believe you're building the software natively. Because the code becomes complex. I've prepared the source repo for you to try.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/retrocodingnet/otls">https://github.com/retrocodingnet/otls</a></div>
<p>Here's the result on macOS</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652283499914/74vJS7Jem.gif" alt="macos.gif" /></p>
]]></content:encoded></item><item><title><![CDATA[Secure Oldies I : Introducing Windows Sockets and Simple HTTP Client]]></title><description><![CDATA[Goal
TLS 1.3 has been defined in 2018 and it has been 4 years from the definition, and earlier version TLS 1.2 has been defined one decade earlier at 2008. TLS 1.2 supports on Windows started from Windows 8.1 and Windows 7 Service Pack 1. If you want...]]></description><link>https://retrocoding.net/secure-oldies-i-introducing-windows-sockets-and-simple-http-client</link><guid isPermaLink="true">https://retrocoding.net/secure-oldies-i-introducing-windows-sockets-and-simple-http-client</guid><category><![CDATA[General Programming]]></category><category><![CDATA[networking]]></category><category><![CDATA[Windows]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Wed, 11 May 2022 11:00:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652216768801/wER4Hslkx.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-goal">Goal</h1>
<p>TLS 1.3 has been defined in 2018 and it has been 4 years from the definition, and earlier version TLS 1.2 has been defined one decade earlier at 2008. TLS 1.2 supports on Windows started from Windows 8.1 and Windows 7 Service Pack 1. If you want to access modern website using browsers on Windows XP, for example, it won't work. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652225844682/Q9GEg_1rM.png" alt="Jepretan Layar 2022-05-11 pukul 06.37.01.png" /></p>
<p>This series aim to create a command line tool to demonstrate ability to bring security to old platforms back to Windows 95 OSR 2 era. The primary goal is just for fun, the secondary goal is maybe for those who has these old operating systems around for mission-critical applications, can use this as a guide to write a secure applications.</p>
<p>Because we want to create a networked application, we'll start by TCP/IP and sockets.</p>
<h1 id="heading-about-tcpip">About TCP/IP</h1>
<p>Let's start series with short discussion about TCP/IP. The de-facto protocol of the internet. It was invented and built within the ARPA and by fate and momentum becomes the ubiquitous internet we know today. I won't explain this, I'd refer to a popular video directed to laymen video instead, because I'm lazy.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/PpsEaqJV_A0">https://youtu.be/PpsEaqJV_A0</a></div>
<p>TCP/IP comes in two versions: IPV4 and IPV6. I also won't indulge much on this one. In short, they are different in addressing scheme and there are also different setup which will be relevant for our next discussion point: the sockets API.</p>
<h1 id="heading-sockets-api">Sockets API</h1>
<p>In the beginning of the internet there's one API that prevails as the de-facto standard for interprocess communications: <a target="_blank" href="https://cis.temple.edu/~giorgio/old/cis307s96/readings/docs/sockets.html">The BSD Sockets</a>. Socket is just like a wall-socket: It's a place for two devices to connect and communicate. It abstracts the mechanism of networking between processes and machines. It's first implemented by BSD Unix. It provides an API standard that allows two processes or more to communicate. Sockets is pretty abstract and not limited to networked applications, there's also sockets between user space and kernel space. However, networked applications is the most common use case.</p>
<p>Socket API is pretty ubiquitous nowadays. Not only BSDs like FreeBSD, OpenBSD, or NetBSD. Unix clones like macOS and Linux also implement BSD sockets API. Non Unix operating systems, including Windows also joined the bandwagon since mid-90s because they don't want to be excluded in the internet era.</p>
<h2 id="heading-about-windows-sockets">About Windows Sockets</h2>
<p>Windows Sockets is Microsoft Windows implementation of BSD Sockets. Microsoft has released 2 versions of it. Before Windows Sockets there are vendor-specific socket libraries. The first WinSock 2 implementation was available for Windows 95 OSR 2 and Windows NT 4.0. So this will be our oldest target platforms.</p>
<h2 id="heading-differences-between-ipv4-and-ipv6">Differences between IPV4 and IPV6</h2>
<p>Before IPV6 the function to get address information is by using <a target="_blank" href="https://www.unix.com/man-page/posix/3posix/gethostbyname/">gethostbyname()</a>. Now, it's <code>getaddrinfo()</code> as documented in <a target="_blank" href="https://datatracker.ietf.org/doc/html/rfc2553#section-6.4">RFC-2553</a>and <a target="_blank" href="https://pubs.opengroup.org/onlinepubs/9699919799/">POSIX-2001</a> standard. As we want to support the ultimate ancient platforms who might not have <code>getaddrinfo()</code> on their platform library, we will use <code>gethostbyname()</code> in all of our programs.</p>
<h1 id="heading-writing-simple-http-client">Writing Simple HTTP Client</h1>
<p>Before we delve into secure socket connection, we'll learn at least how to create a simple TCP/IP socket client by using WinSock. This client will get a simple HTTP payload from http://httpbin.org. We'll start by creating plaintext HTTP.</p>
<h2 id="heading-setting-up-projects">Setting Up Projects</h2>
<h3 id="heading-toolchains">Toolchains</h3>
<p>There are two toolchains that we can use:</p>
<ul>
<li>We'll be using GNU-based MinGW toolchains. In Windows, we can install them from <a target="_blank" href="https://www.mingw-w64.org/">here</a> and for Linux and macOS, you can install MinGW using your install </li>
<li>We also need to install <a target="_blank" href="https://cmake.org/">CMake</a>. And add <code>cmake</code> to our <code>PATH</code>. Please refer to the installation guide how to do it. </li>
</ul>
<h2 id="heading-writing-the-source-code">Writing The Source Code</h2>
<p>First we'll create a simple Win32 Console Application <code>main.c</code>.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> WIN32_LEAN_AND_MEAN</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;winsock2.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;ws2tcpip.h&gt;</span></span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> **argv)</span> </span>{
  <span class="hljs-comment">// Winsock data </span>
  WSADATA wsa;

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Starting Up...\n"</span>);

  <span class="hljs-comment">// Result</span>
  <span class="hljs-keyword">int</span> res = WSAStartup(MAKEWORD(<span class="hljs-number">2</span>, <span class="hljs-number">0</span>), &amp;wsa);


  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Cleaning Up...\n"</span>);

  WSACleanup();

  <span class="hljs-keyword">return</span> res;
}
</code></pre>
<p>This code just startup and cleanup WinSock, nothing else. Just to test if the winsock works.</p>
<p>If you're cross compiling, you'd create a file called <code>mingw32-w64-x86_64.cmake</code> with this contents.</p>
<pre><code class="lang-cmake"># Sample toolchain file for building for Windows from an Ubuntu Linux system.
#
# Typical usage:
#    *) install cross compiler: `sudo apt-get install mingw-w64`
#    *) cd build
#    *) cmake -DCMAKE_TOOLCHAIN_FILE=~/mingw-w64-x86_64.cmake ..

set(CMAKE_SYSTEM_NAME Windows)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)

# cross compilers to use for C, C++ and Fortran
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)

# target environment on the build host system
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})


# modify default behavior of FIND_XXX() commands
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
</code></pre>
<p>Then you'd create a file called <code>CMakeLists.txt</code> with this contents:</p>
<pre><code class="lang-cmake">cmake_minimum_required(VERSION 3.20.0)
project(binfetch)

set (SOURCES main.c) 

add_executable(binfetch ${SOURCES})
target_link_libraries (binfetch ws2_32)
</code></pre>
<h3 id="heading-building">Building</h3>
<p>Create a directory called <code>build</code> inside the current directory. Use this command to generate the makefile and executable.</p>
<p>On Windows</p>
<pre><code class="lang-cmd">&gt; mkdir build 

&gt; cd build 

&gt; cmake -G "MinGW Makefiles" ..

&gt; migw32-make
</code></pre>
<p>On Linux/Mac or if you're using MingW for Windows</p>
<pre><code class="lang-sh">$ mkdir build

$ <span class="hljs-built_in">cd</span> build 

$ cmake --toolchain ../mingw-w64-x86_64.cmake ..

$ make
</code></pre>
<p>The result will be an executable named <code>binfetch.exe</code>, in which we can run. The result will be like this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652237153924/C8DIAALT9.png" alt="Jepretan Layar 2022-05-11 pukul 09.45.42.png" /></p>
<h2 id="heading-preparing-structure-for-hostname-resolution">Preparing structure for hostname resolution.</h2>
<p>Hostname resolution in IPV4 is done by using <code>gethostbyname</code>. This will result in <code>struct hostent</code> structure. This structure is defined as:</p>
<pre><code class="lang-c"><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">hostent</span> {</span>
  <span class="hljs-keyword">char</span>  *h_name;
  <span class="hljs-keyword">char</span>  **h_aliases;
  <span class="hljs-keyword">short</span> h_addrtype;
  <span class="hljs-keyword">short</span> h_length;
  <span class="hljs-keyword">char</span>  **h_addr_list;
} HOSTENT, *PHOSTENT, *LPHOSTENT;
</code></pre>
<p>What we're interested in is the <code>h_addr_list</code> member. This will contains a pointer to a buffer which each of the entry is a <code>struct in_addr*</code>. Honestly, I think the type of this should be <code>void**</code> as it's confusing and by <code>char**</code> it implies that it's a character buffer or array of string which is actually not.</p>
<p>Alright, let's declare an <code>hostent</code> variable on top and get the entries.</p>
<pre><code class="lang-c"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">hostent</span> *<span class="hljs-title">entry</span>;</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">in_addr</span> **<span class="hljs-title">addr_list</span>, **<span class="hljs-title">addr_iter</span>, <span class="hljs-title">addr_item</span>;</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">in_addr</span> <span class="hljs-title">addr</span>;</span>

<span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> httpbin[] = <span class="hljs-string">"httpbin.org"</span>;
</code></pre>
<p>And then show time, we'll get the host entry for the address.</p>
<pre><code class="lang-c">entry = gethostbyname(httpbin);

  <span class="hljs-keyword">if</span> ( entry == <span class="hljs-literal">NULL</span> ) {
    res = WSAGetLastError();
    <span class="hljs-keyword">goto</span> error;
  }
</code></pre>
<p>We'll use <code>goto</code> on this case because we want to bail out when error happens and we don't want to type multiple types. In the bottom of the function, we can put an error label just after <code>return</code></p>
<pre><code class="lang-c">  WSACleanup();
  <span class="hljs-keyword">return</span> res;

<span class="hljs-comment">// error handling, printing something before exiting</span>
error:
  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Get Winsock error 0x%X!"</span>, res);
  WSACleanup();

  <span class="hljs-keyword">return</span> res;
</code></pre>
<p>If the call succeeded then we iterate on each of the host entries.</p>
<pre><code class="lang-c">  addr_list = (struct in_addr **) entry-&gt;h_addr_list; <span class="hljs-comment">// (1)</span>
  addr_iter = addr_list; <span class="hljs-comment">// (2) </span>

  <span class="hljs-keyword">while</span> (*addr_iter != <span class="hljs-literal">NULL</span>) { <span class="hljs-comment">// (3)</span>
    <span class="hljs-built_in">memcpy</span>(&amp;addr_item, *addr_iter, entry-&gt;h_length); <span class="hljs-comment">// (4)</span>
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, inet_ntoa(addr_item)); <span class="hljs-comment">// (5) </span>
    ++addr_iter;  <span class="hljs-comment">// (6)</span>
  }
</code></pre>
<p>So let me explain line by line, because this can be mouthful. </p>
<ol>
<li>We cast the <code>h_addr_list</code> to a pointer to a <code>struct in_addr</code> pointer.</li>
<li>We use iterator to iterate on the entries.</li>
<li>We check whether it's a <code>NULL</code> if it's null we bail out.</li>
<li>If it's not null then we copy the content of that location to <code>addr_item</code> which will hold our address structure.</li>
<li>We convert <code>addr_item</code> to a string which we can read and then print them to screen.</li>
<li>We advance the pointer once to get next entry.</li>
</ol>
<p>Until here, the result are like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652241248600/8x0aDDoYm.png" alt="Jepretan Layar 2022-05-11 pukul 10.53.54.png" /></p>
<p>These are the IP addresses of <code>httpbin.org</code>. Which one we want to choose? We can just pick the first entry for our next activity: connecting and disconnecting.</p>
<h2 id="heading-prepare-the-socket-and-connect-to-the-server">Prepare the socket and connect to the server.</h2>
<p>To connect to a server we'd need to do these steps:</p>
<ol>
<li>Prepare <code>sockaddr_in</code> using <code>AF_INET</code> as the protocol family, and <code>80</code> as the port </li>
<li>Open a socket, using <code>socket</code> call with <code>PF_INET</code> as the protocol family. 
(http port). We copy the resolved address to <code>sin_addr</code>.</li>
<li>Connect using <code>sockaddr_in</code> which is passed as <code>struct sockaddr *</code>. </li>
<li>Close the socket when done.</li>
</ol>
<p>On each step, we'll check for error.</p>
<pre><code class="lang-c">  <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">sockaddr_in</span> <span class="hljs-title">addr</span>;</span>
  <span class="hljs-comment">//...</span>

  <span class="hljs-built_in">memset</span>(&amp;addr, <span class="hljs-number">0</span>, <span class="hljs-keyword">sizeof</span>(struct sockaddr_in)); <span class="hljs-comment">// (1)</span>

  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);

  <span class="hljs-built_in">memcpy</span>(&amp;addr.sin_addr, addr_list[<span class="hljs-number">0</span>], entry-&gt;h_length);

  client = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); <span class="hljs-comment">// (2)</span>

  <span class="hljs-keyword">if</span> (INVALID_SOCKET == client) {
    <span class="hljs-keyword">goto</span> error;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Socket opened 0x%X\n"</span>, client);

  res = connect(client, (struct sockaddr *) &amp;addr, 
    <span class="hljs-keyword">sizeof</span>(struct sockaddr_in)); <span class="hljs-comment">// (3)</span>

  <span class="hljs-keyword">if</span> (SOCKET_ERROR == res) {
    <span class="hljs-keyword">goto</span> error;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Connected to %s (%s)\n"</span>, inet_ntoa(addr.sin_addr), httpbin);

  res = closesocket(client); <span class="hljs-comment">// (4)</span>

  <span class="hljs-keyword">if</span> ( SOCKET_ERROR == res ) {
    <span class="hljs-keyword">goto</span> error;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Socket 0x%X closed\n"</span>, client);
</code></pre>
<p>After compilation the result is like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652244068860/TToASrL0C.png" alt="Jepretan Layar 2022-05-11 pukul 11.40.54.png" /></p>
<p>This means that our connection is succeeded. </p>
<h2 id="heading-send-request-and-receive-response">Send request and receive response.</h2>
<p>HTTP is request-response text-based protocol. To fetch from <code>httpbin.org</code>, we'll execute <code>GET</code> to <code>/get</code> path. To send this request, according to <a target="_blank" href="https://www.rfc-editor.org/rfc/rfc2616#section-4">RFC2616 § 4</a> is separated line-by line.</p>
<ol>
<li>First Line is the HTTP message type. This includes the method and path. Example: <code>GET /get HTTP/1.1</code>.</li>
<li>The next line is the headers. As we're using HTTP 1.1, we'd need to put at least two headers.<ul>
<li><code>Host: httpbin.org</code> telling the host name of the server. Just in case there are multiple 'virtual hosts' within one single web server, the web server will decide which traffic to serve based on this header.</li>
<li><code>Connection: close</code> we tell the web server to use HTTP 1.0 connection. We close connection on each request-response.</li>
</ul>
</li>
<li>We'll add more headers<ul>
<li><code>User-Agent: Retrocoder/1.0</code>. We're telling our software name and version.</li>
<li><code>Content-Length: 0</code>. We don't have content within our body.</li>
<li><code>Accept: application/json</code>. We're asking JSON response.</li>
</ul>
</li>
</ol>
<p>We'll hard code this request for now.</p>
<pre><code class="lang-c"><span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> request [] = 
    <span class="hljs-string">"GET /get HTTP/1.1\r\n"</span>
    <span class="hljs-string">"Host: httpbin.org\r\n"</span>
    <span class="hljs-string">"Connection: close\r\n"</span>
    <span class="hljs-string">"User-Agent: Retrocoder/1.0\r\n"</span>
    <span class="hljs-string">"Accept: application/json\r\n"</span>
    <span class="hljs-string">"Content-Length: 0\r\n"</span>
    <span class="hljs-string">"\r\n"</span>;
</code></pre>
<p>Then we'll send the request to the server using <code>send()</code> function.</p>
<pre><code class="lang-c">res = send(client, request, <span class="hljs-keyword">sizeof</span>(request) - <span class="hljs-number">1</span>, <span class="hljs-number">0</span>);

<span class="hljs-keyword">if</span> ( SOCKET_ERROR == res ) {
    <span class="hljs-keyword">goto</span> error;
}
</code></pre>
<p>This will send our request to <code>httpbin.org</code> web server. We substract <code>1</code> from request size because we only want the string without the terminating zero. </p>
<p>To receive response we'd need to define receive buffer and total buffer we have. We'll set and MTU (minimum transfer unit) of <code>1500</code> and buffer size of 8KB.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MTU 1500 </span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> BUF_MAX_SIZE (8 * 2014)</span>
  <span class="hljs-keyword">uint8_t</span> buf[MTU];
  <span class="hljs-keyword">char</span> response[BUF_MAX_SIZE]; <span class="hljs-comment">// 8K buffer</span>
</code></pre>
<p>This we define two local variables. We'll use them as the buffer for the data we receive later using <code>recv()</code>. We'll receive the packet using <code>buf</code> and then append the result to <code>response</code>. Before we continue, I'd like to give you the prototype of <code>recv</code> from WinSock API:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">recv</span><span class="hljs-params">(
  [in]  SOCKET s,
  [out] <span class="hljs-keyword">char</span>   *buf,
  [in]  <span class="hljs-keyword">int</span>    len,
  [in]  <span class="hljs-keyword">int</span>    flags
)</span></span>;
</code></pre>
<p>The return of this function is bytes receive, so we'd need to keep track of that. We'll use <code>i</code> to track the total bytes we receive.</p>
<pre><code class="lang-c"><span class="hljs-keyword">size_t</span> i = <span class="hljs-number">0</span>;
</code></pre>
<p>And then we begin to receive</p>
<pre><code>  do {
    res <span class="hljs-operator">=</span> recv(client, (char <span class="hljs-operator">*</span>) buf, MTU, <span class="hljs-number">0</span>); <span class="hljs-comment">// (1)</span>

    <span class="hljs-keyword">if</span> ( SOCKET_ERROR <span class="hljs-operator">=</span><span class="hljs-operator">=</span> res <span class="hljs-operator">|</span><span class="hljs-operator">|</span> i <span class="hljs-operator">+</span> res <span class="hljs-operator">&gt;</span> BUF_MAX_SIZE ) { <span class="hljs-comment">// (2)</span>
      <span class="hljs-keyword">break</span>;
    }

    memcpy(response <span class="hljs-operator">+</span> i, buf, res); <span class="hljs-comment">// (3)</span>

    i <span class="hljs-operator">+</span><span class="hljs-operator">=</span> res; <span class="hljs-comment">// (4)</span>
  } <span class="hljs-keyword">while</span> (res <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>);  <span class="hljs-comment">// (5)</span>

  <span class="hljs-keyword">if</span> (res <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) { <span class="hljs-comment">// (6)</span>
    goto <span class="hljs-function"><span class="hljs-keyword">error</span></span>;
  }

  printf(<span class="hljs-string">"Response:\n\n"</span>);

  fwrite(response, sizeof(char), i, stdout); <span class="hljs-comment">// (7)</span>
</code></pre><p>The explanation is as follows:</p>
<ol>
<li>We'll receive a packet with maximum size of <code>MTU</code> to <code>buf</code>.</li>
<li>If the function fails or the received result exceeds the <code>BUF_MAX_SIZE</code> (8KB), we bail out.</li>
<li>Copy the response from <code>buf</code> to the <code>response</code> on offset <code>i</code>.</li>
<li>Advance <code>i</code> by the size of received packet.</li>
<li>Loop until <code>res</code> is zero which means that connection closed gracefully.</li>
<li>Go to error handling if we bails out before end of connection.</li>
<li>Write the response to standard out.</li>
</ol>
<p>Now that our program is complete, here's the complete source code:</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> WIN32_LEAN_AND_MEAN</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;windows.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;winsock2.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;ws2tcpip.h&gt;</span></span>

<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdint.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">(<span class="hljs-keyword">int</span> argc, <span class="hljs-keyword">char</span> **argv)</span> </span>{
  <span class="hljs-comment">// Winsock data </span>
  WSADATA wsa;
  <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">hostent</span> *<span class="hljs-title">entry</span>;</span>
  <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">in_addr</span> **<span class="hljs-title">addr_list</span>, **<span class="hljs-title">addr_iter</span>, <span class="hljs-title">addr_item</span>;</span>
  <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">sockaddr_in</span> <span class="hljs-title">addr</span>;</span>
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> httpbin[] = <span class="hljs-string">"httpbin.org"</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">short</span> port = <span class="hljs-number">80</span>;
  <span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> request [] = 
    <span class="hljs-string">"GET /get HTTP/1.1\r\n"</span> <span class="hljs-comment">/* Request Line */</span>
    <span class="hljs-string">"Host: httpbin.org\r\n"</span>
    <span class="hljs-string">"Connection: close\r\n"</span>
    <span class="hljs-string">"User-Agent: Retrocoder/1.0\r\n"</span>
    <span class="hljs-string">"Accept: application/json\r\n"</span>
    <span class="hljs-string">"Content-Length: 0\r\n"</span>
    <span class="hljs-string">"\r\n"</span>;
  SOCKET client = INVALID_SOCKET;
  <span class="hljs-keyword">size_t</span> i = <span class="hljs-number">0</span>;

<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> MTU 1500 </span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> BUF_MAX_SIZE (8 * 2014)</span>

  <span class="hljs-keyword">uint8_t</span> buf[MTU];
  <span class="hljs-keyword">char</span> response[BUF_MAX_SIZE]; <span class="hljs-comment">// 4K buffer</span>

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Starting Up...\n"</span>);

  <span class="hljs-comment">// Result</span>
  <span class="hljs-keyword">int</span> res = WSAStartup(MAKEWORD(<span class="hljs-number">2</span>, <span class="hljs-number">0</span>), &amp;wsa);

  <span class="hljs-comment">// host entries (this is allocated by gethostbyname) </span>
  entry = gethostbyname(httpbin);

  <span class="hljs-keyword">if</span> ( entry == <span class="hljs-literal">NULL</span> ) {
    res = WSAGetLastError();
    <span class="hljs-keyword">goto</span> error;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Address resolved for %s\n"</span>, httpbin);

  addr_list = (struct in_addr **) entry-&gt;h_addr_list; <span class="hljs-comment">// (1)</span>
  addr_iter = addr_list; <span class="hljs-comment">// (2) </span>

  i = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">while</span> (*addr_iter != <span class="hljs-literal">NULL</span>) { 
    <span class="hljs-built_in">memcpy</span>(&amp;addr_item, *addr_iter, entry-&gt;h_length); <span class="hljs-comment">// (3)</span>
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\n"</span>, inet_ntoa(addr_item)); <span class="hljs-comment">// (4) </span>
    ++addr_iter;  <span class="hljs-comment">// (5)</span>
    ++i;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d addresses resolved.\n\n"</span>, i);

  <span class="hljs-built_in">memset</span>(&amp;addr, <span class="hljs-number">0</span>, <span class="hljs-keyword">sizeof</span>(struct sockaddr_in));

  addr.sin_family = AF_INET;
  addr.sin_port = htons(port);

  <span class="hljs-built_in">memcpy</span>(&amp;addr.sin_addr, addr_list[<span class="hljs-number">0</span>], entry-&gt;h_length);

  client = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

  <span class="hljs-keyword">if</span> (INVALID_SOCKET == client) {
    <span class="hljs-keyword">goto</span> error;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Socket opened 0x%X\n"</span>, client);

  res = connect(client, (struct sockaddr *) &amp;addr, 
    <span class="hljs-keyword">sizeof</span>(struct sockaddr_in));

  <span class="hljs-keyword">if</span> (SOCKET_ERROR == res) {
    <span class="hljs-keyword">goto</span> error;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Connected to %s (%s)\n"</span>, inet_ntoa(addr.sin_addr), httpbin);

  res = send(client, request, <span class="hljs-keyword">sizeof</span>(request) - <span class="hljs-number">1</span>, <span class="hljs-number">0</span>);

  <span class="hljs-keyword">if</span> ( SOCKET_ERROR == res ) {
    <span class="hljs-keyword">goto</span> error;
  }

  i = <span class="hljs-number">0</span>;
  <span class="hljs-keyword">do</span> {
    res = recv(client, (<span class="hljs-keyword">char</span> *) buf, MTU, <span class="hljs-number">0</span>);

    <span class="hljs-keyword">if</span> ( SOCKET_ERROR == res || i + res &gt; BUF_MAX_SIZE ) {
      <span class="hljs-keyword">break</span>;
    }

    <span class="hljs-built_in">memcpy</span>(response + i, buf, res);

    i += res;
  } <span class="hljs-keyword">while</span> (res != <span class="hljs-number">0</span>); 

  <span class="hljs-keyword">if</span> (res != <span class="hljs-number">0</span>) {
    <span class="hljs-keyword">goto</span> error;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Response:\n\n"</span>);

  fwrite(response, <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">char</span>), i, <span class="hljs-built_in">stdout</span>);

  res = closesocket(client); 

  <span class="hljs-keyword">if</span> ( SOCKET_ERROR == res ) {
    <span class="hljs-keyword">goto</span> error;
  }

  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Socket 0x%X closed\n"</span>, client);

out:
  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Cleaning Up...\n"</span>);
  WSACleanup();
  <span class="hljs-keyword">return</span> res;

error:
  <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Get Winsock error 0x%X!"</span>, res);
  WSACleanup();

  <span class="hljs-keyword">return</span> res;
}
</code></pre>
<p>And here's the result running on 64-bits Windows 10.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652258276796/Dfk0f8F5u.gif" alt="httpclient.gif" /></p>
<h1 id="heading-testing-on-older-windows">Testing on Older Windows</h1>
<h2 id="heading-adjusting-the-toolchain-to-32-bit">Adjusting the Toolchain to 32-bit.</h2>
<p>First we try to run the application for Windows XP, an operating system from 2001. To compile for Windows XP we'd need to change our toolchain file.</p>
<p>As ironic as it is, MinGW doesn't really work for 32-bit Windows nowadays. Especially if your host is Windows 10. So, the solution is just us <a target="_blank" href="https://www.docker.com/products/docker-desktop/">docker on Windows</a> and use it as a cross compiler.</p>
<p>On macOS and Linux</p>
<ol>
<li>Copy <code>mingw-w64-x86_64.cmake</code> to <code>mingw-w64-i686.cmake</code></li>
<li>Edit and change the line who says <code>set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)</code> to <code>set(TOOLCHAIN_PREFIX i686-w64-mingw32)</code>.</li>
<li>Run the <code>cmake</code> like follow
 ```
cmake --toolchain ../mingw-w64-i686.cmake ..</li>
</ol>
<p>make
    ```</p>
<p>We'll fix this issue by using even older toolchain called OpenWatcom. But for now, we'll stick on using MinGW first.</p>
<p>Here's the test using Windows XP Service Pack 3</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652259228416/kp55f0L7Z.gif" alt="xptest.gif" /></p>
<p>and then we run it on Windows 2000 SP 4.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652264207862/JJ2FYG5PO.gif" alt="win2ktest.gif" /></p>
<p>So, this software is able to run on top of 23 years old operating system. There's one problem tho: because Windows 7 SP 1 was the earliest to support TLS 1.2 which is mandatory to access secure HTTP, we cannot use the TLS layer from Windows' built-in SChannels. We'll be using mbedTLS as the TLS library on top of Winsock. </p>
<h1 id="heading-trivia-and-exercise">Trivia and Exercise</h1>
<p>The code on <code>main.c</code> is actually pretty portable. The only platform specific code is the Windows Header and Winsock startup and shutdown. Can you make it portable so it can be compiled on Linux and macOS?</p>
<p>Here's the hint</p>
<ul>
<li>Look at the definition of sockets structures from the manpages.</li>
<li>Linux define <code>__linux__</code> on their headers and macos defines <code>DARWIN</code> on the compiler, and Windows defines <code>WIN32</code>.</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Windows' Hello World in x86_64]]></title><description><![CDATA[So I've written about how to do Hello World in Linux and macOS. You might need to check it out. 
Toolchain
For this article, I will still use GNU Assembler as our tool of choice. We'll be using MINGW-W64 to build our hello world project. MingW is a G...]]></description><link>https://retrocoding.net/windows-hello-world-in-x8664</link><guid isPermaLink="true">https://retrocoding.net/windows-hello-world-in-x8664</guid><category><![CDATA[General Programming]]></category><category><![CDATA[Windows]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Fri, 06 May 2022 19:06:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651864075976/mc1h5l2Ul.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>So I've written about how to do <a target="_blank" href="https://retrocoding.net/hello-world-in-x8664-assembly-on-linux-and-macos">Hello World in Linux and macOS</a>. You might need to check it out. </p>
<h1 id="heading-toolchain">Toolchain</h1>
<p>For this article, I will still use GNU Assembler as our tool of choice. We'll be using MINGW-W64 to build our hello world project. MingW is a GCC distribution to create a windows application. You can install it on Windows, macOS, or Linux.</p>
<p>To install you can install in on Linux or Mac using your package manager. For Ubuntu and Debian</p>
<pre><code><span class="hljs-comment"># Ubuntu &amp; Debian</span>
<span class="hljs-attribute">sudo</span> apt install mingw-w<span class="hljs-number">64</span>
</code></pre><p>For other linux distributions, you can look at the manual of the respective package managers.</p>
<h1 id="heading-writing-the-application">Writing the application</h1>
<p>With Windows, it'll be little different. I'll be creating two programs. First it's the same as the command line tools we've been written for Linux and macOS. The other one is we'll be using pure Windows API to show "Hello World" in message box.</p>
<p>Also same with macOS, our code will be <a target="_blank" href="https://en.wikipedia.org/wiki/Position-independent_code">Position Independent Code</a>, so we'll use relative addressing with <code>RIP</code> as the base address.</p>
<h2 id="heading-command-line-style-hello-world">Command Line Style Hello World</h2>
<p>With Linux and macOS we can use the <code>syscall</code> assembly instructions. In Windows, we cannot as the number changes between versions. You can see system call numbers in Windows here: https://j00ru.vexillium.org/syscalls/nt/64/. To print "Hello, World!" we'd need to call something to write into <code>stdout</code> and also to exit the program. In Linux it was system call number 1 <code>write</code> and 60 <code>exit</code>. In Windows, system calls aren't stable across versions, so we'll sue Windows API</p>
<ol>
<li>We'd need to get handle to stdout by calling up <a target="_blank" href="https://docs.microsoft.com/en-us/windows/console/getstdhandle">GetStdHandle</a> with <code>-11</code> as the value of the parameter.</li>
<li>To be able to write on <code>stdout</code> we'd need to call <a target="_blank" href="https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile">WriteFile</a> function from the Windows API.</li>
<li>And after everything is done we'll call <a target="_blank" href="https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitprocess">ExitProcess</a>.</li>
</ol>
<p>They are normal function calls, in which we'd need to refer to <a target="_blank" href="https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170">Windows x64 ABI and calling convention</a>. Some important points are</p>
<blockquote>
<p>Integer valued arguments in the leftmost four positions are passed in left-to-right order in RCX, RDX, R8, and R9, respectively. The fifth and higher arguments are passed on the stack as previously described.</p>
<p>These registers, and RAX, R10, R11, XMM4, and XMM5, are considered volatile</p>
<p>The shadow space is the mandatory 32 bytes (4x8 bytes) you must reserve for the called procedure. The address of our entry point is added to the stack, so we'd need to allocate shadow space of 40 bytes. (32 + 8 byte address).</p>
</blockquote>
<p>I think this is enough to deduce how to write Hello World in Windows. We can start with usual preamble with <code>.rodata</code> defined.</p>
<pre><code class="lang-asm">.code64
.section .rodata
msg: .ascii "Hello, World!\n"
.set msglen, (. - msg)

.section .text
.global _start
_start:
  sub $40, %rsp 

  add $40, %rsp
  ret $0
</code></pre>
<p>We'd need to call Windows APIs: <code>GetStdHandle</code>, <code>WriteFile</code>, and <code>ExitProcess</code>. So we'll declare them as <code>.extern</code>.</p>
<pre><code class="lang-asm">.extern GetStdHandle
.extern WriteFile
.extern ExitProcess
</code></pre>
<h3 id="heading-getting-standard-out-handle">Getting Standard Out Handle</h3>
<p>The first task is to get handle for stdout. For this we'll declare a value <code>STD_OUTPUT_HANDLE</code> as documented in Windows API and assign value <code>-11</code>.</p>
<pre><code class="lang-asm">.set STD_OUTPUT_HANDLE, -11
</code></pre>
<p>Don't forget to add new section <code>.data</code> to save the result of the call</p>
<pre><code class="lang-asm">.section .data
stdout: .long 0
</code></pre>
<p>and below start, we pass it as the first argument of <code>GetStdHandle</code> and then give the return value which is saved to register <code>RAX</code> to <code>stdout</code>.</p>
<pre><code class="lang-asm">_start:
  sub $40, %rsp

  mov $STD_OUTPUT_HANDLE, %rcx
  call GetStdHandle
  mov %rax, stdout(%rip)
</code></pre>
<p>This is similar to calling in C code: </p>
<pre><code class="lang-C">HANDLE <span class="hljs-built_in">stdout</span> = GetStdHandle(STD_OUTPUT_HANDLE);
</code></pre>
<h3 id="heading-writing-to-standard-out-and-exiting">Writing to Standard Out and Exiting</h3>
<p>We'll use <code>WriteFile</code> API which has this prototype</p>
<pre><code class="lang-C"><span class="hljs-function">BOOL <span class="hljs-title">WriteFile</span><span class="hljs-params">(
  [in]                HANDLE       hFile,
  [in]                LPCVOID      lpBuffer,
  [in]                DWORD        nNumberOfBytesToWrite,
  [out, optional]     LPDWORD      lpNumberOfBytesWritten,
  [in, out, optional] LPOVERLAPPED lpOverlapped
)</span></span>;
</code></pre>
<p>Calling it with assembly means that we'll pass the first four parameters to <code>RCX</code>, <code>RDX</code>, <code>R8</code>, and <code>R9</code> and then fifth parameter to the stack. With that we can see that.</p>
<ul>
<li><code>hFile</code> is the result of <code>GetStdHandle</code> we'll pass it out to <code>RCX</code>.</li>
<li><code>lpBuffer</code> is our message, so we'll load the address to <code>RDX</code>.</li>
<li><code>nNumberOfBytesToWrite</code> is our message length. We'll load it to <code>R8</code>.</li>
<li><code>lpNumberOfBytesWritten</code> is an address where we'll capture the bytes written, we'll define a location in <code>data</code> section and then pass this to <code>R9</code></li>
<li><code>lpOverlapped</code> is an indicator whether we'll want Overlapped IO, which we'll answer with pushing <code>0</code> to the stack.</li>
</ul>
<p>So, we'll define <code>bytes_written</code> as a location in <code>.data</code> section.</p>
<pre><code class="lang-asm">bytes_written: .long 0
</code></pre>
<p>Then we'll call the function</p>
<pre><code class="lang-asm">  mov stdout(%rip), rcx
  lea msg(%rip), %rdx
  mov %msglen, %r8
  lea bytes_written(%rip), %r9
  push $0
  call WriteFile
</code></pre>
<p>Last but not least we exit the process and returning 0</p>
<pre><code class="lang-asm">xor %rcx, %rcx
call ExitProcess
ret
</code></pre>
<p>The full source code will be:</p>
<pre><code class="lang-asm">.code64
.section .rodata
msg: .ascii "Hello, World!\n"
.set msglen, (. - msg)

.extern GetStdHandle 
.extern WriteFile
.extern ExitProcess 

.set STD_OUTPUT_HANDLE, -11 

.section .data 

stdout: .long 0 
bytes_written: .long 0 

.section .text
.global _start 
_start:
    sub $40, %rsp
    mov $STD_OUTPUT_HANDLE, %rcx
    call GetStdHandle
    mov %rax, stdout(%rip) 


    mov stdout(%rip), %rcx
    lea msg(%rip), %rdx
    mov $msglen, %r8
    lea bytes_written(%rip), %r9 
    push $0
    call WriteFile 

    xor %rcx, %rcx 
    call ExitProcess 
    add $40, %rsp
    ret $0
</code></pre>
<p>We then assemble and link the file. Let's say we use the name <code>main.S</code>.</p>
<pre><code class="lang-sh">x86_64-w64-mingw32-as main.S -o main.o
x86_64-w64-mingw32-ld main.o -entry=_start -subsystem=console -lkernel32 -o hello.exe
</code></pre>
<p>Parameters <code>-entry</code> on the linker signify the entry point of the program <code>-subsystem=console</code> means that we want to build this for command line entireface. <code>-lkernel32</code> means that we will need to link to <code>KERNEL32.DLL</code> the library of Windows which provides <code>GetStdHandle</code>, <code>WriteFile</code>, and <code>ExitProcess</code>.</p>
<p>This is the result running in Windows 10</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651860770844/6GytPfDHX.png" alt="Jepretan Layar 2022-05-07 pukul 01.12.26.png" /></p>
<h2 id="heading-message-box-style-hello-world">Message Box Style Hello World:</h2>
<p>This style of hello world will show a message box instead of showing hello world in console. For that to happen, we'll invoke <a target="_blank" href="https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxa">MessageBoxA</a> API instead of <code>WriteFile.</code>MessageBoxA` is a Windows API to show a message box with ASCII character set. The prototype is as follows:</p>
<pre><code class="lang-C"><span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">MessageBoxA</span><span class="hljs-params">(
  [in, optional] HWND   hWnd,
  [in, optional] LPCSTR lpText,
  [in, optional] LPCSTR lpCaption,
  [in]           UINT   uType
)</span></span>;
</code></pre>
<p>As you can see, it accept <code>LPCSTR</code> which literally means <strong>L</strong>ong <strong>P</strong>ointer to <strong>C Str</strong>ing. What does it means? It means it needs a zero-terminated string. We'd need to change our <code>msg</code> declaration to this:</p>
<pre><code class="lang-asm">msg: .asciz "Hello, World!"
</code></pre>
<p>We change <code>.ascii</code> directive to <code>.asciz</code> which will terminate the string with NULL character. I will also define another symbol for the caption</p>
<pre><code class="lang-asm">caption: .asciz "Hello!"
</code></pre>
<p>The last parameter is <code>uType</code>, we'll use the constant MB_OK and MB_ICONINFORMATION by defining it as a <code>.set</code> symbols:</p>
<pre><code>.set MB_OK, <span class="hljs-number">0</span>
.set MB_ICONINFORMATION, <span class="hljs-number">0x40</span>
</code></pre><p>Calling the function is as easy as just loading those to registers.</p>
<ul>
<li><code>hWnd</code> will be <code>0</code> or <code>NULL</code> as this is the parent window, we pass to <code>RCX</code>. </li>
<li><code>lpText</code> will be the text. We load to <code>RDX</code>.</li>
<li><code>lpCaption</code> will be the caption of the dialog. We load them to <code>R8</code>.</li>
<li><code>uType</code> will be the or between <code>MB_OK</code> and <code>MB_ICONINFORMATION</code> and will be loaded to <code>R9</code>.</li>
</ul>
<p>Therefore the call will be:</p>
<pre><code class="lang-asm">    xor %rcx, %rcx
    lea msg(%rip), %rdx
    lea caption(%rip), %r8
    mov $(MB_OK | MB_ICONINFORMATION), %r9
    call MessageBoxA
</code></pre>
<p>The result of the call will be saved to <code>RAX</code>, but we won't use it. The exit instructions are the same so the full source will be:</p>
<pre><code class="lang-asm">.code64
.section .rodata
msg: .asciz "Hello, World!"
caption: .asciz "Hello!"

.set MB_OK, 0
.set MB_ICONINFORMATION, 0x40

.extern MessageBoxA
.extern ExitProcess 

.section .text
.global _start 
_start:

    sub $40, %rsp 

    xor %rcx, %rcx 
    lea msg(%rip), %rdx 
    lea caption(%rip), %r8 
    mov $(MB_OK | MB_ICONINFORMATION), %r9 
    call MessageBoxA

    xor %rcx, %rcx 
    call ExitProcess

    add $40, %rsp 
    ret $0
</code></pre>
<p>The assembling and linking process is pretty much the same:</p>
<pre><code class="lang-sh">x86_64-w64-mingw32-as main.S -o main.o
x86_64-w64-mingw32-ld main.o -o hello.exe \
  -entry=_start -subsystem=windows \
  -luser32 -lkernel32
</code></pre>
<p>Except for the linking part when we use <code>-subsystem=windows</code> to say that we don't want console, and also we'd need to link to <code>USER32.DLL</code> by adding <code>-luser32</code>. And here's the result</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651863687635/MNe9Vu2B2.png" alt="Jepretan Layar 2022-05-07 pukul 02.00.58.png" /></p>
<h1 id="heading-summary">Summary</h1>
<p>So here we are we have built a modern 64-bit hello world application in Linux, macOS, and Windows using GNU Assembler syntax. You may also interested on my 16-bit Windows tutorial on youtube</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=dRfodF1Uo6U">https://www.youtube.com/watch?v=dRfodF1Uo6U</a></div>
]]></content:encoded></item><item><title><![CDATA[Hello World in x86_64 Assembly on Linux, and macOS.]]></title><description><![CDATA[I want to start this blog with something that's easier to digest and maybe relevant with the theme of this blog: Assembly. It's 2022 and we're thinking: can I program in assembly nowadays? Well it turns out you can. Assembly is pretty much alive not ...]]></description><link>https://retrocoding.net/hello-world-in-x8664-assembly-on-linux-and-macos</link><guid isPermaLink="true">https://retrocoding.net/hello-world-in-x8664-assembly-on-linux-and-macos</guid><category><![CDATA[General Programming]]></category><dc:creator><![CDATA[Didiet Noor]]></dc:creator><pubDate>Mon, 02 May 2022 05:35:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1651461516895/bdym5glUC.gif" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I want to start this blog with something that's easier to digest and maybe relevant with the theme of this blog: Assembly. It's 2022 and we're thinking: can I program in assembly nowadays? Well it turns out you can. Assembly is pretty much alive not dead. People telling you otherwise don't know what they're talking about. Look at this TIOBE index of programming language. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651462119106/DsKYXuKzD.png" alt="Jepretan Layar 2022-05-02 pukul 10.26.51.png" />
It's 8th in the index. So much achievement who many consider as <em>dead language</em> 🤷. Not even PHP can beat its popularity. </p>
<p>Assembly is not really a <em>programming language</em> like C or Go. In short, it's like 1-1 mapping between machine language and its textual format. By that definition, it's the lowest level of language and it's inherently non-portable across machines.</p>
<p>Writing assembly on modern system is possible and fairly easy if you're a developer. You only need, at least, two things. An assembler and a linker. Assembler is a program which will <em>assemble</em> the textual representation to machine code, also known as <strong>object code</strong>. A linker will link the object code with platform libraries to form a full program.</p>
<h1 id="heading-linux">Linux</h1>
<p>Let's start with the easiest platform to work and explain with: Linux. Fire up your computer, virtual machine, or docker container to start this journey. I assume as you're going here, you don't have problem installing <code>gcc</code> to your machine. But anyway, I'll still give you reference for Ubuntu/Debian and Fedora/Redhat.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Red Hat Based Distro (including Fedora)</span>
sudo dnf groupinstall gcc

<span class="hljs-comment"># Debian/Ubuntu</span>
sudo apt install gcc
</code></pre>
<p>I didn't put how to install in distro like Arch, because if you're using Arch Linux, then you basically know what you're doing. </p>
<p>You can check by invoking the <code>as</code> and <code>ld</code> command.</p>
<pre><code><span class="hljs-string">$</span> <span class="hljs-string">as</span> <span class="hljs-string">--version</span>

<span class="hljs-string">GNU</span> <span class="hljs-string">assembler</span> <span class="hljs-string">(GNU</span> <span class="hljs-string">Binutils</span> <span class="hljs-string">for</span> <span class="hljs-string">Ubuntu)</span> <span class="hljs-number">2.38</span>
<span class="hljs-string">Copyright</span> <span class="hljs-string">(C)</span> <span class="hljs-number">2022 </span><span class="hljs-string">Free</span> <span class="hljs-string">Software</span> <span class="hljs-string">Foundation,</span> <span class="hljs-string">Inc.</span>
<span class="hljs-string">This</span> <span class="hljs-string">program</span> <span class="hljs-string">is</span> <span class="hljs-string">free</span> <span class="hljs-string">software;</span> <span class="hljs-string">you</span> <span class="hljs-string">may</span> <span class="hljs-string">redistribute</span> <span class="hljs-string">it</span> <span class="hljs-string">under</span> <span class="hljs-string">the</span> <span class="hljs-string">terms</span> <span class="hljs-string">of</span>
<span class="hljs-string">the</span> <span class="hljs-string">GNU</span> <span class="hljs-string">General</span> <span class="hljs-string">Public</span> <span class="hljs-string">License</span> <span class="hljs-string">version</span> <span class="hljs-number">3</span> <span class="hljs-string">or</span> <span class="hljs-string">later.</span>
<span class="hljs-string">This</span> <span class="hljs-string">program</span> <span class="hljs-string">has</span> <span class="hljs-string">absolutely</span> <span class="hljs-literal">no</span> <span class="hljs-string">warranty.</span>
<span class="hljs-string">This</span> <span class="hljs-string">assembler</span> <span class="hljs-string">was</span> <span class="hljs-string">configured</span> <span class="hljs-string">for</span> <span class="hljs-string">a</span> <span class="hljs-string">target</span> <span class="hljs-string">of</span> <span class="hljs-string">`x86_64-linux-gnu'.</span>

<span class="hljs-string">$</span> <span class="hljs-string">ld</span> <span class="hljs-string">--version</span>

<span class="hljs-string">GNU</span> <span class="hljs-string">ld</span> <span class="hljs-string">(GNU</span> <span class="hljs-string">Binutils</span> <span class="hljs-string">for</span> <span class="hljs-string">Ubuntu)</span> <span class="hljs-number">2.38</span>
<span class="hljs-string">Copyright</span> <span class="hljs-string">(C)</span> <span class="hljs-number">2022 </span><span class="hljs-string">Free</span> <span class="hljs-string">Software</span> <span class="hljs-string">Foundation,</span> <span class="hljs-string">Inc.</span>
<span class="hljs-string">This</span> <span class="hljs-string">program</span> <span class="hljs-string">is</span> <span class="hljs-string">free</span> <span class="hljs-string">software;</span> <span class="hljs-string">you</span> <span class="hljs-string">may</span> <span class="hljs-string">redistribute</span> <span class="hljs-string">it</span> <span class="hljs-string">under</span> <span class="hljs-string">the</span> <span class="hljs-string">terms</span> <span class="hljs-string">of</span>
<span class="hljs-string">the</span> <span class="hljs-string">GNU</span> <span class="hljs-string">General</span> <span class="hljs-string">Public</span> <span class="hljs-string">License</span> <span class="hljs-string">version</span> <span class="hljs-number">3</span> <span class="hljs-string">or</span> <span class="hljs-string">(at</span> <span class="hljs-string">your</span> <span class="hljs-string">option)</span> <span class="hljs-string">a</span> <span class="hljs-string">later</span> <span class="hljs-string">version.</span>
<span class="hljs-string">This</span> <span class="hljs-string">program</span> <span class="hljs-string">has</span> <span class="hljs-string">absolutely</span> <span class="hljs-literal">no</span> <span class="hljs-string">warranty.</span>
</code></pre><p>You're practically set. Now how to start writing Hello World in assembly? Well let's break down what constitutes a hello world program.</p>
<ol>
<li>You'd need somewhere to save information about the string <code>"Hello, World!"</code>.</li>
<li>You'd need a place and way to print that string to screen.</li>
<li>And last but not least, you'd need a way to <strong>exit</strong> the program.</li>
</ol>
<p>Number (3) is particularly important because as high level language programmer you may never thinks about it. A program should quit, du-uh... But if we're dealing with machine here, it needs to be told to quit and return to operating system. Let's break it down one by one.</p>
<h2 id="heading-prerequisite-and-entry-point">Prerequisite and Entry Point.</h2>
<p> So let's fire up your favourite text editor and write these line of codes to a file, e.g. <code>hello.s</code></p>
<pre><code class="lang-asm">.code64
.section .rodata

.section .text
.global _start 
_start:
</code></pre>
<p>I'll explain as we go. <code>_start</code> is what we called the <strong>entry point</strong>. The code which an operating system will execute first after loading it to memory. <code>.code64</code> is a <em>directive</em>. It's like keyword and it means that we want to target an x86_64 architecture.</p>
<h2 id="heading-a-place-to-save-hello-world-information">A place to save "Hello World" information</h2>
<p>Linux uses ELF as its executable format.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651464712911/m-L5Qu_8P.webp" alt="Lord-of-the-Rings-Galadriel-Legolas-Elrond.webp" /></p>
<p>Just kidding, not that ELF but this ELF: <a target="_blank" href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format">Executable and Linkable Format</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651464779960/pISGer44P.png" alt="elf-view.png" /></p>
<p>In short, ELF file consists of several sections. Those sections is defined within the assembly file. The place to place static information, like <code>"Hello, World1"</code> is a section called <code>.rodata</code> or <strong>Read Only Data</strong>. Pretty self explanatory. That's the <code>.rodata</code> on our previous code means. So let's type in our string below the <code>section .rodata</code>. And because we're dealing with ASCII characters we use <code>.ascii</code> directive.</p>
<pre><code class="lang-asm">.section .rodata
msg: .ascii "Hello, World!\n"
.set msglen, (. - msg)
</code></pre>
<p>Another thing that we'll need is the length of the string. To do that, we can hard-code the length, or use directive. <code>set</code> directive will assign a <em>symbol</em> to a value. This symbol is available at compile time only. The last line means that we set msglen equals substraction of current position <code>.</code> to the position of <code>msg</code> which will result to the length of the <code>msg</code>. Pretty neat. We're done defining place for "Hello, World!"</p>
<h2 id="heading-a-place-and-a-way-to-write-the-string">A place and a way to write the string.</h2>
<p>In Linux, the output terminal is represented by <code>stdout</code> or <em>standard output</em> with file number of <code>1</code>. You can look it up by using command <code>man stdout</code> or from <a target="_blank" href="https://man7.org/linux/man-pages/man3/stdout.3.html">this page</a> on 5th paragraph.</p>
<blockquote>
<p>On program startup, the integer file descriptors associated with the streams stdin, stdout, and stderr are 0, 1, and 2, respectively. </p>
</blockquote>
<p>What we should do is just write to that "file". To do that, we can use <code>write</code> system call. But how we invoke write? Every system call has a number, and it turns out <code>write</code> has <code>1</code> as the system call number. You can see the on <a target="_blank" href="https://filippo.io/linux-syscall-table/">Filippo's system call table</a>. The C signature for this system call is as follows:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">ssize_t</span> <span class="hljs-title">write</span><span class="hljs-params">(<span class="hljs-keyword">int</span> fd, <span class="hljs-keyword">const</span> <span class="hljs-keyword">void</span> *buf, <span class="hljs-keyword">size_t</span> count)</span></span>;
</code></pre>
<p>To invoke the system call we're using <code>SYSCALL</code> instruction. But before that, we'd need to put the system call number in <code>rax</code> register. In AT&amp;T syntax that's used by GNU Assembler it's like this:</p>
<pre><code class="lang-asm">mov $1, %rax
</code></pre>
<p>A constant in AT&amp;T syntax is prefixed by <code>$</code> and a register name is prefixed by <code>%</code>. So it means that move a constant <code>1</code> to register <code>rax</code>. That's our first instruction and put below <code>.section .text</code> </p>
<p>Alright, and lastly, we'd need to know how to invoke the system calls? Well that's what Application Binary Interfaces designed to do. It specifies a way to call function. <a target="_blank" href="https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions">Wikipedia</a> says that 1st to 6th parameters are passed to <code>RDI</code>, <code>RSI</code>, <code>RDX</code>, <code>RCX</code>, <code>R8</code>, <code>R9</code> respectively. So we passed them like this:</p>
<ol>
<li><code>fd</code> is the file descriptor we pass stdout which is <code>1</code>. That goes to <code>rdi</code>.</li>
<li><code>buf</code> is the address, we pass <code>msg</code>. That goes to <code>rsi</code>. This uses special instruction <code>lea</code> which allows us to load an address to a register.</li>
<li>And lastly, we pass the length <code>msglen</code> to <code>rdx</code> is it's the register holding the 3rd parameter. It's a constant so we prefix that with dollar sign.</li>
</ol>
<p>and then we call <code>SYSCALL</code> instruction.</p>
<pre><code class="lang-asm">mov $1, %rdi 
lea msg, %rsi 
mov $msglen, %rdx
syscall
</code></pre>
<p>That'll write the message to the standard out. And with the same analogy we call <code>exit</code> with syscall number 60 with an exit code of <code>0</code> (success) to terminate the program.</p>
<pre><code class="lang-asm">mov $60, %rax
mov $0, %rdi 
syscall
</code></pre>
<p>So, there, we finished source code. Let's name it <code>hello.s</code></p>
<pre><code class="lang-asm">.code64
.section .rodata
msg: .ascii "Hello, World!\n"
.set msglen, (. - msg)

.section .text 
.global _start
_start:
  mov $1, %rax
  mov $1, %rdi 
  lea msg, %rsi 
  mov $msglen, %rdx
  syscall

  mov $60, %rax
  mov $0, %rdi 
  syscall
</code></pre>
<p>And then we assemble and link using the tools we have installed.</p>
<pre><code class="lang-bash">as -o hello.o -s hello.s

ld -o hello hello.o
</code></pre>
<p>You can execute the binary:</p>
<pre><code class="lang-bash">./hello

Hello, World!
</code></pre>
<h1 id="heading-macos">macOS</h1>
<p>On macOS, all of those tools are included within Xcode and Command Line Tools for Xcode. It'll install <a target="_blank" href="https://llvm.org/">LLVM</a> based tooling. Open terminal and test if you have it installed.</p>
<p><em>Notes: This is only tested on macOS with Intel chip. I didn't test this on Apple Silicon</em></p>
<pre><code>$ <span class="hljs-keyword">as</span> <span class="hljs-operator">-</span><span class="hljs-operator">-</span>version
Apple clang version <span class="hljs-number">13.1</span><span class="hljs-number">.6</span> (clang<span class="hljs-number">-1316.0</span><span class="hljs-number">.21</span><span class="hljs-number">.2</span><span class="hljs-number">.3</span>)
Target: x86_64<span class="hljs-operator">-</span>apple<span class="hljs-operator">-</span>darwin21<span class="hljs-number">.4</span><span class="hljs-number">.0</span>
Thread model: posix
InstalledDir: <span class="hljs-operator">/</span>Applications<span class="hljs-operator">/</span>Xcode.app/Contents<span class="hljs-operator">/</span>Developer<span class="hljs-operator">/</span>Toolchains<span class="hljs-operator">/</span>XcodeDefault.xctoolchain/usr<span class="hljs-operator">/</span>bin

$ ld <span class="hljs-operator">-</span><span class="hljs-operator">-</span>help
ld64: For information on command line options please use <span class="hljs-string">'man ld'</span>.
</code></pre><p>If you see those messages, it means that you're ready to write code. Open up your favourite text editor and type these commands. </p>
<h2 id="heading-the-code-and-differences-with-linux">The code and differences with Linux</h2>
<p>The code is similar to linux in a way you call syscall and suff with some changes in syntax and syscall number. Let's see:</p>
<pre><code class="lang-asm">.code64
.global _main
.static_data
msg: .ascii "Hello, World!\n"
.set msglen, (. - msg)
.text
_main:
    mov $0x2000004, %rax 
    mov $1, %rdi 
    lea msg(%rip), %rsi 
    mov $msglen, %rdx
    syscall 
    mov $0x2000001, %rax 
    xor %rdi, %rdi 
    syscall
</code></pre>
<ol>
<li>The first one we notice is the <em>entry point</em>. Instead of <code>_start</code>, we have <code>_main</code>.</li>
<li>Read only data section is marked with <code>.static_data</code>. It's difference between GNU assembler and Apple's LLVM assembler. Another difference is text section is simply marked as <code>.text</code> instead of <code>.section .text</code>.</li>
<li>The <code>msg</code> should be loaded with relative location to <code>RIP</code> (instruction pointer register).</li>
<li>The <code>write</code> system call is numbered <code>0x2000004</code> instead of <code>1</code>. The real system call is <code>4</code> as shown here https://github.com/opensource-apple/xnu/blob/master/bsd/kern/syscalls.master but you'd need to add <code>0x2000000</code> to signify it's BSD system call instead of Mach.</li>
<li>The <code>exit</code> system call is numbered <code>1</code> and prefixed with <code>0x20000000</code></li>
</ol>
<h2 id="heading-assembly-and-executing">Assembly and Executing</h2>
<p>Assembling and executing is similar to Linux with some additional parameters:</p>
<pre><code><span class="hljs-keyword">as</span> <span class="hljs-operator">-</span>arch x86_64 hello.s <span class="hljs-operator">-</span>o hello.o
ld <span class="hljs-operator">-</span>arch x86_64  \ 
<span class="hljs-operator">-</span>L <span class="hljs-operator">/</span>Library<span class="hljs-operator">/</span>Developer<span class="hljs-operator">/</span>CommandLineTools<span class="hljs-operator">/</span>SDKs<span class="hljs-operator">/</span>MacOSX.sdk/usr<span class="hljs-operator">/</span>lib  \
<span class="hljs-operator">-</span>lSystem <span class="hljs-operator">-</span>o hello hello.o

./hello
</code></pre><p>The first command is similar we just add <code>-arch x86_64</code> to signify our target architecture. This is because LLVM is a cross compiler by default and can target multiple architecture.</p>
<p>The last one other than architecture we add directory and the library we want to link with:  <code>-L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib  -lSystem</code> means that we want to link to <code>libSystem</code> which is mandatory in macOS.</p>
<h1 id="heading-wrap-up">Wrap Up</h1>
<p>That's how you do assembly in 2022 in full-blown 64-bit modern operating systems.I purposedly left Windows out because Windows is little <em>unique</em> in this regard. Stay tuned and I'll write about writing a Hello World in Windows with Assembly.</p>
]]></content:encoded></item></channel></rss>