(十三)《汇编语言(王爽)》 | 实验 8:分析一个奇怪的程序


1. 预备知识

  • 汇编语言中的 nop 表示空指令,程序运行到此处时什么也不做,但会占用一个指令的时间。
  • 操作符 offset 的功能是取得指定标号的偏移地址。
  • CPU 在执行 jmp 指令时并不需要转移的目的地址,而是通过位移来定位转移后指令的地址。这样做的好处是,方便程序段在内存中的浮动装配,使带转移的程序在内存中的不同位置都可以正确执行,因为跳转指令只涉及目的地址的偏移而不是地址。
  • 其中,转移位移通过标号处的地址减去 jmp 指令后的第一个字节的地址得到,所以此时的位移可能为负数。在汇编语言中,转移的位移使用补码表示

2. 实验任务

分析下面程序,在运行前思考:这个程序可以正确返回吗?运行后再思考:为什么是这种结果?

assume cs:codesg
codesg segment
	mov ax,4c00h
	int 21h
start:
	mov ax,0
s:	
	nop
	nop
	mov di,offset s 
	mov si,offset s2
	mov ax,cs:[si]
	mov cs:[di],ax 
s0:	
	jmp short s 
s1:	
	mov ax,0
	int 21h
	mov ax,0
s2:
	jmp short s1
	nop
codesg ends
end start
  • end start 指明程序的入口为标号 start 处。

请添加图片描述

如上图,初始时 CS:IP 指向的地址为 076A:0005,即指令 mov ax,0000,为程序中 start 标号处的指令。

  • 标号 s 到标号 s0 间的代码,mov di,offset s 语句将标号 s 处指令的偏移地址赋值给寄存器 DI;mov si,offset s2 语句将标号 s2 处指令的地址赋值给寄存器 SI。后两条语句将标号 s2 处指令的地址赋值到标号 s 处。由于转移指令实际上使用的是机器码,所以实质是将机器码 EBF0 赋值到标号 s 处。而标号 s2 处指令长度为 2 字节,正好覆盖了标号 s 处两个 nop 指令的位置。
s:	
	nop					;空指令,占一个字节
	nop					;空指令,占一个字节
	mov di,offset s 	;将标号s处指令的偏移地址赋值到寄存器DI
	mov si,offset s2	;将标号s2处指令的偏移地址赋值到寄存器SI
	mov ax,cs:[si]		;将标号s2处指令的内容赋值到寄存器AX
	mov cs:[di],ax 		;将寄存器AX的内容赋值到标号s处,即两个nop指令(两字节)会被jmp short s1覆盖

此时,标号 s 处的指令变为:

请添加图片描述

  • 后续,再次执行指令标号 s0 处的指令 jmp short s。如上图,此时标号 s 处的指令变为 JMP 0000,即跳转到 076A:0000 处,而此处的指令为程序返回指令,程序正常返回。另一方面,FB 用于表示当前指令的性质,后两位表示转移的位移。在机器码中,位移使用补码表示,F6 对应的二进制是 1111 0000,对应的十进制数为 -10,所以 jmp 指令后一指令地址 076A:000A 向前偏移 10 个字节恰好是程序返回指令的地址 076A:0000。

3. 总结

本题的关键是将标号 s2 处的指令 jmp short s1 赋值到标号 s 处,由于转移指令使用位移表示,真正赋值的内容是 FBF6 而非 jmp short s1


  • 8
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值