同时修改 CS 和 IP : JMP 段地址:偏移地址 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
只修改 IP 内容: JMP 某一合法寄存器
DEBUG 操作:
R :查看、修改寄存器内容 R
D :查看内存中的内容 D 段地址:便宜地址
E :修改内存中的内容 E 段地址:偏移地址····数据····
U :将数据解析对应汇编
T :执行 CS:IP 处的指令
A :向内存形式写入汇编指令
P ush 寄存器 ;将一个寄存器的数据入栈。
SP=SP-2 向 SS:IP 送入数据
Pop 寄存器; 出栈,寄存器接受出栈的内容
从 SS:IP 读取数据 SP=SP+2
SS 和 SP 存放栈顶的段地址和偏移地址
DS 数据, CS:IP 代码, SS:IP 栈段。
编译步骤:
1. 编译,打开 masm.exe 输入 ASM 源文件的路径
2. 连接,打开 link.exe 打开 1 生成的连接文件, obj 扩展名的。输入路径。
mov cs, 循环的次数
s:
循环执行的程序段
L oop s
程序框架:
A ssume cs:code
C ode segment
数据····
S tart:
代码···
C ode ends
E nd start
A nd 和 or 指令
A nd 指令:逻辑与指令,按位进行运算,有 0 为 0 ,可以将操作对象的相应位设置为 0 ,其他位不变。
al=0011 0101b
and al, 1101 1111b =0001 0101
or 指令:逻辑或指令,按位进行或运算。可以将操作的相应位设置为 1 ,其他位不变。
A l=0001 0101
O r al, 0100 0000 = 0101 0101
BP 寄存器和 BX 寄存器相视
指令要处理的数据有多长
word ptr 指明了指令访问的内存单元是一个字单元
byte ptr 指明了指令访问的内存单元是一个字节单元
div 除法指令
AX(16 位 ) / 8 位 = AL( 商 ) ··· AH( 余数 )
【 DX( 高位 )AX( 低位 ) 】 / 16 位 = AX( 商 ) ··· DX( 余数 )
db 和 dw dd 定义数据
db 字节, dw 字 , dd 双字
dup 是一个操作符
db 3 dup (0) 定义了 3 个字节 0,0,0
db 3 dup(0,1,2) 定义了 9 个字节 0,1,2,0,1,2,0,1,2
格式:
db 重复的次数 dup (重复的字节数据)
dw 重复的次数 dup (重复的字数据)
db 重复的次数 dup (重复的双字数据)
转移指令:
依据位移进行转移:
jmp shor 标号(转移到标号处执行指令)
段内短转移, IP 的修改范围 -127~127
IP= ( IP ) +8 位位移
8 位位移 = 标号 -jmp 指令后的第一个字节的地址。 8 位位移用补码表示,由编译程序在编译时算出。
jmp near ptr 标号
它实现的是段内近转移
(IP)=(IP)+16 位位移
16 位移 = 标号处的地址 -jmp 指令后的第一个字节的地址
Near ptr 指明此处的位移为 16 位位移,进行的是段内近转移
修改范围 -32768~32767
转移的目的地址在指令中:
J mp far ptr 标号
实现的是段间转移,又称远转移
(CS)= 标号所在段的地址; (IP)= 标号在段中的偏移地址。
far ptr 指明了指令用标号的段地址和偏移地址修改 CS 和 IP. 。
转移地址在寄存器中:
jmp 16 位寄存器
(IP)=(16 位寄存器 )
转移指令在内存中:
jmp word ptr 内存单元地址(段内转移)
功能:从内存单元地址处存放一个字,是转移的目的偏移地址。
jmp dword ptr 内存单元地址(段间转移)
功能:存放两个字,高位目的地址,低位偏移地址
CS=( 内存单元地址 +2)
IP=( 内存单元地址 )
J cxz 指令
有条件转移指令,所有的有条件转移指令都是短转移,对应机器码中包含转移的位移,而不是目的地址。
J cxz 标号(如果 cx=0, 转移到标号处执行)
操作:当 cx=0 是, IP=IP+8 位位移
8 位位移 = 标号处的地址 -jcxz 指令后的第一个字节的地址
8 位位移的范围 -128~127 ,用补码表示
L oop 指令
L oop 标号( CX=CX-1 ) , 如果 CX 不等 0 ,转移到标号处执行
CX=XC-1
CX 不等 0 , IP=IP+8 位位移
R et 和 retf 指令
R et 指令用栈中的数据,修改 IP 的内容,从而实现近转移。
R etf 指令用栈中的数据,修改 CS 和 IP 的内容,从而实现近转移。
R et:
IP=CS*16+SP
SP=SP+2
R etf:
IP=SS*16+SP
SP+2
CS=SS*16+SP
SP=SP+2
CALL 指令
将当前的 IP 或 CS 和 IP 压入栈中,转移。相当:
PUSH IP
JMP NEAR PTR 标号
C all far ptr 标号,实现的是段间转移
SP=SP-2
SS*16+SP=CS
SP=SP-2
SS*16+SP=IP
相当:
PUSH CS
PUSH IP
JMP FAR PTR 标号
C all 16 位寄存器
SP=SP-2
SS*16+SP=IP
IP=16 位寄存器
相当:
PUSH IP
JMP 16 位寄存器
C all word ptr 内存单元地址
相当于:
PUSH IP
JMP WORD PTR 内存单元地址
C all dword ptr 内存单元地址
相当于:
P ush cs
P ush ip
J mp dword ptr 内存单元地址
C all 和 ret 的配合使用
A ssume cs:code
C ode segment
M ain :
:
C all sub1
:
:
M ov ax,4c00h
I nt 21h
S ub1 ::
:
R et
C ode ends
E nd main
M ul 指令乘法
AL ( 8 位) =5
M ul 6 ( 8 位)
AX= 积 30
AX(16 位 )=30
M ul 44 (16 位 )
D S= 积高位, AX= 积低位
标志寄存器 flag
ZF 标志
ZF=1, 结果等于 0
ZF=0 ,结果不等于 0
PF 标志
PF=0 ,最低有效字节 bit 位中 1 的个数为奇
PF=1 ,最低有效字节 bit 位中 1 的个数为偶
SF 标志
SF=1 ,结果为负
SF=0 ,结果不为负
有符号运算采用意义,无符号运算虽然可以改变 SF 的值,但是没有意义。
CF 标志
记录无符号运算的最高有效位,向更高位的进位值,或从更高位的借位值
OF 标志
OF=1 ,有符号运算发生溢出
OF=0 ,有符号运算没有溢出
adc 指令
带位加法,利用了 CF 位上记录的进位值。
A dc 操作对象 1 ,操作对象 2
操作对象 1= 操作对象 1+ 操作对象 2+CF
S bb 指令
带借位减法指令,利用了 CF 上记录的借位值。
S bb 操作对象 1 ,操作对象 2
操作对象 1= 操作对象 1- 操作对象 2-CF
C mp 指令
是比较指令,相当于减法指令,只是不保存结果。
C mp 操作对象 1 ,操作对象 2
操作对象 1- 操作对象 2 ,不保存结果,对标志寄存器进行设置。
ZF=1 ,结果相等
ZF=0 ,结果不相等
CF=1 , ax < bx
CF=0, ax>=0
CF=0,ZF=0, ax>bx
CF=0,ZF=1, ax<=bx
如果 SF=1 , OF=0 ,说明没有溢出,结果的正负 = 实际结果的正负。
以为 SF1 ,实际结果为负数,所以逻辑上真正的结果为负, ah<bh 。
如果 SF=1 , OF=1
OF=1 ,说明有溢出,逻辑上真正结果的正负不等实际结果的正负;
因为, SF=1 ,结果为负数。
如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正,这样 SF=1 , OF=1 ,说明 ah>bh. 。
如果 SF=0 , OF=1
OF=1 ,说明有溢出,逻辑上真正结果的正负不等实际结果的正负;
如果因为溢出导致了实际结果为正,那么逻辑上真正的结果必然位负数。
这样, SF=0 , OF=1 ,说明了 AH<BH 。
如果 SF=0 ,而 OF=0
OF=0 ,说明没有溢出,逻辑上真正的正负 = 实际结果的正负。
SF=0 ,实际结果非负,所以逻辑上真正的结果非负,所以 AH>=BH 。
检查比较结果的条件转移指令
指令 含义 检测的相关标志位
JE 等于则转移 ZF=1
JNE 不等于则转移 ZF=0
JB 低于怎转移 CF=1
JNB 不低于则转移 CF=0
JA 高于则转移 CF=0 , ZF=0
JNA 不高于则转移 CF=1 , ZF=1
DF 标志和串传送指令
DF=0 ,每次操作后 si ,di 递增。
DF=1, 每次操作后 si ,di 递减
正序 DF = 0 CLD
倒序 DF = 1 STD
Movsb 常和 ret 、 cx 配合使用
Movsb 就是把 ds:si 的内容传个 es:di , si 默认段地址是 DS , si 默认段地址是 ES.
SI------->DI
MOV AX, DATA
MOV DS, AX
MOV SI,0
MOV ES, AX
MOV DII16
MOV CX, 18
CLD
REP MOVSB
Pushf 和 popf
Pushf 将标志寄存器的值压栈,而 popf 是从栈中弹出数据,送入标志寄存器中。
Shl 和 shr 指令
Shl 和 shr 是逻辑位移指令
Shl 是逻辑左移指令
将一个寄存器或内存单元的数据向左移位
将最后移出的一位写入 CF 中
最后地位用 0 补充
如果移动位数大于 1 时,必须将移动位数放在 CL 中。
shr 是逻辑右移指令,它和 shl 所进行的操作刚好相反。
将一个寄存器或内存单元的数据向右移位
将最后移出的一位写入 CF 中
最后地位用 0 补充
MOV AL,0101 0000
MOV CL,3 移动的 3 位 ( 移动几位,如果大于 1 要用 CL)
SHL AL, CL
X 逻辑左移一位,相当于执行 X=X*2
X 逻辑右移一位,相当于执行 X=X / 2