学汇编,记笔记(八)《汇编语言)》王爽著——转移指令_jmp、jcxz和loop

187 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

学习教材:《汇编语言(第4版)》王爽著 此笔记是书中内容+自我总结,方便查阅和复习 请支持原著

转移指令

指能修改IP或同时修改CS、IP的指令。由是否修改CS,前者称为段内转移,后者称为段间转移。

其中段内转移又可分为短转移和近转移,前者范围-128~127,后者-32768~32767,正负表示向前或向后移动字节数

@[toc]

章末实验8 章末实验9

一、操作符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需要给出两个信息

  1. 目标地址
  2. 转移距离(段间、段内短转移、段内近转移)

由于距离的不同,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

后记

  • 注意段间转移的本质是基于偏移量,而不是标号的当前地址
  • 注意几种地址长度的限制
  • decinc的反向操作