<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Linux on bitstream!</title>
    <link>https://bitstream.systems/tags/linux/</link>
    <description>Recent content in Linux on bitstream!</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Thu, 30 Apr 2026 16:54:17 +0000</lastBuildDate><atom:link href="https://bitstream.systems/tags/linux/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Web Server in ARM64 Assembly</title>
      <link>https://bitstream.systems/posts/webserver_arm64/</link>
      <pubDate>Thu, 30 Apr 2026 16:54:17 +0000</pubDate>
      
      <guid>https://bitstream.systems/posts/webserver_arm64/</guid>
      <description>&lt;h1 id=&#34;writing-a-web-server-in-arm64-assembly&#34;&gt;Writing a Web Server in ARM64 Assembly&lt;/h1&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this post, we are going to learn ARM64 assembly the hard way: by writing a basic web server in assembly for Linux systems. If this seems long or intimidating, don&amp;rsquo;t worry we&amp;rsquo;ll start with the basics and work our way up to the web server, explaining every step.&lt;/p&gt;
&lt;h2 id=&#34;syscalls&#34;&gt;Syscalls&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Syscalls&lt;/strong&gt; are how user-space programs interact with the kernel. They are the interface between your application and the operating system, allowing you to perform operations like reading and writing files, creating processes, and interacting with hardware.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;writing-a-web-server-in-arm64-assembly&#34;&gt;Writing a Web Server in ARM64 Assembly&lt;/h1&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this post, we are going to learn ARM64 assembly the hard way: by writing a basic web server in assembly for Linux systems. If this seems long or intimidating, don&amp;rsquo;t worry we&amp;rsquo;ll start with the basics and work our way up to the web server, explaining every step.&lt;/p&gt;
&lt;h2 id=&#34;syscalls&#34;&gt;Syscalls&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Syscalls&lt;/strong&gt; are how user-space programs interact with the kernel. They are the interface between your application and the operating system, allowing you to perform operations like reading and writing files, creating processes, and interacting with hardware.&lt;/p&gt;
&lt;div align=&#34;center&#34; class=&#34;mermaid&#34;&gt;
  
graph LR
  Application--&gt;|syscall|Kernel
  Kernel--&gt;|return|Application

&lt;/div&gt;

