Tag Archives: Assembly

The Complete 8086 Register Reference: AX, BX, CX, DX, Segment, Index & Pointer Registers Explained

The first assembly exercise most students write touches four registers: AX, CX, DX, and BX, usually in that order. By the second week, they’ve discovered that two of those registers have hidden obligations — MUL silently writes into DX, LOOP quietly owns CX — and the bugs that follow take an hour to diagnose. I wrote this reference after going through exactly that experience in a microprocessor architecture course in my third year, and again later when I was building a small 8086 emulator in C and needed a reliable answer to “which registers are valid inside an effective address?” — because getting that wrong produces an assembler error with no intuitive explanation.

The Intel 8086 has exactly 14 programmer-visible registers, each with a fixed width and — in many cases — aliases for 8-bit access. This reference was built from the Intel 8086 Microprocessor Datasheet (order number 231455), the 8086 Family User’s Manual (1979), and hands-on testing in DOSBox-X and EMU8086. Where behaviour differs between emulators and real hardware (FLAGS edge cases, segment override interactions), I’ve noted it explicitly.

Continue reading The Complete 8086 Register Reference: AX, BX, CX, DX, Segment, Index & Pointer Registers Explained

8086 Assembly Program to Compute the Power of a Number

This blog post details an 8086-assembly program that computes the power of a number, specifically baseexponent. This example demonstrates fundamental assembly concepts like loops, multiplication, and register manipulation to perform iterative arithmetic. Let’s get started!

data segment
    base dw 0003h
    exponent dw 0004h
    result dd ?
data ends

code segment
    assume cs:code, ds:data
start:
    ; Initialize data segment
    mov ax, data
    mov ds, ax

    ; Initialize result to 1 (R = B^0)
    mov word ptr result, 0001h
    mov word ptr result+2, 0000h

    ; Load base and exponent
    mov cx, exponent ; CX = exponent (loop counter)
    mov bx, base     ; BX = base

    cmp cx, 0000h
    je exit          ; If exponent is 0, result is already 1. Jump to exit.

power_loop:
    ; Multiply result by base
    ; The result is a 32-bit number in result[0] (lower word) and result[2] (upper word)
    ; Multiplication requires careful handling of the 32-bit result with a 16-bit multiplier.
    
    ; 1. Multiply the lower word of result by base
    mov ax, word ptr result ; AX = result[0]
    mul bx                  ; AX * BX -> DX:AX (32-bit product)
    push dx                 ; Save the higher word (DX) of the product
    mov word ptr result, ax ; Store the lower word (AX) of the product as the new result[0]

    ; 2. Multiply the upper word of result by base
    mov ax, word ptr result+2 ; AX = result[2]
    mul bx                    ; AX * BX -> DX:AX (32-bit product)
    
    ; 3. Add the two 16-bit 'carry' terms
    pop cx                    ; Retrieve the saved higher word (DX) from step 1 into CX
    add ax, cx                ; AX = AX + CX (Sum of two high words)
    adc dx, 0000h             ; DX = DX + 0 + Carry from the previous ADD (final carry from the 32-bit multiplication)
    
    ; 4. Store the final upper word
    mov word ptr result+2, ax ; Store AX as the new result[2]
    
    ; Handle the 32-bit overflow (DX is the final carry from the 32-bit multiplication)
    ; For a 32-bit result storage, this program assumes the result fits in 32-bits.
    ; If the power is large, overflow might occur, which is a limitation of this 32-bit storage approach.

    loop power_loop ; Decrement CX and jump back to power_loop if CX != 0

exit:
    int 3 ; Program termination
code ends
end start

Continue reading 8086 Assembly Program to Compute the Power of a Number

8086 MASM Assembly Program for Addition of Two 8-bit Numbers

This blog post will guide you through a MASM (Microsoft Macro Assembler) program that performs the addition of two 8-bit numbers. While this is a fundamental operation, it demonstrates crucial assembly programming concepts such as data handling, register usage, and memory storage. Let’s dive in!

Assembly Code

    .model small
    .data
    a db 09h
    b db 02h
    c dw ?
    
    .code
    main proc
        mov ax, @data
        mov ds, ax
        
        mov al, a
        mov bl, b
        add al, bl
        
        mov ah, 0
        mov c, ax
        
        int 3  ; Breakpoint interrupt
        
        mov ax, 4C00h  ; Exit program
        int 21h
    main endp
    
    end main
Continue reading 8086 MASM Assembly Program for Addition of Two 8-bit Numbers

Implementing Code Generator in C++

Code generation is the final back-end phase of a compiler. It takes the intermediate representation (IR) of the program — typically a sequence of three-address instructions — and translates each one into the equivalent target machine instructions. For a register-based architecture like the 8086, this means emitting MOV, ADD, SUB, MUL, DIV, and assignment instructions that use the AX and BX registers.

This C++ program reads three-address IR instructions from an input file (AIP.TXT), generates the corresponding 8086-style assembly code, and writes it to an output file (ANOP.TXT). Each IR instruction has the form:

operator  operand1  operand2  result
Continue reading Implementing Code Generator in C++

Implementing Macro Processor in C

A macro processor is a system program that expands macros in a source file before the code is assembled or compiled. A macro is a named block of assembly statements; every time its name appears in the program the processor substitutes the full block in place of the call. This eliminates repetition and makes large assembly programs easier to maintain.

This C implementation reads an assembly program from MACIN.TXT, detects MACRO / MEND delimiters to populate a Macro Definition Table (MDT), and then expands every macro call by inline-substituting the stored body. The expanded output is written to MACOUT.TXT and the raw MDT is saved to MDT.TXT.

Continue reading Implementing Macro Processor in C

Implementing Multi-pass Assembler in C

An assembler is a system software tool that translates an assembly language program (ALP) into machine code. A multi-pass assembler does this translation in two distinct passes over the source program. In Pass 1, it scans the ALP to build a Symbol Table (ST) that maps all labels and symbols to their memory addresses. In Pass 2, it uses the symbol table along with a Machine Opcode Table (MOT) and a Pseudo Opcode Table (POT) to generate the final object code.

This C implementation reads the assembly program from alp.txt, the machine opcode table from mot.txt, and the pseudo opcode table from pot.txt. The generated object code is written to OUTPUTNEW.txt and the symbol table is saved to SymT.txt.

Continue reading Implementing Multi-pass Assembler in C