Technical Explanation of the BOUND Instruction in Assembly Language

1. Instruction Overview

<span>BOUND</span> instruction is used to check whether an array index (subscript) is within predefined boundary limits. It is a hardware-supported mechanism for array boundary checking, designed to prevent programs from accessing memory outside of the array, thereby enhancing program robustness. If the check fails, the processor will generate an interrupt (exception), which usually results in the program being terminated by the operating system.

2. Instruction Format and Operands

<span>BOUND</span> instruction generally follows this format:

BOUND  OPRD1, OPRD2
  • **OPRD1 (Operand to be checked)**:

    • This is a register operand whose content represents the array index (subscript) to be checked.
    • On 16-bit processors like 8086/286, it must be a 16-bit register (such as <span>AX</span>, <span>BX</span>, <span>SI</span>, <span>DI</span>, etc.).
    • Starting from 32-bit processors like 80386 and later, it can also be a 32-bit register (such as <span>EAX</span>, <span>EBX</span>, <span>ESI</span>, <span>EDI</span>, etc.).
  • **OPRD2 (Boundary Operand)**:

    • Low 32 bits (low double word): stores the array’s starting subscript (<span>lower_bound</span>).
    • High 32 bits (high double word): stores the array’s ending subscript (<span>upper_bound</span>).
    • Low 16 bits (low word): stores the array’s starting subscript (<span>lower_bound</span>).
    • High 16 bits (high word): stores the array’s ending subscript (<span>upper_bound</span>).
    • This is a memory operand that defines the valid range of array subscripts [<span>lower_bound</span>, <span>upper_bound</span>] .
    • When <span>OPRD1</span> is a 16-bit register, <span>OPRD2</span> must be a 32-bit (4 bytes) memory operand.
    • When <span>OPRD1</span> is a 32-bit register, <span>OPRD2</span> must be a 64-bit (8 bytes) memory operand.
    • Important:<span>OPRD2</span> cannot be an immediate value or a register; it must point to a contiguous area in memory that stores the two boundary values.

3. Operations and Exceptions

The operation performed by this instruction can be understood as the following pseudocode:

if ( (OPRD1 < [OPRD2]) || (OPRD1 > [OPRD2 + sizeof(OPRD1)]) ) {
    RaiseException(Interrupt_5); // Raise boundary exception
}

Specifically, it checks whether the signed number in <span>OPRD1</span> satisfies:<span>lower_bound</span> <= <span>OPRD1</span> <= <span>upper_bound</span>

  • If the check passes: the instruction does nothing, and the program continues to execute the next instruction.
  • If the check fails (out of bounds): the CPU will immediately generate a <span>#BR</span> (boundary range exceeded) exception, with the interrupt type number 5. In most operating systems, this will directly cause the program to crash to prevent it from continuing to access illegal memory.

4. Impact on Flags

<span>BOUND</span> instruction does not affect any flags (such as zero flag ZF, carry flag CF, etc.).

5. Considerations and Modern Usage

  • Performance: On modern processors (Pentium 4 and later), the implementation of the <span>BOUND</span> instruction may be very inefficient, and its performance may not be as good as performing two comparisons manually using simple <span>CMP</span> (compare) and <span>Jcc</span> (conditional jump) instructions.
  • Usage habits: Due to performance reasons and the fact that high-level languages (like C++) typically perform software boundary checks in their runtime libraries, the <span>BOUND</span> instruction has rarely been explicitly used in modern programming. It is more of a legacy instruction used in specific safety-critical scenarios.
  • Exception handling: Type 5 exceptions are usually unrecoverable serious errors.

Code Example

The following is an example in 16-bit mode (or 32-bit mode using 16-bit operands) demonstrating how to safely access array elements.

.MODEL SMALL
.STACK 100h
.DATA

; Define an array containing 100 bytes
NUM = 100
ARRAY DB NUM DUP(0) ; Array, size 100 bytes

; Define the boundaries of the array subscript
; STV is a double word (32-bit) memory variable
;  Low word (STV[0]) = 0 (starting subscript)
;  High word (STV[2]) = NUM-1 (ending subscript, i.e., 99)
STV DW 0, NUM-1     ; Equivalent to DD 0, NUM-1's low and high words

.CODE
START:
    MOV AX, @DATA
    MOV DS, AX

    ; Assume the SI register contains the subscript to access
    ; This subscript may come from user input or complex calculations, we need to ensure it is safe
    MOV SI, 50       ; A valid subscript (0 <= 50 <= 99)

    ; !!! Critical safety check !!!
    BOUND SI, DWORD PTR STV ; Check if SI is within [0, 99] range
    ; If 50 is within this range, the check passes, continue execution
    ; If SI is 100 or -1, this will raise interrupt 5

    ; Safely use the subscript to access the array
    MOV AL, ARRAY[SI] ; Load the value of ARRAY[50] into AL
    ; ... operate on AL ...

    ; Another example: using a potentially dangerous subscript
    MOV SI, 150      ; An obviously out-of-bounds subscript (150 > 99)

    BOUND SI, DWORD PTR STV ; This instruction will raise interrupt 5, the program usually terminates here
    ; The following instruction will not be executed
    MOV AL, ARRAY[SI] ; Dangerous access is prevented by the BOUND instruction

    MOV AX, 4C00h    ; DOS exit function
    INT 21h          ; Normally the program exits here

END START

Example Explanation:

  1. Data Definition:

  • <span>ARRAY DB NUM DUP(0)</span>: Creates a 100-byte array.
  • <span>STV DW 0, NUM-1</span>: Defines two contiguous characters (32 bits total) in memory.<span>STV</span> at the offset address is <span>0</span> (starting subscript), <span>STV+2</span> at the offset address is <span>99</span> (ending subscript).
  • Safety Check:

    • First, set <span>SI</span> to <span>50</span>, which is a valid subscript.<span>BOUND SI, DWORD PTR STV</span> instruction checks whether <span>50</span> is within the <span>[0, 99]</span> range. The check passes, and the program continues.
    • Next, set <span>SI</span> to <span>150</span>, which is an invalid subscript.<span>BOUND</span> instruction fails the check, and the CPU generates a type 5 exception. In DOS or similar environments, this usually pops up an error message and terminates the program, thus preventing the subsequent illegal <span>MOV AL, ARRAY[SI]</span> instruction from executing, protecting the system from undefined behavior.
  • **<span>DWORD PTR</span>**: This operator tells the assembler that the memory unit following the <span>STV</span> label should be treated as a double word (32 bits), which is consistent with the <span>BOUND</span> instruction’s requirement for the second operand.

  • In summary, the <span>BOUND</span> instruction provides a hardware-level, efficient (on some older processors) method for array boundary checking, effectively capturing out-of-bounds access and immediately terminating the program, making it a useful tool for writing robust assembly code.

    Leave a Comment