Assembly-Lab 8

深入理解JMP指令
本文详细解析了JMP指令在汇编语言中的工作原理,通过具体实验程序,展示了向前和向后转移时,汇编编译器如何计算位移量,并生成相应的机器指令。深入探讨了masm.exe在编译过程中的处理方式。

实验8

分析下面程序,这个程序可以正确返回吗?

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

实验分析

主要考察对于jmp指令的原理的理解

    mov	di,offset s
    mov	si,offset s2
    mov	ax,cs:[si]
    mov	cs:[di],ax

这4条指令的作用就是将s2标号地址的指令赋值到s标号地址

  1. 直接从s0标号地址指令开始分析

    此时程序会跳转到s标号位置,而s标号地址我们已经知道现在存储的时s2标号地址指令

  2. 这里就考察对于jmp 转移位移的指令的原理的理解

    先贴出其对应的机器指令
    在这里插入图片描述

    1. 首先先回顾CPU执行指令的过程,比如下面中的指令EB03

在这里插入图片描述
在这里插入图片描述

  1. jmp 转移位移指令的转移位移的计算方法

在这里插入图片描述

  1. 清楚了上面的知识,再来观察ip

在这里插入图片描述

  1. 程序经过编译之后

    • s0标号地址的jmp指令计算的转移位移为F0(补码)=-16

    • s2标号地址的jmp指令计算的转移位移是程序还没有运行前的,所以转移位移为F6(补码)=-10

    所以当执行完mov cs:[di],ax时,ip=16h

    之后读取jmp short s后,ip+=2,等于18h也就是24

    之后执行指令ip+=-16,等于8

    之后再读取s标号地址指令,注意此时已经为EB F0(也就是jmp short s1编译的机器指令),ip+=2,等于0ah也就是10

    之后再执行指令ip+=-10,等于0

  2. 程序执行之后变为
    在这里插入图片描述

汇编编译器(masm.exe)对jmp的相关处理

1.向前转移

s:	.
	.
	jmp s ( jmp short s、 jmp near ptr s、 jmp far ptr s)

编译器中有一个地址计数器(AC,编译器在编译程序过程中,每读到一个字节AC就加1。当编译器遇到一些伪操作的时候,也会根据具体情况使AC增加,如db、dw等。
在向前转移时,编译器可以在读到标号s后记下AC的值as,在读到jmp….s后记下AC的值aj。编译器就可以用as-aj算出位移量disp。

2.向后转移

jmp s( jmp short s、 jmp near ptr s、 jmp far ptr s)
	.
	.
s:	

在这种情况下,编译器先读到jmp….s指令。由于它还没有读到标号s,所以编译器此时还不能确定标号s处的AC值。也就是说,编译器不能确定位移量disp的大小。

此时,编译器将jmp….s指令都当作 jmp short s来读取,记下jmp….指令的位置和AC的值a,并作如下处理。

  • 对于 jmp short s,编译器生成EB和I个nop指令(相当于预留1个字节的空间,存放8位disp);
  • 对于jmp s和 jmp near ptr s,编译器生成EB和两个nop指令(相当于预留两个字节的空间,存放16位disp)
  • 对于 jmp far ptr s,编译器生成EB和4个nop指令(相当于预留4个字节的空间,存放段地址和偏移地址)

作完以上处理后,编译器继续工作,当向后读到标号s时,记下AC的值as,并计算出转移的位移量:disp=as-aj

基于模拟退火的计算器 在线运行 访问run.bcjh.xyz。 先展示下效果 https://pan.quark.cn/s/cc95c98c3760 参见此仓库。 使用方法(本地安装包) 前往Releases · hjenryin/BCJH-Metropolis下载最新 ,解压后输入游戏内校验码即可使用。 配置厨具 已在2.0.0弃用。 直接使用白菜菊花代码,保留高级厨具,新手池厨具可变。 更改迭代次数 如有需要,可以更改 中39行的数字来设置迭代次数。 本地编译 如果在windows平台,需要使用MSBuild编译,并将 改为ANSI编码。 如有条件,强烈建议这种本地运行(运行可加速、可多次重复)。 在 下运行 ,是游戏中的白菜菊花校验码。 编译、运行: - 在根目录新建 文件夹并 至build - - 使用 (linux) 或 (windows) 运行。 最后在命令行就可以得到输出结果了! (注意顺序)(得到厨师-技法,表示对应新手池厨具) 注:linux下不支持多任务选择 云端编译已在2.0.0弃用。 局限性 已知的问题: - 无法得到最优解! 只能得到一个比较好的解,有助于开阔思路。 - 无法选择菜品数量(默认拉满)。 可能有一定门槛。 (这可能有助于防止这类辅助工具的滥用导致分数膨胀? )(你问我为什么不用其他语言写? python一个晚上就写好了,结果因为有涉及json读写很多类型没法推断,jit用不了,算这个太慢了,所以就用c++写了) 工作原理 采用两层模拟退火来最大化总能量。 第一层为三个厨师,其能量用第二层模拟退火来估计。 也就是说,这套方法理论上也能算厨神(只要能够在非常快的时间内,算出一个厨神面板的得分),但是加上厨神的食材限制工作量有点大……以后再说吧。 (...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值