<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: William</title>
    <description>The latest articles on DEV Community by William (@willy1948).</description>
    <link>https://dev.to/willy1948</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3379916%2F10272090-1bf6-4f51-bdc9-1883ae2b5149.png</url>
      <title>DEV Community: William</title>
      <link>https://dev.to/willy1948</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/willy1948"/>
    <language>en</language>
    <item>
      <title>Guide to VBE graphics in x86</title>
      <dc:creator>William</dc:creator>
      <pubDate>Sun, 27 Jul 2025 19:25:29 +0000</pubDate>
      <link>https://dev.to/willy1948/guide-to-vbe-graphics-in-x86-5g2n</link>
      <guid>https://dev.to/willy1948/guide-to-vbe-graphics-in-x86-5g2n</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlr1m1eme2pnl1fd174f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlr1m1eme2pnl1fd174f.jpg" alt=" " width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Preface 📘
&lt;/h1&gt;

&lt;p&gt;This should act as your complete guide to implementing and understanding VBE graphics in x86 assembly, if you are unfamiliar with BIOS programming I recommend my article about making pong (&lt;a href="https://dev.to/willy1948/making-pong-in-x86-assembly-11li"&gt;https://dev.to/willy1948/making-pong-in-x86-assembly-11li&lt;/a&gt;). So, &lt;em&gt;what is VBE graphics?&lt;/em&gt; VBE (VESA bios extension) graphics is a standard that aims to improve upon VGA graphics which was created by IBM. What are the benefits of using VBE graphics? Well, the biggest benefit is the improvement in screen resolution. VGA at best gives you 320x200 whereas using VBE one can have up to 1280x1024. It's not just the resolution, but in certain video you can have up to 255^3 colours, compare that to just 255 for VGA. If you are looking to make a OS or just a bootloader game you should definitely consider using VBE graphics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;  &lt;span class="err"&gt;／＞　&lt;/span&gt; &lt;span class="err"&gt;フ&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="err"&gt;　&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="err"&gt;　&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
&lt;span class="err"&gt;／`&lt;/span&gt; &lt;span class="err"&gt;ミ＿&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="err"&gt;ノ&lt;/span&gt; 
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;　　　　&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;　&lt;/span&gt; &lt;span class="err"&gt;ヽ　　&lt;/span&gt; &lt;span class="err"&gt;ﾉ&lt;/span&gt;
&lt;span class="err"&gt;│　　&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;　&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;　&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;／￣&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;　　&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;　&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;￣ヽ＿&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="err"&gt;ヽ&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Setting the video mode 🎛️
&lt;/h1&gt;

&lt;p&gt;We need to tell BIOS that we want to use VBE graphics. luckily there exists an interrupt that we can call with specific arguments to do this. Using &lt;em&gt;int 0x10&lt;/em&gt; with &lt;em&gt;ax&lt;/em&gt; set to &lt;em&gt;0x4f02&lt;/em&gt; and &lt;em&gt;bx&lt;/em&gt; used to specify the video mode, (&lt;a href="https://en.wikipedia.org/wiki/INT_10H" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/INT_10H&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x4f02&lt;/span&gt; &lt;span class="c1"&gt;; code to set video mode&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;bx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x4118&lt;/span&gt; &lt;span class="c1"&gt;; specifies video + flags&lt;/span&gt;
&lt;span class="nf"&gt;int&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;
&lt;span class="nf"&gt;cmp&lt;/span&gt; &lt;span class="nb"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x4f&lt;/span&gt; &lt;span class="c1"&gt;;Check if video mode is supported by hardware&lt;/span&gt;
&lt;span class="nf"&gt;je&lt;/span&gt;  &lt;span class="nv"&gt;.successLabel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To understand what the &lt;em&gt;cmp&lt;/em&gt; line does we can look at the VBE specification document (&lt;a href="https://pdos.csail.mit.edu/6.828/2011/readings/hardware/vbe3.pdf" rel="noopener noreferrer"&gt;https://pdos.csail.mit.edu/6.828/2011/readings/hardware/vbe3.pdf&lt;/a&gt;).&lt;/p&gt;

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

&lt;p&gt;We want to check if the video mode in &lt;em&gt;bx&lt;/em&gt; is supported and therefore we check to see if &lt;em&gt;ax&lt;/em&gt; is &lt;em&gt;0x4f&lt;/em&gt;. I mentioned earlier that &lt;em&gt;bx&lt;/em&gt; stores the mode, this is partly true but it also stores flags which specify certain behaviours. &lt;/p&gt;

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

&lt;p&gt;It is a bit confusing but &lt;em&gt;D&lt;/em&gt; means bit number. Breaking down &lt;em&gt;0x4118&lt;/em&gt; into binary we get &lt;em&gt;0b|0|1|00|0|00|1|00011000|&lt;/em&gt; (I used | character to separate the different sections). Moving from left to right the sections are defined as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;0=clear display, 1=preserve display. This means weather or not what is in video memory will be cleared to black. Majority of the time it makes sense to clear the display when switching modes. Hence why the first bit is 0.&lt;/li&gt;
&lt;li&gt;0=Use banked frame buffer, 1=linear frame buffer. The reason this exists is because with 16 bits one can only address so much memory, even with segment offsets. Video memory could need up to 1280x1024x3 = 3,932,160 bytes, which is greater than 64kb. To get around this issue video card manufactures split up memory in &lt;em&gt;banks&lt;/em&gt;. Only one bank exists in memory at one time and one can switch to a particular bank through a BIOS call. Linear frame buffer is where the frame buffer is just stored as normal in memory. Because I am going to use 32 bit registers (this can be done in real mode), I am going to use a linear buffer. If you are developing for 16-bit retro hardware then you would need to set this bit to 0.&lt;/li&gt;
&lt;li&gt;Must be 0&lt;/li&gt;
&lt;li&gt;0=Uses BIOS default refresh rate, 1=Use user specified CRTC (Cathode ray tube controller). You may think, &lt;em&gt;well, I'm not using a CRT monitor.&lt;/em&gt; But you still specify values through the CRTC to control your up to date monitor. Using BIOS defaults will be fine. If you do want to specify the refresh rate, I believe you specify a pointer in &lt;em&gt;ES:DI&lt;/em&gt; to a CRTC information struct.&lt;/li&gt;
&lt;li&gt;Should be 0&lt;/li&gt;
&lt;li&gt;0=mode specifies VGA mode, 1=mode specifies super VGA mode. This should be set to 1 because we want access to higher resolutions that are available only in super VGA (super VGA is VBE). &lt;/li&gt;
&lt;li&gt;Specifies the video mode:
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bo2mul4muhlhlm32akg.png" alt=" " width="636" height="533"&gt;
Entry one has mode number of 0 and so on, this is a little unclear from the table. 7 bit mode number means that the 8th bit(zero indexed) is set to 0.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Great, using this information you should be able to run your program and it should show a bigger window than before. There are still some problems we need to fix. Firstly we don't know important information like where video memory is, and secondly we do not have enough address lines to write into all of video memory. Lets take a look at how to solve these issues.&lt;/p&gt;

&lt;h1&gt;
  
  
  Finding video memory 💾
&lt;/h1&gt;

&lt;p&gt;We can call a function that will give us all the information we need about the current mode. It takes a pointer to a struct and fills in all the information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x4F01&lt;/span&gt;       &lt;span class="c1"&gt;; VBE function 01h which returns mode info&lt;/span&gt;
&lt;span class="c1"&gt;; mode number (remember to include the 8th bit)&lt;/span&gt;
&lt;span class="c1"&gt;; cx is mode 5 with 8th bit set because we are using super VGA&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x105&lt;/span&gt;        
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;di&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;video_info&lt;/span&gt;   &lt;span class="c1"&gt;; pointer to structure&lt;/span&gt;
&lt;span class="nf"&gt;int&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we need to define the structure&lt;/p&gt;

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

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

&lt;p&gt;That's a bit of a pain to write out by hand so here is a text version with labels for the important attributes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;video_info:&lt;/span&gt;
    &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;     &lt;span class="c1"&gt;; ModeAttributes found on page 40 of VBE spec pdf&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; WinAAttributes&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; WinBAttributes&lt;/span&gt;
    &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; WinGranularity&lt;/span&gt;
    &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; WinSize&lt;/span&gt;
    &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; WinASegment&lt;/span&gt;
    &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; WinBSegment&lt;/span&gt;
    &lt;span class="kd"&gt;dd&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; WinFuncPtr&lt;/span&gt;
&lt;span class="nl"&gt;video_bytesPerScanLine:&lt;/span&gt; &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt; &lt;span class="c1"&gt;; BytesPerScanLine&lt;/span&gt;
    &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; XResolution&lt;/span&gt;
    &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; YResolution&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; XCharSize&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; YCharSize&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;            &lt;span class="c1"&gt;; NumberOfPlanes&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;              &lt;span class="c1"&gt;; BitsPerPixel&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; NumberOfBanks&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; MemoryModel&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; BankSize&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; NumberOfImagePages&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; Reserved1&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; RedMaskSize&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; RedFieldPosition&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; GreenMaskSize&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; GreenFieldPosition&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; BlueMaskSize&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; BlueFieldPosition&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; RsvdMaskSize&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; RsvdFieldPosition&lt;/span&gt;
    &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; DirectColorModeInfo&lt;/span&gt;
&lt;span class="nl"&gt;video_address:&lt;/span&gt; &lt;span class="kd"&gt;dd&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;      &lt;span class="c1"&gt;; PhysBasePtr&lt;/span&gt;
    &lt;span class="kd"&gt;dd&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; OffScreenMemOffset&lt;/span&gt;
    &lt;span class="kd"&gt;dw&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;             &lt;span class="c1"&gt;; OffScreenMemSize&lt;/span&gt;
    &lt;span class="kd"&gt;times&lt;/span&gt; &lt;span class="mi"&gt;206&lt;/span&gt; &lt;span class="nv"&gt;db&lt;/span&gt; &lt;span class="mh"&gt;0h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;video address&lt;/em&gt; label stores the pointer to the first pixel.&lt;/p&gt;

&lt;h1&gt;
  
  
  Accessing more memory🚀
&lt;/h1&gt;

&lt;p&gt;When the computer boots in real mode only 20 address lines are usable. This means we can only address 2^20=1MB of memory. This is not good enough, say if we want to use video mode &lt;em&gt;0x11B&lt;/em&gt; which is 1280x1024 with 3 colour channels, we would need about 4MB of memory just to access all of video memory. To fix this we can do something called &lt;em&gt;enabling the A20 line&lt;/em&gt;. This doesn't just give us one more address line, which still wouldn't be enough, but it gives us access to all available address lines, circa 32 probably. This means we can now address up to 4GB of RAM.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Great, so how do I enable the A20 line?&lt;/em&gt; Most BIOS's provide a fast and simple way of doing this by setting some port signals. In fact some BIOS's come with the A20 lines enabled on boot, but this is not always the case so we better make sure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x92&lt;/span&gt;
&lt;span class="nf"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nf"&gt;out&lt;/span&gt; &lt;span class="mh"&gt;0x92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;    
&lt;span class="c1"&gt;;A20 lines now enabled&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Drawing pixels 🎨
&lt;/h1&gt;

&lt;p&gt;Jolly good, now we can start drawing pixels to the screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;dword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;video_address&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="c1"&gt;; determins the x cord of the pixel / bytes per pixel&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x4&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the resolution of the video mode you choose, you may find it difficult to see the pixel because it is so small. Here's some code that should set all the pixels on screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ecx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;dword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;video_address&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;;set this to the number of pixels for your chosen video mode&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;edx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1280&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="c1"&gt;;resolution X * resolution Y * bytes per pix&lt;/span&gt;
&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="nb"&gt;edx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ecx&lt;/span&gt;    
&lt;span class="c1"&gt;;edx is now the end value for the loop&lt;/span&gt;
&lt;span class="c1"&gt;;ecx being the start&lt;/span&gt;
&lt;span class="nl"&gt;.loopHead:&lt;/span&gt;
        &lt;span class="c1"&gt;;set the colour the counter for more interesting display&lt;/span&gt;
        &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;cl&lt;/span&gt;
    &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;ecx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;
        &lt;span class="nf"&gt;inc&lt;/span&gt; &lt;span class="nb"&gt;ecx&lt;/span&gt; &lt;span class="c1"&gt;; move onto next pixel&lt;/span&gt;
    &lt;span class="nf"&gt;cmp&lt;/span&gt; &lt;span class="nb"&gt;ecx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;edx&lt;/span&gt;
    &lt;span class="nf"&gt;jle&lt;/span&gt; &lt;span class="nv"&gt;.loopHead&lt;/span&gt;
&lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="kc"&gt;$&lt;/span&gt; &lt;span class="c1"&gt;; infinate loop, $ means address of current instruction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Now you have all the tools you need to create something awesome.&lt;/p&gt;

&lt;h1&gt;
  
  
  Going further 🧭
&lt;/h1&gt;

&lt;p&gt;I decided to draw the &lt;em&gt;hello world&lt;/em&gt; of images, &lt;em&gt;Lena&lt;/em&gt;. It took me a little while to get it working but in the end I managed it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxo31bavdjwful0tvk2a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxo31bavdjwful0tvk2a.png" alt=" " width="800" height="666"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The pixelated effect is due to my code not a limitation of VBE.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This just leaves one question. &lt;em&gt;What are you going to do with this knowledge?&lt;/em&gt; Let me know in the comments below. Perhaps coding a game, or maybe adding nicer graphics for your kernel.&lt;/p&gt;

&lt;h1&gt;
  
  
  Wrapping up 🎁
&lt;/h1&gt;

&lt;p&gt;I have produced a GitHub repo to pair with this tutorial so if you want to look at sections in more detail head to (&lt;a href="https://github.com/asdf-a11/VBE_Tutorial" rel="noopener noreferrer"&gt;https://github.com/asdf-a11/VBE_Tutorial&lt;/a&gt;). If you have any questions make sure to leave them in the comments below. If you have enjoyed this article then make sure to check out my other articles, I think they'll be of interest to you. Have a great day!&lt;/p&gt;

</description>
      <category>assembly</category>
      <category>programming</category>
    </item>
    <item>
      <title>Learn any Language Faster with One Click</title>
      <dc:creator>William</dc:creator>
      <pubDate>Sat, 26 Jul 2025 15:37:04 +0000</pubDate>
      <link>https://dev.to/willy1948/learn-any-language-faster-with-one-click-2611</link>
      <guid>https://dev.to/willy1948/learn-any-language-faster-with-one-click-2611</guid>
      <description>&lt;p&gt;Have you ever wished that you could learn a new language just by browsing the web? Well I know I have. About a year ago I decided that I wanted to learn Russian. Learning a new language is a slow process, so being able to spend time constantly working towards this goal is critical. However once the novelty of embarking on a new hobby wore off I found it harder and harder to engage and enjoy what I was reading, children stories just aren't that entertaining. This lead to me thinking, &lt;em&gt;I wish I could engage with Russian the same way I do English every day.&lt;/em&gt;  And this is where I decided to create Lingo Journey, a Chrome extension designed to help people learn a new language. If Language learning is all about immersion, then what better way to achieve this than surfing the web entirely in your new language. I wanted the ability to read news articles and watch YouTube videos all in my target language. &lt;br&gt;
Here are some images showing Lingo Journey in action.&lt;/p&gt;

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

&lt;p&gt;For those who are familiar with LingQ it works somewhat similarly. Words are highlighted different colours depending on their learning status. You have the ability to click on words creating a popup window displaying translations, the learning status and other information. &lt;/p&gt;

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

&lt;p&gt;This window remembers where you placed it so you can position it wherever you want and every time you click on a word it will popup and show translations. It can highlight words in the subtitles as you watch the video. Being able to use YouTube to learn a new language opens up so many opportunities.&lt;/p&gt;

&lt;p&gt;If that sounds good to you then I strongly recommend taking a look at installing Lingo Journey here (&lt;a href="https://chromewebstore.google.com/detail/lingo-journey/hkkghimlnkomhmnndmnnidbpilokcaeo" rel="noopener noreferrer"&gt;https://chromewebstore.google.com/detail/lingo-journey/hkkghimlnkomhmnndmnnidbpilokcaeo&lt;/a&gt;). If you are curious you can find the source code on GitHub here (&lt;a href="https://github.com/asdf-a11/LingoJourney" rel="noopener noreferrer"&gt;https://github.com/asdf-a11/LingoJourney&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paid translations&lt;/strong&gt;. Lingo Journey provides free translations which should be good for beginners but as you progress you may find words that don't have translations, I suggest getting the complete translation list from my patron (&lt;a href="https://patreon.com/LingoJourney" rel="noopener noreferrer"&gt;https://patreon.com/LingoJourney&lt;/a&gt; and then in the shop tab). It costs barely more than one month of LingQ but you keep it forever, sounds like a good deal to me. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's next.&lt;/strong&gt; I think my main focus is to support more languages, German, French and Spanish just to name a few. So far I have been solo testing this project and developing for my own needs, but I am excited to see what other make of it and implement any feedback.&lt;/p&gt;

&lt;p&gt;Lastly if you have any thoughts or questions you wish to share I would love to hear about them in the comments. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Making Pong in x86 Assembly</title>
      <dc:creator>William</dc:creator>
      <pubDate>Thu, 24 Jul 2025 18:37:55 +0000</pubDate>
      <link>https://dev.to/willy1948/making-pong-in-x86-assembly-11li</link>
      <guid>https://dev.to/willy1948/making-pong-in-x86-assembly-11li</guid>
      <description>&lt;h1&gt;
  
  
  Introduction 📘
&lt;/h1&gt;

&lt;p&gt;So many developers won't have even touched assembly language let alone decide to write a whole program in it. This is understandable, reasons to write assembly are few and far between. However the knowledge you gain from doing as such can help build a deeper understanding of how computers function helping you write better more efficient code even in other programming languages. &lt;/p&gt;

&lt;p&gt;So to start off lets take a look at what "&lt;em&gt;x86 Assembly&lt;/em&gt;" actually means. Assembly code is device specific meaning code that runs one one machine might not work on another. This is because CPUs can have different architecture and therefore expect different instructions. Each architecture will have a certain set of instructions that the CPU is designed to use. Here we are using the x86 architecture which is what majority of laptops and desktops use. ARM and RISCV are the other two major ones. Whilst your code might not run on a different architecture the knowledge you gain from learning one variant of assembly will easily transfer to any other variant.&lt;/p&gt;

&lt;h1&gt;
  
  
  Boot loaders 🧰
&lt;/h1&gt;

&lt;p&gt;A common use of assembly is writing bootloader games. These were popular 40 or so years ago where memory was expensive and so compacting a game into the 512 byte boot segment was a popular and challenging thing to do. It was the first segment that is loaded into memory when the computer boots, and is the first to starts running. &lt;/p&gt;

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

&lt;p&gt;I decided to set myself this challenge of writing pong in assembly from the bootloader. I gave myself one allowance: the ability to utilize additional memory segments beyond the strict 512-byte boot sector. This is critical if I want to implement a font which requires lots of space to store. Here are some of the most interesting parts of this project. &lt;/p&gt;

&lt;p&gt;One thing that you might not have expected is the fact that when booting computers are in 16 bit mode, even if it is a 64 bit processor. This may seem strange, and it is, but the reason for it is to keep backwards compatibility with older software whilst computers were still making the transition from 16 bit to 32 bit. This isn't the only weird thing about booting. For some reason the boot sector is loaded in the hex address 0x7c00. One would naturally expect it to be address 0, but no. The reason for this is that BIOS (code that boots the bootloader and does other stuff) can use values in the lower address space and overwriting that would be bad. So before any code is written it is important to have the two lines&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;bits&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;;tells the assembler this code is for 16 bit mode&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;org&lt;/span&gt; &lt;span class="mh"&gt;0x7c00&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;;tells the assembler where the code is located in RAM&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;16 bit instructions are different to 32 bit instructions and therefore we need to tell the assembler to generate the 16 bit machine code not 32 bit. &lt;em&gt;[org 0x7c00]&lt;/em&gt; is important so that the assembler can correctly calculate the address of our labels and data. This is because in assembly instead of using &lt;em&gt;if, while, for&lt;/em&gt; you use labels. These are just flags that don't actually exist but the assembler knows there byte position in the machine code and you can tell the CPU to jump to them e.g&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;someLabel:&lt;/span&gt;
&lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="nv"&gt;someLable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 creating an infinite loop. This links back to &lt;em&gt;[org 0x7c00]&lt;/em&gt; if we don't tell the assembler the starting address of our labels it will miscalculate their positions. This means that &lt;em&gt;jmp someLabel&lt;/em&gt; will send execution to completely the wrong place in memory, which is &lt;em&gt;no bueno&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Right, now the assembler knows what its doing, lets take a look at the next vital part of our program.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;bits&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;org&lt;/span&gt; &lt;span class="mh"&gt;0x7c00&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="c1"&gt;; Jump over variables to not execute as instructions&lt;/span&gt;
&lt;span class="nl"&gt;BOOT_DISK:&lt;/span&gt; &lt;span class="kd"&gt;db&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="c1"&gt;; Stores boot device ID&lt;/span&gt;
&lt;span class="nl"&gt;main:&lt;/span&gt;
  &lt;span class="c1"&gt;;Stack grows downwards from the bootloader&lt;/span&gt;
  &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;bp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x7c00&lt;/span&gt;
  &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;bp&lt;/span&gt;
  &lt;span class="c1"&gt;;Save the boot device for loading the later segments&lt;/span&gt;
  &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;BOOT_DISK&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;dl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the first things we need to do is set up the stack. If you have programmed in C or C++ you may be familiar with what the stack is, but if not. The stack is data structure in computer science where you can only add or remove an item from the top but you can read from any where on the stack. This is how the majority of data is stored in a computer program, there is something else called the heap. This can be used for say, lists that can change dynamically in size during run time, but we don't need to worry about that for this project. &lt;strong&gt;However&lt;/strong&gt; there is a problem to solve. After a function has been called and during which variables have been added to the stack, when that function returns how do we know how to restore the stack i.e remove all the data that was previously pushed whilst the function was running? To solve this we break the stack into sections called stack frames. A stack frame is created every time a function is called, and when it is created it pushes the address of the previous stack frame onto the stack. This means when climbing up the stack it can set &lt;em&gt;bp&lt;/em&gt; = &lt;em&gt;sp&lt;/em&gt; then read of the stack the new value for &lt;em&gt;sp&lt;/em&gt;, returning the stack to it's state before the function call.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftk2o8yns0ll5z0vozpx5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftk2o8yns0ll5z0vozpx5.png" alt=" " width="800" height="950"&gt;&lt;/a&gt;&lt;br&gt;
All we need to implement a stack is a value to store the address of the start of the stack and a value to store the address of the previse stack frame. Luckily for us, x86 architecture comes with two registers designed just for that. The names of the two registers are &lt;em&gt;sp&lt;/em&gt; and &lt;em&gt;bp&lt;/em&gt;, standing for &lt;em&gt;stack pointer&lt;/em&gt; and &lt;em&gt;base pointer&lt;/em&gt;. Stack pointer points to the previse stack frame and the base pointer to the bottom of the stack. You may think that to set up the stack you should do something like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;bp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 setting their address to begging of memory seems sensible right? &lt;strong&gt;Wrong&lt;/strong&gt;! The slightly unintuitive thing about stacks are that they grow downwards, each subsequent item added is at a lower memory address. That is why the following code works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;bp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x7c00&lt;/span&gt;&lt;span class="c1"&gt;; setting to the top of the stack&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;bp&lt;/span&gt;&lt;span class="c1"&gt;; no previse stack frame so just set it to bp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 Whilst the memory segments containing our program are loaded into higher addresses, the stack will use lower address. Understanding memory and therefore stacks is a really important part of righting good efficient programs in any language. &lt;/p&gt;

&lt;p&gt;The BIOS will only load the boot sector, so it is our job to do the rest. We need to load the next, how ever many pages (512 bytes) of memory. This is the reason for the line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;BOOT_DISK&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;dl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
Upon boot the 8 bit id of the storage device that was used to boot from, is moved into the lower half of the 16 bit dx register, hence dl (data lower). We need to make a copy of this value so we know which device to read the remaining sectors off of. One of the great things about being in 16 bit mode is that we have access to BIOS routines, this is not the case in 32 bit / 64 bit mode because the processor uses different methods for managing memory which makes the code incompatible (16 bit mode uses segmentation, 64 bit mode uses paging and 32 bit mode uses a combination of paging and segmentation). To call these routines all you have to do is call the &lt;em&gt;int&lt;/em&gt; instruction, short for interrupt, with some code which relates to some routine. So to read in the next segments from memory all we have to do is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;readDisk:&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ah&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x02&lt;/span&gt;&lt;span class="c1"&gt;; Specifies BIOS function: "Read sectors from disk"&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;bx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;PROGRAM_SPACE&lt;/span&gt; &lt;span class="c1"&gt;; ES:BX = destination address in memory to load the data&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;BOOT_DISK_READ_SIZE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;; AL = number of sectors to read (each sector is 512 bytes)&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;dl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;BOOT_DISK&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;; DL = BIOS drive number (e.g., 0x00 for floppy, 0x80 for HDD)&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x00&lt;/span&gt; &lt;span class="c1"&gt;; CH = cylinder number (part of the CHS address), here it's 0&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;dh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x00&lt;/span&gt; &lt;span class="c1"&gt;; DH = head number, starting at head 0&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;cl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x02&lt;/span&gt; &lt;span class="c1"&gt;;CL = sector number (sectors start at 1; this means sector 2)&lt;/span&gt;

&lt;span class="nf"&gt;int&lt;/span&gt; &lt;span class="mh"&gt;0x13&lt;/span&gt; &lt;span class="c1"&gt;; BIOS disk hindering function — executes the read based on register setup&lt;/span&gt;
&lt;span class="nf"&gt;jc&lt;/span&gt; &lt;span class="nv"&gt;.errorCode&lt;/span&gt; &lt;span class="c1"&gt;;carry flag is set if error occurs&lt;/span&gt;
&lt;span class="nf"&gt;ret&lt;/span&gt; &lt;span class="c1"&gt;; returns from function back to callee&lt;/span&gt;
&lt;span class="nl"&gt;.errorCode:&lt;/span&gt;
    &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;bx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;di&lt;/span&gt;&lt;span class="nv"&gt;skReadErrMsg&lt;/span&gt;&lt;span class="c1"&gt;; bx is pointer to string&lt;/span&gt;
    &lt;span class="nf"&gt;call&lt;/span&gt; &lt;span class="nv"&gt;print&lt;/span&gt;&lt;span class="c1"&gt;; takes bx as argument&lt;/span&gt;
    &lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="c1"&gt;; $ means current address therefore infinite loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 There is one small part of this code that you might not be able to understand just yet, and that is &lt;em&gt;ES:BX&lt;/em&gt;. This simply means &lt;em&gt;BX&lt;/em&gt; offset by &lt;em&gt;ES&lt;/em&gt;. More precisely it translates to &lt;em&gt;BX + ES * 16&lt;/em&gt;. Because this program is small we don't need to write into the higher address spaces so &lt;em&gt;ES&lt;/em&gt; and all other segment registers are set to zero at the start by the bootloader. &lt;/p&gt;

&lt;p&gt;This raps up all the functionality that we need from the bootloader. All we need to do now is call the &lt;em&gt;readDisk&lt;/em&gt; function then jump to the loaded segments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;call&lt;/span&gt; &lt;span class="nv"&gt;readDisk&lt;/span&gt;
&lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="mh"&gt;0x7e00&lt;/span&gt;&lt;span class="c1"&gt;; = 0x7c00 + 512&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 You may be wondering why the code jumps to the new segments and doesn't just run from the boot sector into the new segments. That would save space right? Well this is partially true but there is a special two bytes called the boot signature, 0xaa55. Located at the end of the boot sector which is mandatory. As our code grows we don't want it to overwrite these two bytes. So it is just simpler to jump over them and execute in the new segments.&lt;/p&gt;
&lt;h1&gt;
  
  
  Graphics 🎨
&lt;/h1&gt;

&lt;p&gt;I think the most interesting part of this project is the graphics. I mean, what is a game without graphics, right? Luckily for use we can get graphics working within a few lines of code just by using in-built interrupts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x13&lt;/span&gt; &lt;span class="c1"&gt;; VGA mode 0x13&lt;/span&gt;
&lt;span class="nf"&gt;int&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt; &lt;span class="c1"&gt;; Sets the graphics mode based on ax&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VGA mode 13 gives us a colour pallet size of 255 and a resolution of 320 x 200. A list of what &lt;em&gt;int 0x10&lt;/em&gt; can do can be found here (&lt;a href="https://en.wikipedia.org/wiki/INT_10H" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/INT_10H&lt;/a&gt;). This is great, but now we need to be able to draw to the screen. There are two ways to do this, using interrupts and writing directly to memory. Using interrupts is simple, but at the cost of performance. The second option of writing directly to memory at a certain address where the graphics card will read from is much faster. This special place is at address &lt;em&gt;0xA0000&lt;/em&gt; (not the same for all video modes), you may think, &lt;em&gt;hang on this is bigger than 16 bit register can address, do we need to use segment registers?&lt;/em&gt; You would be right that is a valid way, but the strange thing is, in 16 bit mode we are still free to use 32 bit registers (not the case for 64 bit registers). To write to the first pixel on the screen (top left) all we need to do is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0xA0000&lt;/span&gt;&lt;span class="c1"&gt;; eax is 32 bit version of ax&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;200 represents the 200th colour in the VGA 13h colour pallet. This is very simple and very fast. Building upon this to draw text is easy. All we need to do is have a way to draw pictures, this can be done with two loops like so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nl"&gt;drawImg_f:&lt;/span&gt; &lt;span class="c1"&gt;; eax = ptr edi = xpos esi = ypos&lt;/span&gt;
    &lt;span class="nf"&gt;pushad&lt;/span&gt;&lt;span class="c1"&gt;; pushes all resgisters to the stack&lt;/span&gt;
    &lt;span class="nf"&gt;push&lt;/span&gt; &lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="c1"&gt;; stored because mul uses eax&lt;/span&gt;
        &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;SX&lt;/span&gt;&lt;span class="c1"&gt;; SX=screen size x = 320&lt;/span&gt;
        &lt;span class="nf"&gt;mul&lt;/span&gt; &lt;span class="nb"&gt;esi&lt;/span&gt;&lt;span class="c1"&gt;; = SX * ypos&lt;/span&gt;
        &lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="c1"&gt;; xpos + SX * ypos&lt;/span&gt;
        &lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;BM&lt;/span&gt;&lt;span class="c1"&gt;; xpos + SX * ypos + buf offset&lt;/span&gt;
    &lt;span class="nf"&gt;pop&lt;/span&gt; &lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="c1"&gt;; restore to value&lt;/span&gt;
    &lt;span class="c1"&gt;;esi ecx x,y respectivly&lt;/span&gt;
    &lt;span class="nf"&gt;xor&lt;/span&gt; &lt;span class="nb"&gt;ecx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ecx&lt;/span&gt;&lt;span class="c1"&gt;; quicker than mov ecx, 0&lt;/span&gt;
        &lt;span class="c1"&gt;; I chose to store the sizex and sizey before the start&lt;/span&gt;
        &lt;span class="c1"&gt;; of the image therefore need to jump over both 4 bytes&lt;/span&gt;
    &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ebx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
    &lt;span class="nl"&gt;.loopY:&lt;/span&gt;
        &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;edx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;dword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;; get size y&lt;/span&gt;
        &lt;span class="nf"&gt;cmp&lt;/span&gt; &lt;span class="nb"&gt;ecx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;edx&lt;/span&gt;
        &lt;span class="nf"&gt;jge&lt;/span&gt; &lt;span class="nv"&gt;.endLoopY&lt;/span&gt;

        &lt;span class="nf"&gt;xor&lt;/span&gt; &lt;span class="nb"&gt;esi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;esi&lt;/span&gt;
        &lt;span class="nl"&gt;.loopX:&lt;/span&gt;
            &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;edx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;dword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="c1"&gt;; get size x&lt;/span&gt;
            &lt;span class="nf"&gt;cmp&lt;/span&gt; &lt;span class="nb"&gt;esi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;edx&lt;/span&gt;
            &lt;span class="nf"&gt;jge&lt;/span&gt; &lt;span class="nv"&gt;.endLoopX&lt;/span&gt;

            &lt;span class="nf"&gt;push&lt;/span&gt; &lt;span class="nb"&gt;eax&lt;/span&gt;        
                &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;ebx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;al&lt;/span&gt;
            &lt;span class="nf"&gt;pop&lt;/span&gt; &lt;span class="nb"&gt;eax&lt;/span&gt;

            &lt;span class="nf"&gt;inc&lt;/span&gt; &lt;span class="nb"&gt;esi&lt;/span&gt; 
            &lt;span class="nf"&gt;inc&lt;/span&gt; &lt;span class="nb"&gt;edi&lt;/span&gt;
            &lt;span class="nf"&gt;inc&lt;/span&gt; &lt;span class="nb"&gt;ebx&lt;/span&gt;
            &lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="nv"&gt;.loopX&lt;/span&gt;
        &lt;span class="nl"&gt;.endLoopX:&lt;/span&gt;

        &lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;SX&lt;/span&gt;
        &lt;span class="nf"&gt;sub&lt;/span&gt; &lt;span class="nb"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;dword&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;eax&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="nf"&gt;inc&lt;/span&gt; &lt;span class="nb"&gt;ecx&lt;/span&gt;
        &lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="nv"&gt;.loopY&lt;/span&gt;
    &lt;span class="nl"&gt;.endLoopY:&lt;/span&gt;  
    &lt;span class="nf"&gt;popad&lt;/span&gt;&lt;span class="c1"&gt;; pops all registers from the stack&lt;/span&gt;
    &lt;span class="nf"&gt;ret&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now all we need to do is add the images to our code. We want to have a way of getting the location of each numerical character so we can render it. To do this we can use labels and have the NASM pre-processor set them for use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="cp"&gt;%assign i 0 &lt;/span&gt;&lt;span class="c1"&gt;; what number the font reprisents
&lt;/span&gt;&lt;span class="cp"&gt;%rep 10 &lt;/span&gt;&lt;span class="c1"&gt;; set all 0-9 characters
&lt;/span&gt;&lt;span class="nf"&gt;Font&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="c1"&gt;; defines the label we can use later&lt;/span&gt;
        &lt;span class="c1"&gt;;Gets the bin file from folder Font&lt;/span&gt;
&lt;span class="cp"&gt;    %defstr myString Font\\%[i].bin
&lt;/span&gt;        &lt;span class="c1"&gt;;Short for include binary&lt;/span&gt;
    &lt;span class="nf"&gt;incbin&lt;/span&gt; &lt;span class="nv"&gt;myString&lt;/span&gt;
        &lt;span class="c1"&gt;; incriments the number counter&lt;/span&gt;
&lt;span class="cp"&gt;    %assign i i+1
%endrep
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;em&gt;Font0&lt;/em&gt; is represents the address of the 0 character image and so on. This is all well and good, but image editors don't just output the plain image data. There is almost always some sort of compression going on. To get the plain data we can use a python script to help us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="c1"&gt;#Takes in images names as arguments when program is launched
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;pic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="c1"&gt;#Understands png format
&lt;/span&gt;    &lt;span class="n"&gt;pix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getdata&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ubyte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;#Remove the .png from the end of the file name
&lt;/span&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.bin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;#Writes image dimension each 4 bytes
&lt;/span&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="n"&gt;pic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="c1"&gt;#Writes the image data .flatten() means make it one 
&lt;/span&gt;    &lt;span class="c1"&gt;#dimentional list
&lt;/span&gt;    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatten&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All together it yields:&lt;br&gt;
(&lt;a href="https://github.com/asdf-a11/Pong_Boot_Sector/blob/main/README_Images/Animation.gif" rel="noopener noreferrer"&gt;https://github.com/asdf-a11/Pong_Boot_Sector/blob/main/README_Images/Animation.gif&lt;/a&gt;). I don't believe one can upload a gif, so here it is hosted in the repo.&lt;/p&gt;

&lt;p&gt;This has been a quick overview into getting started with x86 assembly. I hope you found it engaging, any questions leave them in the comment section. If you would like to learn more, here is the link to my GitHub repo (&lt;a href="https://github.com/asdf-a11/Pong_Boot_Sector/" rel="noopener noreferrer"&gt;https://github.com/asdf-a11/Pong_Boot_Sector/&lt;/a&gt;).&lt;/p&gt;
&lt;h1&gt;
  
  
  Common Bugs 🐛
&lt;/h1&gt;

&lt;p&gt;Lastly for those who would like to get started with assembly bootloader shenanigans, I would like to help you avoid some of the pitfalls I fell in whilst I was learning. The first being, include special data at the start of you bootloader.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;    &lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="c1"&gt;; dont want to execute this table by accident&lt;/span&gt;
    &lt;span class="kd"&gt;TIMES&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kc"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;DB&lt;/span&gt; &lt;span class="mh"&gt;0x90&lt;/span&gt; 
    &lt;span class="nl"&gt;OEMname:&lt;/span&gt; &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="s"&gt;"mkfs.fat"&lt;/span&gt;
    &lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="nl"&gt;sPerSector:&lt;/span&gt;    &lt;span class="kd"&gt;dw&lt;/span&gt;    &lt;span class="mi"&gt;512&lt;/span&gt;
    &lt;span class="nl"&gt;sectPerCluster:&lt;/span&gt;    &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nl"&gt;reservedSectors:&lt;/span&gt;   &lt;span class="kd"&gt;dw&lt;/span&gt;    &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nl"&gt;numFAT:&lt;/span&gt;            &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="nl"&gt;numRootDirEntries:&lt;/span&gt; &lt;span class="kd"&gt;dw&lt;/span&gt;    &lt;span class="mi"&gt;224&lt;/span&gt;
    &lt;span class="nl"&gt;numSectors:&lt;/span&gt;        &lt;span class="kd"&gt;dw&lt;/span&gt;    &lt;span class="mi"&gt;2880&lt;/span&gt;
    &lt;span class="nl"&gt;mediaType:&lt;/span&gt;         &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="mh"&gt;0xf0&lt;/span&gt;
    &lt;span class="nl"&gt;numFATsectors:&lt;/span&gt;     &lt;span class="kd"&gt;dw&lt;/span&gt;    &lt;span class="mi"&gt;9&lt;/span&gt;
    &lt;span class="nl"&gt;sectorsPerTrack:&lt;/span&gt;   &lt;span class="kd"&gt;dw&lt;/span&gt;    &lt;span class="mi"&gt;18&lt;/span&gt;
    &lt;span class="nl"&gt;numHeads:&lt;/span&gt;          &lt;span class="kd"&gt;dw&lt;/span&gt;    &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="nl"&gt;numHiddenSectors:&lt;/span&gt;  &lt;span class="kd"&gt;dd&lt;/span&gt;    &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nl"&gt;numSectorsHuge:&lt;/span&gt;    &lt;span class="kd"&gt;dd&lt;/span&gt;    &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nl"&gt;driveNum:&lt;/span&gt;          &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nl"&gt;reserved:&lt;/span&gt;          &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nl"&gt;signature:&lt;/span&gt;         &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="mh"&gt;0x29&lt;/span&gt;
    &lt;span class="nl"&gt;volumeID:&lt;/span&gt;          &lt;span class="kd"&gt;dd&lt;/span&gt;    &lt;span class="mh"&gt;0x2d7e5a1a&lt;/span&gt;
    &lt;span class="nl"&gt;volumeLabel:&lt;/span&gt;       &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="s"&gt;"NO NAME    "&lt;/span&gt;
    &lt;span class="nl"&gt;fileSysType:&lt;/span&gt;       &lt;span class="kd"&gt;db&lt;/span&gt;    &lt;span class="s"&gt;"FAT12   "&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 You may notice that your code runs in a emulator but not on real hardware. If you don't have this at the very start of your bootloader, that might be the problem. I don't know exactly what it does but make sure to include it. Another thing to be aware of is making sure the processor is in a known state. When booting registers and settings could be anything, make sure to set their values. For example at the start of my bootloader I do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="c1"&gt;;Dont need to use segment registers so sell them to 0&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mh"&gt;0x00&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;es&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ax&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ss&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ax&lt;/span&gt;
&lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="nb"&gt;ds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ax&lt;/span&gt;
&lt;span class="c1"&gt;;set the direction flag, it is used for certain string related&lt;/span&gt;
&lt;span class="c1"&gt;;instructions&lt;/span&gt;
&lt;span class="nf"&gt;cld&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
 If you are using the FPU (floating point processing unit) then make sure you add &lt;em&gt;fninit&lt;/em&gt;, this sets the FPU to a default state. &lt;/p&gt;

</description>
      <category>assembly</category>
      <category>low</category>
      <category>learning</category>
      <category>gamedev</category>
    </item>
  </channel>
</rss>
