16-bit Assembly

From SkullSecurity
Revision as of 20:18, 24 December 2009 by SamB (talk | contribs) (Work on the cs:ip bit some; also clarify the last section)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
Stop hand.png This page is under construction. USE AT YOUR OWN RISK!

Assembly Language Tutorial
Please choose a tutorial page:

Older software, before 32-bit was common, was written in 16-bit x86 assembly. Although it is rare to come across, it does happen. This section will talk about some of the challenges to cracking a 16-bit program.

Thankfully, IDA supports 16-bit programs as well as 32-bit programs. That means that, if nothing else, a friendly disassembler is available to assist with reverse engineering.

W32Dasm also works well on 16-bit programs.


There are many challenges with cracking a 16-bit game that aren't present in modern 32-bit programs. Some examples of issues are:

  • Debuggers don't work unless they're specially designed, since 16-bit programs run in a virtual machine.
  • Small segments means code is more spread out.
  • Different uses for registers/instructions.

This section will address the final point, since that's the only really necessary tool.


The general purpose registers are similar, with one exception: the 32-bit registers no longer exist. That means that the registers available are:

  • ax
  • bx
  • cx
  • dx
  • si
  • di
  • bp
  • sp

Another change is in the instruction pointer, eip -- the instruction pointer is now split into two parts, cs and ip. cs points to the current code segment and ip points to the current instruction within that segment.

The reason for this change is because a 16-bit register only has a 65536-value range, and most programs are more than 64k big.

(Technically, 32-bit code actually uses cs along with eip in the same way, but most of the time we don't care about this and always use the same segment for everything, unless we're writing a DPMI implementation or a win16 compatibility layer or the like, which *must* be concerned with such things.)


The main differences in instructions is that the instructions that operate on 64-bit values stored in register pairs (such as div and mul) now operate on 32-bit values. That means that any instruction that uses edx:eax now uses dx:ax.