Skip to content

数据处理的两个基本问题

计算机处理数据时,每条指令都必须明确两件事:

  1. 数据在哪里?(寄存器 / 内存 / 指令本身)
  2. 数据有多长?(字节 byte / 字 word)

数据位置的三种来源

来源汇编术语示例
指令本身(立即数)idatamov ax, 1
CPU 寄存器reg / sregmov ax, bx
内存单元段地址+偏移地址mov ax, ds:[0]

立即数(idata)

asm
mov ax, 1
add bx, 2000h
or  bx, 00010000b
mov al, 'a'         ; 字符也是立即数(编译器转换为 ASCII 码)

寄存器

asm
; reg:ax, bx, cx, dx, ah, al, bh, bl, ch, cl, dh, dl, sp, bp, si, di
; sreg:ds, ss, cs, es
mov ax, bx
mov ds, ax
push bx

内存(段地址:偏移地址)

asm
mov ax, ds:[bp]         ; (ax) = ((ds)*16 + (bp))
mov ax, es:[bx]         ; (ax) = ((es)*16 + (bx))
mov ax, ss:[bx+si]      ; (ax) = ((ss)*16 + (bx) + (si))
mov ax, cs:[bx+si+8]    ; (ax) = ((cs)*16 + (bx) + (si) + 8)

寻址方式汇总

方式示例说明
直接寻址[idata]偏移为常量,段地址在 ds
寄存器间接[bx]偏移在 bx/si/di/bp
寄存器相对[bx+idata] / 200[bx]偏移 = 寄存器 + 常量
基址变址[bx+si]偏移 = bx + si
相对基址变址[bx+si+idata]偏移 = bx + si + 常量

只有 bx, si, di, bp 可出现在 [...] 中。合法组合:bx+si, bx+di, bp+si, bp+di。 使用 bp 时,默认段寄存器为 SS(不是 DS)。

数据长度的指定方式

方式 1:寄存器名隐含长度

asm
; 字操作(16 位)
mov ax, 1
mov bx, ds:[0]
inc ax

; 字节操作(8 位)
mov al, 1
mov al, ds:[0]
inc al

方式 2:word ptrbyte ptr 显式指定

asm
; 字操作
mov word ptr ds:[0], 1
inc word ptr [bx]
add word ptr [bx], 2

; 字节操作
mov byte ptr ds:[0], 1
inc byte ptr [bx]
add byte ptr [bx], 2

当指令中没有寄存器参与时(纯内存操作),必须用 word ptr / byte ptr 显式指明,否则汇编器无法确定操作宽度。

方式 3:指令隐含

asm
push [1000h]    ; push 只进行字操作,无需指明

div 除法指令

asm
; 8 位除法:被除数 ax(16位),除数 8 位寄存器/内存
; 结果:商→AL,余数→AH
div bl
div byte ptr ds:[0]

; 16 位除法:被除数 dx:ax(32位),除数 16 位寄存器/内存
; 结果:商→AX,余数→DX
div bx
div word ptr ds:[0]

综合应用:用 [bx+idata+si] 访问结构体

下面的汇编代码对应 C 结构体字段更新:

c
struct company {
    char  name[3];    // 偏移 0x00,3字节
    char  host[9];    // 偏移 0x03,9字节
    int   range;      // 偏移 0x0C,2字节(字)
    int   income;     // 偏移 0x0E,2字节(字)
    char  product[3]; // 偏移 0x10,3字节
};
// dec.range = 38;
// dec.income += 70;
// dec.product = "VAX";
asm
mov ax, seg
mov ds, ax
mov bx, 60h                     ; 结构体首地址 → bx

mov word ptr [bx].0ch, 38       ; dec.range = 38
add word ptr [bx].0eh, 70       ; dec.income += 70

mov si, 0
mov byte ptr [bx].10h[si], 'V'  ; dec.product[0] = 'V'
inc si
mov byte ptr [bx].10h[si], 'A'  ; dec.product[1] = 'A'
inc si
mov byte ptr [bx].10h[si], 'X'  ; dec.product[2] = 'X'

规律: bx 定位整个结构体,idata(固定偏移)定位字段,si/di 定位字段内的数组元素。 类比 Rust:ptr.add(offset) → 汇编中的 [bx+idata]