1. 关于字型的补充
yte: 8位无符号整数, b表字节
sbyte: 8位有符号整数, s表有符号
word: 16位无符号整数
sword: 16位有符号整数
dword: 32位无符号整数, d表双字
sdword: 32位有符号整数, sd表有符号双字
qword: 64位整数, q表四字
tbyte: 80位(10字节)整数, t表10字节
伪指令
DB: 8位整数
DW: 16位整数
DD: 32位整数或实数
DQ: 64位整数或实数
DT: 定义80位(10字节)整数
8位通用寄存器:AH,AL,BH,BL,CH,CL,DH,DL
16位通用寄存器:AX,BX,CX,DX,SI,DI,SP,BP
32位通用寄存器:EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP
其他通用寄存器只能利用32或者16位名称为访问:
32位 16位
ESI SI
EDI DI
EBP BP
ESP SP
寄存器
EAX:累加(Accumulator)寄存器, 常用于函数返回值
EBX:基址(Base)寄存器, 以它为基址访问内存
ECX:计数器(Counter)寄存器, 常用作字符串和循环操作里的计数器
EDX:数据(Data)寄存器, 常用于乘除法和I/O指针
ESI:源变址寄存器
EDI:目的变址寄存器
ESP:堆栈(Stack)指针(Pointer)寄存器, 指向堆栈顶部
EBP:基址(Base)指针(Pointer)寄存器, 指向当前堆栈底部
EIP:指令寄存器, 指向下一条指令的地址
2. MOVSB 字节串传送指令
功能:将DS:SI指向的内存单元的一个字节的数据送入ES:DI指向的内存单元中。然后
如果DF=0, 则SI自增1, DI自增1;
如果DF=1, 则SI自减1, DI自减1
详细操作:
((ES)*16+(DI))=((DS)*16+(SI))(字节)
如果DF=0, 则(SI)=(SI)+1,(DI)=(DI)+1
如果DF=1, 则(SI)=(SI)-1,(DI)=(DI)-1
3. MOVSW 字串传送指令
功能:将DS:SI指向的内存单元的一个字的数据送入ES:DI指向的内存单元中。然后
如果DF=0, 则SI自增2, DI自增2;
如果DF=1, 则SI自减2, DI自减2
详细操作:
((ES)*16+(DI))=((DS)*16+(SI))(字)
如果DF=0, 则(SI)=(SI)+2,(DI)=(DI)+2
如果DF=1, 则(SI)=(SI)-2,(DI)=(DI)-2
4. REP 重复指令(与串操作指令配合使用)
REP指令要与MOVSB或者MOVSW配合使用, 如下:
REP MOVSB/MOVSW
功能:重复执行MOVSB/MOVSW指令, 每执行一次, CX减1。直到减到0, 停止重复。
以上指令等价于:
S: MOVSB/MOVSW
LOOP S
REP实现了对于CX个连续单位(字节/字)的串操作, 需要提前对DF位和CX进行合理设置
DF提供方向信息, CX提供长度信息
5. CLD/STD DF 方向标志位置位指令
CLD——将DF清0
STD——将DF置1
6. DF 标志位 direction flag 方向标志位
在串操作中, 指示串操作方向的标志位。
如果DF=0, 则SI、DI在串操作后自增
如果DF=1, 则SI、DI在串操作后自减
7. 综合练习
assume cs:code, ss:stack, ds:data
data segment
db 128 dup (0)
data ends
stack segment stack
db 128 dup (0)
stack ends
; 0E34:0000 B82C0E MOV AX,0E2C
; 0E34:0003 8ED0 MOV SS,AX
; 0E34:0005 BC8000 MOV SP,0080
; 0E34:0008 E81200 CALL 001D
; 0E34:000B B8004C MOV AX,4C00
; 0E34:000E CD21 INT 21
; 0E34:0010 B80010 MOV AX,1000
; 0E34:0013 B80010 MOV AX,1000
; 0E34:0016 B80010 MOV AX,1000
; 0E34:0019 B80010 MOV AX,1000
; 0E34:001C 90 NOP
; 0E34:001D 8CCB MOV BX,CS
; 0E34:001F 8EDB MOV DS,BX
; -u
; 0E34:0021 BE1000 MOV SI,0010
; 0E34:0024 BB0000 MOV BX,0000
; 0E34:0027 8EC3 MOV ES,BX
; 0E34:0029 BF007E MOV DI,7E00
; 0E34:002C B90C00 MOV CX,000C
; 0E34:002F FC CLD
; 0E34:0030 F3 REPZ
; 0E34:0031 A4 MOVSB
; 0E34:0032 C3 RET
code segment
start:
mov ax, stack
mov ss, ax
mov sp, 128
call cpy_Boot
mov ax, 4c00h
int 21h
; ------------------------------
; 充当数据 B80010
Boot: ; 0010
mov ax,1000H
mov ax,1000H
mov ax,1000H
mov ax,1000H
Boot_end: ; 001C
nop
; ------------------------------
cpy_Boot: ; 001D
mov bx,cs
mov ds,bx
mov si,OFFSET Boot
mov bx,0
mov es,bx
mov di,7E00H
mov cx,OFFSET Boot_end - Boot ; 001c - 0010 = 0c = 12byte, 获取到数据在哪里=> 4行 B80010 MOV AX,1000
cld ; 将DF清0
; 将DS:SI指向的内存单元的一个字节的数据送入ES:DI指向的内存单元中
; 如果DF=0, 则SI自增1, DI自增1
; 如果DF=1, 则SI自减1, DI自减1
; AX=0E2C BX=0000 CX=000C DX=0000 SP=007E BP=0000 SI=0010 DI=7E00
; DS=0E34 ES=0000 SS=0E2C CS=0E34 IP=0030 NV UP EI PL NZ NA PO NC
; 0E34:0030 F3 REPZ
; 0E34:0031 A4 MOVSB
; -d ds:10
; 0E34:0010 B8 00 10 B8 00 10 B8 00-10 B8 00 10(12bytes) 90 8C CB 8E ................
; -u ds:10
; 0E34:0010 B80010 MOV AX,1000
; 0E34:0013 B80010 MOV AX,1000
; 0E34:0016 B80010 MOV AX,1000
; 0E34:0019 B80010 MOV AX,1000
; 0E34:001C 90 NOP
; 0E34:001D 8CCB MOV BX,CS
; -d es:7e00
; 0000:7E00 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
rep movsb ; 直到 cx = 0
; -d es:7e00
; 0000:7E00 B8 00 10 B8 00 10 B8 00-10 B8 00 00 00 00 00 00 ................
; -r ; 当CX = 0 时
; AX=0E2C BX=0000 CX=0001 DX=0000 SP=007E BP=0000 SI=001B DI=7E0B
; DS=0E34 ES=0000 SS=0E2C CS=0E34 IP=0030 NV UP EI PL NZ NA PO NC
; 0E34:0030 F3 REPZ
; 0E34:0031 A4 MOVSB
; -t
; AX=0E2C BX=0000 CX=0000 DX=0000 SP=007E BP=0000 SI=001C DI=7E0C
; DS=0E34 ES=0000 SS=0E2C CS=0E34 IP=0032 NV UP EI PL NZ NA PO NC
; 0E34:0032 C3 RET
; -d es:7e00
; 0000:7E00 B8 00 10 B8 00 10 B8 00-10 B8 00 10 00 00 00 00 ................
; -u es:7e00
; 0000:7E00 B80010 MOV AX,1000
; 0000:7E03 B80010 MOV AX,1000
; 0000:7E06 B80010 MOV AX,1000
; 0000:7E09 B80010 MOV AX,1000
ret
code ends
end start
8. 使用 rep movsb、cld 实现数据正向传送
assume cs:code, ss:stack, ds:data
; =================================================================
data segment
db 'Welcome to masm!'
db 16 dup (0)
data ends
; =================================================================
stack segment stack
db 128 dup (0)
stack ends
; =================================================================
code segment
start:mov ax, stack
mov ss, ax
mov sp, 128
mov ax, data
mov ds, ax
mov si, 0
mov es, ax
mov di, 16
mov cx, 16
cld ; 将DF设置为0, 正向传送
rep movsb
mov ax, 4c00h
int 21h
code ends
end start
9. 使用 rep movsb、cld 实现数据反向传送
assume cs:code, ss:stack, ds:data
; =================================================================
data segment
db 16 dup (0)
data ends
; =================================================================
stack segment stack
db 128 dup (0)
stack ends
; =================================================================
code segment
start:mov ax, stack
mov ss, ax
mov sp, 128
mov ax, 0F000H
mov ds, ax
mov si, 0FFFFH
mov ax, data
mov es, ax
mov di, 15
mov cx, 16
std
rep movsb
mov ax, 4c00h
int 21h
code ends
end start
10. CLI/STI 中断标志位 IF
CLI: 清除标志位IF, 即设置为0(DI), 禁止中断发生
STI: 设置标志位IF, 即设置为1(EI), 允许中断发生
- 在改变SS:SP之前,必须用cli指令屏蔽中断,然后等操作执行完立即用sti指令恢复
- SS:SP需要设置在空闲的内存地址,不要建立在其他的程序(尤其是系统的)代码区