About Me
Welcome to my blog! This is where I collect my observations and notes on programming and technology. The main subjects range from implementation details to broader ideas about programming.
Main Topics
- Engineering Projects: Exploring implementation details and how technical systems work.
- C/C++: Notes on language features and programming techniques.
- The Programmer’s Perspective: Ideas about developing a career and a way of thinking as a programmer.
For more, visit the categories page.
Contact
If you have questions or would like to discuss something, please get in touch through the About page.
Thank you for reading and for your support. I hope these notes help you on your own technical journey!
Where Assembly Begins: Notes to My Younger Self
Working in DOSBox
Use MOUNT to expose a host directory as a DOSBox drive, then enter C: to switch to it. Assemble an .asm file with MASM to produce an .obj, link the object to produce an .exe, and run the executable. Keeping the source near the tools simplifies paths, although it is not a requirement.
Within the mounted directory, EDIT can create the source. MASM accepts a filename or an appropriate full path. In the simple workflow here, object and executable outputs appear in the current directory; default extensions can often be omitted at the prompts.
To trace an executable, run debug filename.exe. DEBUG lets us inspect registers, disassemble instructions, and step through execution.
Early addressing notes
MASM syntax and DEBUG’s assembler syntax are not identical. The original experiments found that a bare numeric expression in brackets could be treated differently than expected. Explicit notation such as ds:[0006h], or loading an offset into BX and using [bx], makes the intended memory reference clearer. Check the assembler’s actual syntax rather than treating every bracketed number as universally equivalent.
In 16-bit addressing, [ax] is not an available ordinary addressing form. [bx] is one, and BP, SI, and DI participate in other valid combinations. Most data references default to DS, but BP-based addressing normally uses SS; string operations have their own segment rules. A segment override can make an intended choice explicit.
ES, the extra segment register, is often useful as a second data-segment pointer. A MOV cannot directly copy a segment register into another segment register; use an allowed intermediate.
Familiar register roles
AX often participates in DOS service calls. For example:
1 | mov ax,4c00h |
Here AH = 4Ch selects DOS process termination and AL supplies the exit code. Substituting another register does not satisfy that service interface. BX commonly holds an address offset, and CX supplies the count for LOOP.
SS:SP identifies the stack top. If a data segment aliases the same memory, writes through it can corrupt stack contents. The original experiment with popping into overlapping storage is a reminder to reason about physical addresses and stack movement, not merely different segment names.
DEBUG’s t and p
Trace (t) executes an instruction and can enter calls or interrupt handlers. Proceed (p) can step over calls, interrupts, and repeated operations, depending on the command implementation. For ordinary instructions they often appear similar. At int 21h, proceed is useful when the intention is to complete the DOS service rather than inspect its internals.
Questions collected for later study
These early notes raised several topics for future experiments:
- Convert character case with
ANDandOR, distinguishing numeric six from the ASCII character'6'. - Use
DB,DW,DD, andDUPto define data and repeated storage. - Compare assembly addressing with C pointers and arrays.
- Learn register combinations for
DIVand inspect instruction micro-operations. - Investigate paragraph alignment in segment allocation: a small declaration can occupy a larger aligned region.
- Study
NOP, jump encodings, the interrupt vector table, and text video memory near physicalB8000h.
BIOS int 10h provides video services; direct writes to text video memory are another mechanism in a suitable video mode. They should not be confused with a requirement to call a BIOS service after every memory write.
Jumps and relocation
Ordinary source code cannot assign to IP with a MOV; control-transfer instructions update it. Labels are supported by assemblers and are the normal way to express destinations. The original reservation about labels reflects a tool or exercise context rather than an architectural prohibition.
Short and near relative branches encode signed displacements. This helps code remain usable when a whole region moves while preserving relative layout. Short signed displacements span -128 to 127 bytes; a 16-bit displacement has the corresponding signed range.
An indirect near jump reads an offset from memory; an indirect far jump reads an offset and segment. Moving only a jump’s bytes can change the destination of a relative jump because the displacement is interpreted from its new location. Moving the instruction and target together may preserve it. An absolute destination can also need relocation, so absolute jumps are not automatically portable.
If a hexadecimal literal begins with a letter, prefix it with zero in MASM-style syntax.
Division overflow
For an unsigned 16-bit divisor, DIV uses DX:AX as the dividend, returns the quotient in AX, and the remainder in DX. For an 8-bit divisor, the dividend is AX, the quotient is AL, and the remainder is AH. A quotient can exceed the result register’s capacity even when the dividend fits its input registers; division by zero is another exceptional case.
A more concrete explanation of mounting
My original setup used:
1 | mount C G:\develop\DOS\root\DOSBox-0.74-3\MASM |
The analogy to C’s #define was a beginner’s way to think about replacing a long name with a short one. More precisely, DOSBox maps a host directory into its emulated filesystem as a drive. After switching to C:, commands operate in that exposed directory without repeatedly typing the host path.
Inspecting general registers
After mounting, enter debug, then r. This displays register contents. The familiar data registers are AX (accumulator), BX (base), CX (count), and DX (data). The suffix mnemonic in the original notes is a memory aid, not a formal rule defining every general-purpose register; SI, DI, BP, and SP also have important general register roles.
How CS:IP finds instructions
The CPU follows its execution state rather than knowing a program’s meaning or complete extent. CS supplies a code-segment value and IP the offset of the next instruction. On the 8086, the physical address is formed from segment × 16 + offset, within the machine’s address width. The two registers complement each other.
Is MOV always three bytes?
Use u cs:0000 in DEBUG to view machine bytes interpreted as assembly. The result lets us compare source, encoded instructions, and disassembly.
A statement that MOV occupies three bytes may describe one particular instruction form. It is not a universal length. Try register-to-memory, memory-to-register, immediate-to-register, and register-to-register forms. Then compare their byte counts. ADD also has several encodings.
These observations were recorded on July 14, 2023, at approximately 00:41.
What determines instruction size?
The original analogy compares an instruction to a car plus its passengers and cargo. The useful idea is that the mnemonic alone does not determine the total. Opcode form, operand size, ModR/M information, displacement, immediate, and prefixes can all contribute. The exact encoding rules are more precise than simply saying larger operands always produce longer instructions, but examining several encodings makes the principle concrete.
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. All the images used in the blog are my original works or AI works, if you want to take it,don't hesitate. Thank you !