&lt;p&gt;For example, to print something to the console without using &lt;code&gt;printf&lt;/code&gt;, you use the write syscall:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;write&lt;/span&gt;(fd, buffer, size);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fd&lt;/code&gt;: file descriptor (1 for stdout)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;buffer&lt;/code&gt;: the string to print&lt;/li&gt;
&lt;li&gt;&lt;code&gt;size&lt;/code&gt;: length of the string&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can find syscall arguments in the Linux manual. For example, run &lt;code&gt;man 2 write&lt;/code&gt; to see the arguments for the &lt;code&gt;write&lt;/code&gt; syscall.&lt;/p&gt;
&lt;p&gt;Other syscalls essential for network programming (and for our web server) include &lt;code&gt;socket&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;, &lt;code&gt;listen&lt;/code&gt;, &lt;code&gt;accept&lt;/code&gt;, and &lt;code&gt;send&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;hello-world-in-c-using-syscalls&#34;&gt;Hello World in C Using Syscalls&lt;/h2&gt;
&lt;p&gt;Most beginners use &lt;code&gt;printf&lt;/code&gt; in C:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello, World!&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But &lt;code&gt;printf&lt;/code&gt; is just a wrapper around the &lt;code&gt;write&lt;/code&gt; syscall. You can use &lt;code&gt;write&lt;/code&gt; directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;message &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello, World!&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, message, &lt;span style=&#34;color:#ae81ff&#34;&gt;14&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// 1 is stdout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here, 1 is the file descriptor for &lt;code&gt;stdout&lt;/code&gt;, &lt;code&gt;message&lt;/code&gt; is the string, and 14 is the length (including the newline).&lt;/p&gt;
&lt;h2 id=&#34;arm-architecture-basics&#34;&gt;ARM Architecture Basics&lt;/h2&gt;
&lt;p&gt;Before writing assembly, you need to understand ARM64 basics. ARM64 is a 64-bit architecture, so it has 64-bit wide registers and can address more memory than 32-bit architectures.&lt;/p&gt;
&lt;h3 id=&#34;registers&#34;&gt;Registers&lt;/h3&gt;
&lt;p&gt;There are 31 general-purpose registers: &lt;code&gt;x0&lt;/code&gt; to &lt;code&gt;x30&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x0&lt;/code&gt; to &lt;code&gt;x7&lt;/code&gt;: used for passing arguments and returning values&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x8&lt;/code&gt; to &lt;code&gt;x15&lt;/code&gt;: general-purpose&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x19&lt;/code&gt; to &lt;code&gt;x28&lt;/code&gt;: callee-saved (persistent)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x29&lt;/code&gt;: frame pointer (FP)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x30&lt;/code&gt;: link register (LR)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xzr&lt;/code&gt;: zero register (always 0)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The lower 32 bits of each register are accessible as &lt;code&gt;w0&lt;/code&gt; to &lt;code&gt;w30&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;memory-and-pages&#34;&gt;Memory and Pages&lt;/h3&gt;
&lt;p&gt;Linux uses virtual memory. Each process has its own virtual address space, and the kernel maps virtual to physical addresses. Memory is divided into pages (usually 4KB). You never deal with physical memory directly.&lt;/p&gt;
&lt;h3 id=&#34;using-the-stack&#34;&gt;Using the Stack&lt;/h3&gt;
&lt;p&gt;The stack is used for local variables and passing arguments. It grows downward. The &lt;code&gt;sp&lt;/code&gt; (stack pointer) register points to the top of the stack. You use the stack to save register values, store local variables, and keep return addresses.&lt;/p&gt;
&lt;h3 id=&#34;register-conventions-and-common-instructions&#34;&gt;Register Conventions and Common Instructions&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Register(s)&lt;/th&gt;
          &lt;th&gt;Purpose&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;x0–x7&lt;/td&gt;
          &lt;td&gt;Arguments/Results&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;x9–x15&lt;/td&gt;
          &lt;td&gt;Caller-saved (temporary)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;x19–x28&lt;/td&gt;
          &lt;td&gt;Callee-saved (persistent)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;x29&lt;/td&gt;
          &lt;td&gt;Frame Pointer (FP)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;x30&lt;/td&gt;
          &lt;td&gt;Link Register (LR)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;xzr&lt;/td&gt;
          &lt;td&gt;Zero Register&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Common instructions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ldr&lt;/code&gt;: load from memory&lt;/li&gt;
&lt;li&gt;&lt;code&gt;str&lt;/code&gt;: store to memory&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mov&lt;/code&gt;: move value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bl&lt;/code&gt;: branch with link (call)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svc&lt;/code&gt;: supervisor call (syscall)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ret&lt;/code&gt;: return&lt;/li&gt;
&lt;li&gt;&lt;code&gt;add&lt;/code&gt;: add values&lt;/li&gt;
&lt;li&gt;&lt;code&gt;adrp&lt;/code&gt;: address of page&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;sections&#34;&gt;Sections&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.text&lt;/code&gt;: code&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.data&lt;/code&gt;: initialized data&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.bss&lt;/code&gt;: uninitialized data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;.data
helloworld:
    .ascii &amp;#34;Hello, ARM64!\n&amp;#34;
helloworld_len = . - helloworld
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;hello-world-in-arm64-assembly-using-syscalls&#34;&gt;Hello World in ARM64 Assembly Using Syscalls&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;.data
helloworld:
    .ascii &amp;#34;Hello, ARM64!\n&amp;#34;
helloworld_len = . - helloworld

.text
.globl _start
_start:
    mov x0, #1              // fd = stdout
    ldr x1, =helloworld     // buf
    ldr x2, =helloworld_len // count
    mov w8, #64             // write syscall
    svc #0

    mov x0, #0
    mov w8, #93             // exit syscall
    svc #0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Arguments are passed in x0–x7. The syscall number goes in w8. These numbers are architecture-specific (see the syscall table below).&lt;/p&gt;
