Questions tagged [x86-16]

For programming and/or microarchitecture questions about the 16-bit x86 Intel CPUs, including the 8088, 8086, and later chips running in 16-bit mode.

x86-16 refers to the 16-bit family of instruction set architectures (ISAs) based on the Intel 8086 CPU. This processor was designed by Intel in the mid-1970s, and gave rise to the x86 architecture.

See the tag wiki for links to x86 ISA and assembly-language programming resources (mostly aimed at modern 32-bit and 64-bit implementations).

The 8086 uses the same instruction set as later processors, but it is limited to 16-bit mode and lacks support for instructions added with 186, 286, 386 (or later). This means that extremely useful instructions like movzx are unavailable, so many operations require moving data into ax for use with instructions that have it as an implicit operand. The 16-bit implementation of x86 is also limited with respect to which registers can be used in addressing modes. This addressing limitation persists in modern CPUs running in 16-bit mode, because the machine-code format is the same.

The 8088 is a derivative of the 8086. The 8088 is identical in functionality to the 8086 and is fully 16-bit internally, but it has an 8-bit external data bus (instead of the 8086's 16-bit external data bus). In terms of programming, there are no salient differences between the 8088 and 8086, so these are combined under a single tag. Feel free to mention which specific chip you're targeting in the body and/or title of the question, though.

This tag is also appropriate for questions about non-Intel CPUs that use the same instruction set as the 8086, including the NEC v20 and v30, AMD 8086 clones, etc. There are also some modern microcontrollers that use simple 8086 cores.

Note that, while it will run on modern x86 CPUs, code that uses only the 16-bit instructions (as would be supported on an 8086) is not usually considered good or efficient code.

However, there remains much interest in writing 16-bit code for emulators (such as DOSBox and ) and real vintage hardware, both from beginners and enthusiasts. retrocomputing.SE has an 8086 tag, but unless you're asking about actual ancient hardware, Stack Overflow is the right place for questions about 16-bit bootloaders, kernels, and DOS executables. Retrocomputing is mostly about even older systems, like 8-bit micros.



Debuggers

Single-stepping in a debugger and looking at registers is essential. Trying to write a program without one is like trying to build a robot blindfolded. It's very much worth the time to learn to use one. For 32/64-bit mode under a modern OS, see the debugging section at the bottom of the x86 tag wiki.

Under DOS:

  • @ecm's lDebug, based on debug.com from FreeDOS.
  • Turbo Debugger is widely recommended, and maybe can be found for free
  • debug.exe/debug.com in MS-DOS or FreeDOS is an option, although classic MS-DOS DEBUG is pretty terrible to actually program in, not having labels, only numeric addresses for jump targets and so on!

Full system (for bootloaders, or maybe DOS programs)

  • Bochs is usually the gold standard, with a built-in debugger that's aware of segmentation. Manual. Note that it's an optional config feature; some builds might not come with it enabled. It's great for debugging the switch to 32-bit protected mode, and 64-bit mode. It can parse and dump your GDT and page tables, to help you spot mistakes in what you put there, and it knows what mode the CPU is in so it will disassemble in the right mode to match execution, helping you catch mistakes where code was assembled for the wrong bitness.
  • QEMU: can act as a remote for GDB. GDB doesn't know about segmentation so this isn't ideal for real mode or during the switch to protected mode.
  • DOSBox: There's a DOSBox-X fork with a built-in debugger, and the mainline DOSBox apparently also has a debugger built-in. (Curses-based text UI)

Related Tags:

  • (for the x86 in general, including 32-bit and 64-bit. Lots of good stuff in the tag wiki, including some 16-bit links)
  • (for stuff specifically about the 64-bit extensions to the x86 ISA)
  • (for the legacy numeric coprocessor—aka floating point unit, as opposed to the SSE/SSE2 FPU)
  • (for programs written in assembly language of any kind, including x86, MIPS, ARM, and toy architectures like LC-3)
  • (for programs targeting DOS and/or questions about DOS APIs)
  • (for questions specifically about the EMU8086 emulator package, often used by students)
2894 questions
6
votes
2 answers

Full path to self in DOS executable

In my 16bit DOS program I want to get the full path to the instance of my program, using DOS interrupt or its internal tables. In other words, I'm looking for DOS equivalent of Windows API function GetModuleFileName(NULL) Interrupt 21h/AH=60h…
vitsoft
  • 5,515
  • 1
  • 18
  • 31
6
votes
2 answers

Calculating padding length with GAS AT&T directives for a boot sector?

So I want to add padding in the bootsector. Let's say, there is currently just an endless loop in there: jmp .. The sector needs to be 512 bytes long. Also, the magic num 0xaa55 is needed which is added at the end. jmp . .skip 508, 0 .word…
6
votes
1 answer

Assignment directive not assigning new value to a symbol in emu8086

Why doesn't the following code assign new value to a symbol X using Assignment Directive ( = ) in emu8086: .model small .data X = 8 .code .startup mov ax, @data mov ds, ax mov bx, X X = 6 mov…
Ahtisham
  • 9,170
  • 4
  • 43
  • 57
6
votes
3 answers

How buffered input works

The input in next program (using DOS.BufferedInput function 0Ah) works OK, but when I ask to show the output, DOS doesn't display anything at all. How is this possible? ORG 256 mov dx, msg1 mov ah, 09h …
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
6
votes
1 answer

8086 assembly on DOSBox: Bug with idiv instruction?

I was helping a friend of mine debug his program, and we narrowed it down to an issue which occurs even here: .MODEL small .STACK 16 .CODE start: mov ax, 044c0h mov bl, 85 idiv bl exit: mov ax, 4c00h int 21h end start After…
eequinox
  • 63
  • 1
  • 5
6
votes
1 answer

Default registers and segments value on booting x86 machine

I found that usually programmers fixup registers (and sometimes segments) on their very first lines of bootloaders and they advice usually to have this habit. For instance: inc cx dec bx inc bp dec di xor ax, ax What I know is that: BIOS clears all…
6
votes
1 answer

Bootloader works in emulators but not on real hardware

I am writing a bootloader in assembly and it seems to work fine on qemu, bochs and virtualbox. However, it is not loading the kernel on real hardware (it seems). The bootloader starts off by writing a character to the video memory (for debugging),…
user2725580
  • 1,293
  • 2
  • 17
  • 21
6
votes
3 answers

Assembly 8086 EQU directive

I'm having trouble just making clear EQU directive in assembler (8086). abc EQU xyz Does EQU literally swaps abc when found in code with xyz, whatever xyz represents, value etc? i.e. Can i write? varA EQU [bp+4] mov ax, varA And one more question…
luka032
  • 925
  • 4
  • 12
  • 34
6
votes
2 answers

How to print strings in assembly language

I am trying to print a string in Q Emulator using NASM. My code is as below: mov bx,HELLO mov ah, 0x0e int 0x10 HELLO: db 'Hello', 0 jmp $ times 510-($-$$) db 0 dw 0xaa55 However when I compile this code, the output that I get is UU Can anyone…
Sanket Gupte
  • 357
  • 1
  • 4
  • 16
6
votes
1 answer

The 'LES' 8086 instruction is not working as intended

I'm a beginner at 8086 assembly. I'm learning from an old early 90s book I found in a thrift store. I thought it might be fun to program like it's 1992. Anyway I'm done with the book and now i've written a few programs at the command prompt on my…
bad
  • 939
  • 6
  • 18
6
votes
4 answers

How can I get an extra segment in DOS?

I'd like to write a little DOS program (my first one) and I'm a little bit inexperienced. For the program, I need more than 64 kilobytes of (conventional) memory. How can I get extra memory? Ideally, I'd like to have two extra 64k blocks of memory…
fuz
  • 88,405
  • 25
  • 200
  • 352
6
votes
3 answers

16-bit Assembly on 64-bit Windows?

I decided to start learning assembly a while ago, and so I started with 16-bit assembly, using FASM. However, I recently got a really new computer running Windows 7 64-bit, and now none of the compiled .COM files that the program assembles work any…
6
votes
3 answers

Using ES register gives errors

I am converting a program from EMU8086 environment to NASM. When assembling NASM gives these errors : system\kernel.asm:14: error: invalid combination of opcode and operands system\kernel.asm:20: error: invalid combination of opcode and…
gamecraftCZ
  • 306
  • 5
  • 14
6
votes
3 answers

How can I tell if jump is absolute or relative?

I'm studying for a test in assembly and in the subject of "Position-Independent-Code" I find the difference between a relative jump and an absolute jump confusing. How can I tell what kind of jump it is? I understand what a relative jump is (the…
6
votes
2 answers

How to use GDB in 16-bit mode?

I have the following code, where I am trying to implement a function that prints string using the BIOS functions: int printString(char* string) { int i = 0; while (*(string + i) != '\0') { char al = *(string + i); char ah = 0xe; int…
sarthak
  • 774
  • 1
  • 11
  • 27