数据处理的两个基本问题
计算机处理数据时,每条指令都必须明确两件事:
- 数据在哪里?(寄存器 / 内存 / 指令本身)
- 数据有多长?(字节 byte / 字 word)
数据位置的三种来源
| 来源 | 汇编术语 | 示例 |
|---|---|---|
| 指令本身(立即数) | idata | mov ax, 1 |
| CPU 寄存器 | reg / sreg | mov 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 ptr 和 byte 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]。