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

What decides memory address for global variables. Compiler or Operating system?

Consider the below program. int a = 0x45; int main() { int i = a; return 0; } ;; asm code call 0x401780 <__main> mov 0x402000,%eax // why does it allocate 0x402000 only for global 'a'? mov %eax,0xc(%esp) mov $0x0,%eax leave This…
user3205479
  • 1,443
  • 1
  • 17
  • 41
6
votes
2 answers

Why does 20 address space with on a 16 bit machine give access to 1 Megabyte and not 2 Megabytes?

OK, this question sounds simple but I am taken by surprise. In the ancient days when 1 Megabyte was a huge amount of memory, Intel was trying to figure out how to use 16 bits to access 1 Megabyte of memory. They came up with the idea of using…
quantum231
  • 2,420
  • 3
  • 31
  • 53
6
votes
1 answer

How to make x=2a+3b in 4 instructions limit using ONLY mov,add,sub,neg?

Let's say x is a register which its value isn't known. I have to make x=2a+3b where a and b have unknown values. I can use the 8086 asm instructions mov, add, sub, neg only. The use of the mul instruction isn't allowed, and also there is a limit of…
Lior
  • 5,841
  • 9
  • 32
  • 46
6
votes
1 answer

NASM x86 16-bit addressing modes

I am having trouble with pointing to a address and write in my case a variable of byte in size. This gives me the error "error: invalid effective address": mov byte[AX], byte 0x0 After some trail and error i tested the same but with EAX. This…
Michael
  • 892
  • 2
  • 10
  • 28
5
votes
1 answer

Access to PIT (?) IO ports 44h and 46h - what do those ports do?

I was disassembling an MS-DOS .com application and came across some port access which I don't understand. More precisely, via the IN instruction, values are read from the following ports. 40h 44h 46h The documentation found here mentions ports…
Codor
  • 17,447
  • 9
  • 29
  • 56
5
votes
1 answer

Disassembling an old .COM file. Stuck within 48 bytes. Endian problem?

I had an old game... Starflight. I think it came out in '86. Good ol' IBM PC jr days. I figured I'd break out a disassembler and see how it worked. I can see in the little that I've decoded, code size was optimized for sure... but I ended up jumping…
Nolan Robidoux
  • 395
  • 2
  • 17
5
votes
2 answers

Calculating hexadecimal values for 7-segment LED on MDA-8086

I was trying to display 7-segment LED on MDA-8086 kit, but I am stuck at calculating the hexadecimal values for respective digits. I have the code with me, but I don't understand how it actually works. For example, 0 is represented by hexadecimal…
Apprentice
  • 65
  • 3
5
votes
2 answers

What is the correct calling convention to use within a bootloader?

I am trying writing a bootloader and an extremely primitive and basic kernel to learn about bare metal coding practices and techniques. Anyways, I am writing my bootloader using NASM. My code is working, but I have a question about the calling…
5
votes
1 answer

How should the stack be initialized to in an x86 real mode bootloader to prevent conflicts with BIOS?

Suppose I want to initialize the stack to a size of S bytes. I would like to chose the base position of the stack B so that as the stack grows downward from B, I do not end up overwriting any code or other memory being used by the bootloader or the…
Diggs
  • 129
  • 9
5
votes
2 answers

What is i.h.ah, o.h.ah and int86?

I am trying to understand a program to get arrow keys. Here is the code: int getkeys( ) { union REGS i,o; while(!kbhit( )); i.h.ah=0; int86(22,&i,&o); return(o.h.ah); } can someone please explain me…
Vipul
  • 53
  • 1
  • 6
5
votes
1 answer

Assembly: dynamic memory allocation without malloc and syscalls? [FreeDOS application]

My question is about the logic of dynamic memory allocation in assembly (particularly, MASM). There are lot of articles on this topic and all of them rely on the use of malloc or brk. However, according to my understanding, malloc as a part of C…
tenghiz
  • 239
  • 1
  • 10
5
votes
2 answers

How do I properly hook Interrupt 28h in assembly for DOS, and restore it?

I'm trying to set the handler of Interrupt 28h to my own routine, restore all the registers and flags involved, and restore the original Interrupt handler. I'm using NASM Assembler, under DOSBox and MS-DOS 6.22 in VirtualBox. I've thought about…
5
votes
1 answer

How to store 4 characters in a define doubleword in assembly language?

I'm currently doing assembly programming (16-bit) on DOSBox using MASM. var1 dd 'abcd' For the above code MASM is generating the error: A2010: syntax error What is wrong with the syntax? I am simply storing 4 characters in a doubleword. I am…
Hassaan Raza
  • 187
  • 3
  • 12
5
votes
3 answers

Compile and Link to .com file with Turbo C

I'm trying to compile and link a simple program to a DOS .com file using Turbo C compiler and linker. By that I try the simplest C-program I can think of. void main() {} Are there command line arguments to link to com files in the Turbo C Linker?…
user9343438
5
votes
1 answer

Why don't x86 16-bit addressing modes have a scale factor, while the 32-bit version has it?

I'm trying to figure out a reason for the scale factor not being present in the x86 16-bit addressing modes (MASM assembly). While the 32-bit and 64-bit addressing modes have a scale factor. Is there an actual reasoning behind this or it doesn't…
codezart
  • 67
  • 4