&lt;h2 id=&#34;compiling-arm64-assembly&#34;&gt;Compiling ARM64 Assembly&lt;/h2&gt;
&lt;p&gt;Use &lt;code&gt;as&lt;/code&gt; and &lt;code&gt;ld&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;as -o hello.o hello.s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ld -o hello hello.o
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or use &lt;code&gt;gcc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gcc -o hello hello.s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./hello
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;debugging-with-gdb&#34;&gt;Debugging with GDB&lt;/h2&gt;
&lt;p&gt;GDB lets you set breakpoints and inspect registers/memory:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gdb ./hello
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; break _start
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; tui enable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; info registers
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gdb&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; print/x $x0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;web-server-in-c&#34;&gt;Web Server in C&lt;/h2&gt;
&lt;p&gt;A simple TCP server in C:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;arpa/inet.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; server_fd, client_fd;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr_in address;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; addrlen &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(address);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;response &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;HTTP/1.1 200 OK&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Content-Type: text/plain&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Content-Length: 12&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Hello Libc!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    server_fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;socket&lt;/span&gt;(AF_INET, SOCK_STREAM, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    address.sin_family &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; AF_INET;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    address.sin_addr.s_addr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; INADDR_ANY;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    address.sin_port &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;htons&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;8080&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; opt &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;setsockopt&lt;/span&gt;(server_fd, SOL_SOCKET, SO_REUSEADDR, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;opt, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(opt));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;bind&lt;/span&gt;(server_fd, (&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;address, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(address));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;listen&lt;/span&gt;(server_fd, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        client_fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;accept&lt;/span&gt;(server_fd, (&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;address, (&lt;span style=&#34;color:#66d9ef&#34;&gt;socklen_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;addrlen);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; buffer[&lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;read&lt;/span&gt;(client_fd, buffer, &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;send&lt;/span&gt;(client_fd, response, &lt;span style=&#34;color:#a6e22e&#34;&gt;strlen&lt;/span&gt;(response), &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&gt;(client_fd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This server creates a socket, binds to a port, listens, accepts connections, reads requests, sends responses, and closes connections.&lt;/p&gt;
&lt;h3 id=&#34;syscalls-used-in-the-web-server&#34;&gt;Syscalls Used in the Web Server&lt;/h3&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Syscall&lt;/th&gt;
          &lt;th&gt;Purpose&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;socket&lt;/td&gt;
          &lt;td&gt;Create a TCP socket&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;setsockopt&lt;/td&gt;
          &lt;td&gt;Set socket options (e.g., SO_REUSEADDR)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;bind&lt;/td&gt;
          &lt;td&gt;Bind socket to address/port&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;listen&lt;/td&gt;
          &lt;td&gt;Listen for incoming connections&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;accept&lt;/td&gt;
          &lt;td&gt;Accept a new connection&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;read&lt;/td&gt;
          &lt;td&gt;Read data from client&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;send&lt;/td&gt;
          &lt;td&gt;Send data to client&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;close&lt;/td&gt;
          &lt;td&gt;Close client connection&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;exit&lt;/td&gt;
          &lt;td&gt;Exit on error&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;All these are syscalls provided by the kernel. We can implement the same logic in ARM64 assembly.&lt;/p&gt;
&lt;h2 id=&#34;http-response-format&#34;&gt;HTTP Response Format&lt;/h2&gt;
&lt;p&gt;A minimal HTTP response:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 12

Hello Libc!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is the minimum for a valid HTTP response: status line, headers, blank line, and body.&lt;/p&gt;
&lt;h2 id=&#34;syscall-table-for-arm64&#34;&gt;Syscall Table for ARM64&lt;/h2&gt;
&lt;p&gt;Reference: &lt;a href=&#34;https://arm64.syscall.sh/&#34;&gt;https://arm64.syscall.sh/&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Syscall&lt;/th&gt;
          &lt;th&gt;Number&lt;/th&gt;
          &lt;th&gt;Arguments (x0, x1, x2, &amp;hellip;)&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;socket&lt;/td&gt;
          &lt;td&gt;198&lt;/td&gt;
          &lt;td&gt;domain, type, protocol&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;bind&lt;/td&gt;
          &lt;td&gt;200&lt;/td&gt;
          &lt;td&gt;fd, addr*, addrlen&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;listen&lt;/td&gt;
          &lt;td&gt;201&lt;/td&gt;
          &lt;td&gt;fd, backlog&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;accept&lt;/td&gt;
          &lt;td&gt;202&lt;/td&gt;
          &lt;td&gt;fd, addr*, addrlen*&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;sendto/send&lt;/td&gt;
          &lt;td&gt;206&lt;/td&gt;
          &lt;td&gt;fd, buf, len, flags, dest_addr*, addrlen&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;setsockopt&lt;/td&gt;
          &lt;td&gt;208&lt;/td&gt;
          &lt;td&gt;fd, level, optname, optval*, optlen&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;read&lt;/td&gt;
          &lt;td&gt;63&lt;/td&gt;
          &lt;td&gt;fd, buf, count&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;write&lt;/td&gt;
          &lt;td&gt;64&lt;/td&gt;
          &lt;td&gt;fd, buf, count&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;close&lt;/td&gt;
          &lt;td&gt;57&lt;/td&gt;
          &lt;td&gt;fd&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;defining-global-strings-and-structs&#34;&gt;Defining Global Strings and Structs&lt;/h2&gt;
&lt;p&gt;Define error messages and HTTP payload in &lt;code&gt;.data&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;.data
payload:
    .ascii &amp;#34;HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 16\n\nHello from ARM!\n&amp;#34;
payload_len = . - payload
socket_err:
    .ascii &amp;#34;socket failed\n&amp;#34;
socket_err_len = . - socket_err
// ... (other error messages)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Define &lt;code&gt;sockaddr_in&lt;/code&gt; struct:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;.align 4
sockaddr_in:
    .hword 2          // AF_INET
    .hword 0x901f     // port 8080 in network byte order (big-endian)
    .word 0x0100007f  // 127.0.0.1
    .zero 8           // padding
sockaddr_in_len:
    .word 16
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;Note: 0x8080 is represented as 0x1f90 in hex, but in big-endian as 0x901f. Network traffic is always big-endian, even on little-endian machines. This replaces the need for &lt;code&gt;htons&lt;/code&gt; in C.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Same applies for the IP defined in the word just bellow &lt;code&gt;7f 00 00 01&lt;/code&gt; matches the &lt;code&gt;127.0.0.1&lt;/code&gt; but since we are representing in big-endian it stays &lt;code&gt;01 00 00 7f&lt;/code&gt;. Allowing only this IP to connect to the socket.&lt;/p&gt;
&lt;h2 id=&#34;storing-the-server-fd-in-memory&#34;&gt;Storing the Server FD in Memory&lt;/h2&gt;
&lt;p&gt;To store the server file descriptor in memory (for educational purposes):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;server_fd:
    .skip 4 // 4 bytes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To save the value:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;adrp x1, server_fd
add  x1, x1, :lo12:server_fd
str  w0, [x1]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To load it back:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;adrp x1, server_fd
add  x1, x1, :lo12:server_fd
ldr  w0, [x1]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can actually also do this with a pseudo instruction like the one we used in the hello world program and in the strings.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;ldr x1, =server_fd // Load the address
ldr w0, [x1] // Load to the register
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;=&lt;/code&gt; is actually a pseudo instruction that does the &lt;code&gt;adrp&lt;/code&gt; and &lt;code&gt;add&lt;/code&gt; combo.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;writing-the-syscalls&#34;&gt;Writing the Syscalls&lt;/h2&gt;
&lt;p&gt;Each syscall routine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Put arguments in registers&lt;/li&gt;
&lt;li&gt;Set syscall number in w8&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;svc #0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;socket:
    mov x0, #2
    mov x1, #1
    mov x2, #0
    mov w8, #198
    svc #0
    ret
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For syscalls needing pointers to global data, use &lt;code&gt;adrp&lt;/code&gt; and &lt;code&gt;add :lo12:&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;main-routine&#34;&gt;Main Routine&lt;/h2&gt;
&lt;p&gt;The main routine calls each step and checks for errors:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;.text
.globl _start
_start:
    bl  socket
    ldr x1, =socket_err
    ldr x2, =socket_err_len
    bl  err_check
    adrp x1, server_fd
    add  x1, x1, :lo12:server_fd
    str  w0, [x1]
    bl  setsockopt
    ldr x1, =setsockopt_err
    ldr x2, =setsockopt_err_len
    bl  err_check
    bl  bind
    ldr x1, =bind_err
    ldr x2, =bind_err_len
    bl  err_check
    bl  listen
    ldr x1, =listen_err
    ldr x2, =listen_err_len
    bl  err_check
    sub sp, sp, #1040
    stp x29, x30, [sp]
    mov x29, sp
    bl  loop
    bl  exit
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;the-loop&#34;&gt;The Loop&lt;/h2&gt;
&lt;p&gt;The loop accepts connections, reads requests, writes the buffer, sends the response, and closes the connection:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;loop:
    bl  accept
    ldr x1, =accept_err
    ldr x2, =accept_err_len
    bl  err_check
    mov w19, w0
    mov x1, sp
    mov x2, #1040
    bl  read
    ldr x1, =read_err
    ldr x2, =read_err_len
    bl  err_check
    bl  write
    ldr x1, =write_err
    ldr x2, =write_err_len
    bl  err_check
    bl  send
    ldr x1, =send_err
    ldr x2, =send_err_len
    bl  err_check
    bl  close
    ldr x1, =close_err
    ldr x2, =close_err_len
    bl  err_check
    b   loop
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;buffer-and-stack&#34;&gt;Buffer and Stack&lt;/h2&gt;
&lt;p&gt;We allocate 1040 bytes on the stack (1024 + 16 for alignment) for the request buffer:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;sub sp, sp, #1040
stp x29, x30, [sp]
mov x29, sp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is like &lt;code&gt;char buffer[1040];&lt;/code&gt; in C.&lt;/p&gt;
&lt;h2 id=&#34;full-code&#34;&gt;Full code&lt;/h2&gt;
&lt;p&gt;The full code should look like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-assembly&#34; data-lang=&#34;assembly&#34;&gt;.data

// Defining the address struct
.align 4

sockaddr_in:
	.hword 2
	.hword 0x901f
	.word  0x0100007f // Change to 0x0 to accept any connections
	.zero  8

sockaddr_in_len:
	.word 16

payload:
	.ascii &amp;#34;HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 16\n\nHello from ARM!\n&amp;#34;
	payload_len = . - payload

socket_err:
	.ascii &amp;#34;socket failed\n&amp;#34;
	socket_err_len = . - socket_err

setsockopt_err:
	.ascii &amp;#34;setsockopt failed\n&amp;#34;
	setsockopt_err_len = . - setsockopt_err

bind_err:
	.ascii &amp;#34;bind failed\n&amp;#34;
	bind_err_len = . - bind_err

listen_err:
	.ascii &amp;#34;listen failed\n&amp;#34;
	listen_err_len = . - listen_err

accept_err:
	.ascii &amp;#34;accept failed\n&amp;#34;
	accept_err_len = . - accept_err

read_err:
	.ascii &amp;#34;read failed\n&amp;#34;
	read_err_len = . - read_err

write_err:
	.ascii &amp;#34;write failed\n&amp;#34;
	write_err_len = . - write_err

send_err:
	.ascii &amp;#34;send failed\n&amp;#34;
	send_err_len = . - send_err

close_err:
	.ascii &amp;#34;close failed\n&amp;#34;
	close_err_len = . - close_err

	// Here we store uninitialize memory
	.section .bss
	.align   2

server_fd:
	.skip 4 // 4 bytes

	.text
	.globl _start

_start:
	bl  socket
	ldr x1, =socket_err
	ldr x2, =socket_err_len
	bl  err_check

	// Save server_fd in memory
	adrp x1, server_fd
	add  x1, x1, :lo12:server_fd
	str  w0, [x1]

	bl  setsockopt
	ldr x1, =setsockopt_err
	ldr x2, =setsockopt_err_len
	bl  err_check

	bl  bind
	ldr x1, =bind_err
	ldr x2, =bind_err_len
	bl  err_check

	bl  listen
	ldr x1, =listen_err
	ldr x2, =listen_err_len
	bl  err_check

	// Define a buffer on the stack (1040 = 1024 + 16 for alignment)
	// x29 holds the previous pointer
	sub sp, sp, #1040
	stp x29, x30, [sp]
	mov x29, sp
	bl  loop

	bl exit

loop:
	bl  accept
	ldr x1, =accept_err
	ldr x2, =accept_err_len
	bl  err_check

	// Store client_fd in w19
	mov w19, w0

	// Create buffer from read()
	mov x1, sp
	mov x2, #1040

	// Read client_fd
	bl  read
	ldr x1, =read_err
	ldr x2, =read_err_len
	bl  err_check

	// Write the buffer
	bl  write
	ldr x1, =write_err
	ldr x2, =write_err_len
	bl  err_check

	// Send response
	bl  send
	ldr x1, =send_err
	ldr x2, =send_err_len
	bl  err_check

	// Close connection
	bl  close
	ldr x1, =close_err
	ldr x2, =close_err_len
	bl  err_check
	b   loop

socket:
	mov x0, #2
	mov x1, #1
	mov x2, #0
	mov w8, #198
	svc #0
	ret

setsockopt:
	// Get fd from memory
	adrp x1, server_fd
	add  x1, x1, :lo12:server_fd
	ldr  w0, [x1]

	mov w1, #0x1 // SOL_SOCKET
	mov w2, #0x2 // SO_REUSEADDR

	mov w20, #1          // Needs to be a pointer (&amp;amp;opt)
	str w20, [sp, #-16]!
	mov x3, sp
	mov x4, #4           // 32 bits - 4 bytes

	mov w8, #208
	svc #0

	add sp, sp, #16 // Return stack
	ret

bind:
	// Get fd from memory
	adrp x1, server_fd
	add  x1, x1, :lo12:server_fd
	ldr  w0, [x1]

	ldr x1, =sockaddr_in
	ldr x2, =sockaddr_in_len
	ldr w2, [x2]

	mov w8, #200
	svc #0
	ret

listen:
	// Get fd from memory
	adrp x1, server_fd
	add  x1, x1, :lo12:server_fd
	ldr  w0, [x1]

	mov x1, #3
	mov w8, #201
	svc #0
	ret

accept:
	// Get fd from memory
	adrp x1, server_fd
	add  x1, x1, :lo12:server_fd
	ldr  w0, [x1]

	ldr  x1, =sockaddr_in
	adrp x2, sockaddr_in_len           // adrp only loads top bits (page)
	add  x2, x2, :lo12:sockaddr_in_len // (so we need to add the last 12 as offset)

	mov w8, #202
	svc #0
	ret

read:
	mov w0, w19
	mov x1, sp
	mov x2, #1040

	mov w8, #63
	svc #0
	ret

write:
	mov w0, #1
	mov x1, sp
	mov x2, #1040

	mov w8, #64
	svc #0
	ret

send:
	mov w0, w19
	ldr x1, =payload
	mov x2, payload_len

	// Clear old values from args since we don&amp;#39;t need them.
	mov x3, #0 // flags
	mov x4, #0 // dest_addr (NULL)
	mov x5, #0 // addrlen (0)

	mov w8, #206
	svc #0
	ret

close:
	mov w0, w19
	mov w8, #57
	svc #0
	ret

err_check:
	cmp  x0, #0
	b.lt err_handler
	ret

err_handler:
# Write to stderr
mov w0, #2
mov w8, #64
svc #0
bl  exit    // Call exit

exit:
	mov x0, #0
	mov w8, #93
	svc #0
	ret
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;testing&#34;&gt;Testing&lt;/h2&gt;
&lt;p&gt;Build and run the program on an ARM64 Linux system or emulator. Test with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl localhost:8080
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;references&#34;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://syscalls.mebeim.net/?table=arm64/64/aarch64/latest&#34;&gt;https://syscalls.mebeim.net/?table=arm64/64/aarch64/latest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://arm64.syscall.sh/&#34;&gt;https://arm64.syscall.sh/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;RFC 2616 (HTTP/1.1)&lt;/li&gt;
&lt;li&gt;ARM64 Assembly Cheat Sheet&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
  </channel>
</rss>
