今天继续学习汇编语言
转移指令的学习
jmp指令
使用jmp指令需要给出两种信息:
- 转移的目标地址
- 转移的距离(段间转移,段内转移,段内近转移)
根据位移进行的jmp指令
先对两种jmp进行介绍:
1 | jmp short 标号 |
功能为:(IP)=(IP)+ 八位位移(short指明)
- 8位指令=标号处的地址-jmp指令后的第一个字节的地址
- 八位位移的范围是-128~127
- 位移值是在编译程序的过程中计算出来的
1 | jmp near ptr 标号 |
功能为:(IP)=(IP) + 十六位位移(near ptr)
- 16位指令=标号处的地址-jmp指令后的第一个字节的地址
- 十六位位移的范围是-32768~32767
- 位移值是在编译程序的过程中计算出来的
我们可以通过下面的图片理解位移的计算过程:

指定转移目的地址的jmp指令
1 | jmp far ptr 标号 |
far ptr指明了指令用标号的段地址和偏移地址修改CS和IP
其机器码表现形式为指定目的地址
转移地址在寄存器中的jmp指令
1 | jmp (16位reg) |
功能:(IP)= (16位reg)
转移地址在内存中的jmp指令
1 | jmp word ptr 内存单元地址(段内转移) |
功能:从内存单元地址处开始存放一个字,是转移的目的偏移地址
1 | jmp dword ptr 内存单元地址(段间转移) |
功能:从内存单元地址处开始存放着两个字,高地址存放的字是转移的目的段地址,低地址是转移的目的偏移地址
- (CS) = (内存单元地址+2)
- (IP) = (内存单元地址)
jcxz指令
有条件转移指令,所有的有条件转移指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址,对IP修改范围为-128~127
1 | jcxz 标号 |
功能:当(cx)= 0 时,转移到标号处执行
- 8位位移=标号处的地址-jcxz指令后的第一个字节的地址
- 八位位移的范围是-128~127
- 位移值是在编译程序的过程中计算出来的
可以理解为
1 | if((cx)==0) jmp short 标号; |
loop 指令
所有的循环指令都是短转移,在对应的机器码中包含转移的位移,而不是目的地址
我们在之前学习过,可以理解为
1 | (cx)--; |
根据位移进行转移的意义
因为程序段在不同的机器中内存情况并不一样,如果指定内存地址进行跳转会发生错误
但如果根据位移进行索引,便可以准确的找到位置
地址间的相对关系是不会改变的
当然如果位移距离超出范围,会造成编译错误
offset
我们可以通过
1 | offset 标号 |
取到标号的偏移地址
实验九
参考链接:王爽《汇编语言》(第三版)实验9解析 - nojacky - 博客园 (cnblogs.com)
1 | assume cs:code |
效果图

CALL和RET指令
ret与retf
ret指令用栈中的数据,修改IP的内容,从而实现近转移 retf指令用战中的数据,修改CS和IP的内容,从而实现远转移
CPU执行ret: 1
2(IP) = ((ss)*16 + (sp))
(sp) = (sp) + 2 //pop IP
CPU执行retf:
1 | (IP) = ((ss)*16 + (sp)) |
call指令
总结一下就是:
- 将当前的IP或CS和IP压入栈中
- 转移
依据位移进行的call指令
1 | call 标号;将当前的IP压入栈中,转到标号处执行指令 |
执行过程如下:
1 | (sp) = (sp) -2 |
位移的计算同上
转移到目的地址在call指令中
1 | call far ptr 标号 |
相当于进行
1 | push CS |
转移地址在寄存器中的call指令
1 | call (16位reg) |
相当于进行
1 | push IP |
转移地址在内存中的call指令
(1)单字节索引
1 | call word ptr 内存单元地址 |
相当于进行:
1 | push IP |
(2)双字节索引
1 | call dword ptr 内存单元地址 |
相当于进行
1 | push CS |
使用
在学会ret和call的用法之后,我们可以使用下面的框架来模拟函数的调用
1 | assume cs:code |
mul指令
使用mul指令时,我们需要注意以下几点:
- 两个相乘的数要么都是八位,要么都是16位。如果是八位,则一个放在AL中,另一个在8位的reg或内存字节单元中;如果是16位,则一个在AX中,一个在16位的reg或者内存字单元中
- 如果是八位乘法,结果放在AX中;如果是十六位乘法,结果高位放在DX中,低位放在AX中
1 | mul reg/内存单元 |
实验十:编写子程序
显示字符串

1 | assume cs:code |
解决除法溢出问题
tips:
公式
X/N = int(H/N)*65536 + [rem(H/N)*65536+L]/N
X:被除数,范围[0,FFFFFFFF] N:除数,范围[0,FFFF] H:X的高16位,范围[0,FFFF] L:X的低16位,范围[0,FFFF] int():取商 rem():取余
参考链接:汇编语言(王爽第三版)实验10:编写子程序 - 筑基2017 - 博客园 (cnblogs.com)

1 | assume cs:code |
数值显示

暂时写不出来