In real mode operating systems such as DOS, it was possible to overwrite sections of the operating system code if a program was not correctly written and this would crash the operating system and the computer required a reboot to run again.

If you were writing code that wrote directly to the CGA video memory area starting at B800 hex and the code had an loop error in it, it could overwrite the entire area above it until the maximum address range in DOS was reached. This overwrote everything including the BIOS settings in memory.

Protected mode memory is designed to prevent this from happening. A protected mode memory manager controls the address range that an application can write to and it will terminate the application if it tries to write in an address range that it does not have access to.

This style of memory management was available in 16 bit Windows but because of the method that 16 bit Windows simulated multitasking, it was possible to overwrite sections of memory that were owned by other applications or the operating system before the errant program crashed.

Depending on what was overwritten in the operating system, some other program that had no errors in it would call an operating system function and both the program and the operating system would crash, more often than not you received the "Blue screen of death" which at least told you something but if you were writing code and made a real mess of it, you received the "Black screen of death", an instant black screen and locked up machine which told you absolutely nothing.

Changes in hardware and the use of hardware based multitasking in 32 bit Windows made protected mode memory managers more reliable. The fundamentals of writing code in a protected mode operating system is to only read and write to memory that you application has access to.

Because assembler allows you to read and write to almost any address range, you need to take precautions on how you handle the addresses that you read and write to. If you allocate a 10k buffer to read to but you try and read 20k, when the address goes past the end of the 10k buffer, you will get a page read fault. You can also get into trouble if you incorrectly dereference a variable in a register and try and read or write to that address as it will be out of the address range that your program has access to.

Page read and write faults are exceptions that are passed from the operating system to the application that makes the error, if the exception is not handled by the application, the operating system closes the application. This offers some measure of protection from applications that make address range errors.

In a multitasking operating system, if this style of protection was not available when multiple programs were running, one program could overwrite the memory of another program that was running which would crash the other running program. The same problem would occur with operating system code, a program that overwrote part of the operating system code would crash the operating system.