本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
学习教材:《汇编语言(第4版)》王爽著 此笔记是书中内容+自我总结,方便查阅和复习 请支持原著
转移指令
指能修改IP或同时修改CS、IP的指令。由是否修改CS,前者称为段内转移,后者称为段间转移。
其中段内转移又可分为短转移和近转移,前者范围-128~127,后者-32768~32767,正负表示向前或向后移动字节数
@[toc]
一、操作符offset
offset 标号用于获取标号所指代码的偏移地址
例如:将s处指令复制到s0处(问题9.1)
assume cs:codesg
codesg segment
s: mov ax,bx
mov si,offset s ;获取地址
mov di,offset s0
;
mov ax,cs:[si] ;移动地址上的机器码,用寄存器过渡
mov cs:[di],ax
;
s0: nop
nop
codesg ends
end s
二、无条件转移指令——jmp
jmp是无条件转移指令,无条件即可直接转移,使用jmp需要给出两个信息
- 目标地址
- 转移距离(段间、段内短转移、段内近转移)
由于距离的不同,jmp细化为以下几种格式
Ⅰ、段内短转移——jmp short
jmp short 标号
CPU在执行jmp段内转移并不需要目标地址,而是在编译时计算出的位移量。实际上执行的是基于位移量的转移,而不是基于标号的转移。由机器码可以看出,jmp short 标号的机器码是EB 8位位移量,位移量=06-05=01
- 功能为令IP=IP+8位位移量
- 8位位移量=标号地址-jmp下一行代码首地址
- short指明是8位位移量,范围-128~127,以补码表示
- 位移量在编译时就已计算给出
Ⅱ、段内近转移——jmp near ptr
jmp near ptr 标号
- 功能为令IP=IP+16位位移量
- 16位位移量=标号地址-jmp下一行代码首地址
- near指明是16位位移量,范围-32768~32767,以补码表示
- 位移量在编译时就已计算给出
Ⅲ、段间转移——jmp far ptr
段间转移又被称为远转移
jmp far ptr 标号
段间转移改变了CS,由机器码可以看出,jmp far ptr 标号的机器码是EA IP CS,注意高地址存右端
- 功能为令CS=指定段地址,IP=指定偏移量
- 指定地址在编译时就已根据标号给出
Ⅳ、转移地址在寄存器中——jmp reg
jmp 16位reg
- 功能为令IP=(16位reg)
Ⅴ、转移地址在内存中——jmp X ptr
jmp X ptr
同样根据X,分为两种:
1、 地址在内存的段内转移——jmp word ptr
jmp word ptr SA:EA
- 功能为将从内存单元处存放的字作为偏移地址,IP=[X]
- 地址遵从寻址方式格式
2、 地址在内存的段间转移——jmp dword ptr
jmp word ptr SA:EA
- 功能为将从内存单元处存放的第一个字作为偏移地址,IP=[X];第二个字作为段地址,CS=[X+2]
- 地址遵从寻址方式格式
- 地址存储遵从高地址为段地址
- 类似于
jmp far ptr
检测点9.1
补全程序,使jmp执行后,CS:IP指向程序的第一条指令
assume cs:code
data segment
dd 12345678H
data ends
code segment
start: mov ax,data
mov ds,ax
mov bx,0
;
mov [bx],bx
mov [bx+2],cs
;
jmp dword ptr ds:[0]
code ends
end start
要指向第一条指令,无需改变CS,将IP设置为0即可。低位存IP,高位存CS
三、条件转移指令——jcxz
jcxz 标号
(感觉这个指令可以用来做while循环)
所有条件转移指令均为短转移,对应机器码中包含位移量
- 条件为如果CX=0,转移到标号,如果CX≠0,向下执行
- 功能为当CX=0,IP=IP+8位位移量
- 8位位移量=标号地址-jcxz下一行代码首地址
- 8位位移量,范围-128~127,以补码表示
- 位移量在编译时就已计算给出
检测点9.2
补全程序,运用jcxz实现内存2000H段中查找第一个值为0的字节,找到后将偏移地址存在dx中
assume cs:code
code segment
start: mov ax,2000h
mov ds,ax
mov bx,0
;
s: mov ch,0
mov cl,[bx] ;cx是16位寄存器,存字节只用一半
jcxz ok ;如果值是0,条件触发,跳转至存储偏移地址
inc bx ;如果值非0,偏移+1,循环下一字节
;
jmp short s
ok: mov dx,bx
mov ax,4c00h
int 21h
code ends
end start
四、循环指令——loop
loop 标号
所有循环指令均为短转移,对应机器码中包含位移量
- 条件为CX=CX-1,如果CX≠0,转移到标号,如果CX=0,向下执行
- 功能为CX=CX-1,当CX≠0,IP=IP+8位位移量
- 8位位移量=标号地址-loop下一行代码首地址
- 8位位移量,范围-128~127,以补码表示
- 位移量在编译时就已计算给出
检测点9.3
补全程序,运用loop实现内存2000H段中查找第一个值为0的字节,找到后将偏移地址存在dx中
assume cs:code
code segment
start: mov ax,2000h
mov ds,ax
mov bx,0
s: mov ch,0
mov cl,[bx]
;
inc cx ;先减一,如果是0要加一才能pass循环
;
inc bx
jmp short s
ok: dec bx ;自减1,bx--
mov dx,bx
mov ax,4c00h
int 21h
code ends
end start
后记
- 注意段间转移的本质是基于偏移量,而不是标号的当前地址
- 注意几种地址长度的限制
dec是inc的反向操作