汇编语言:call、call far ptr、call word ptr、call dword ptr、call 寄存器

news2024/11/17 1:37:31

引言

        call指令是转移指令,CPU执行call指令,进行两步操作:

(1)将当前IP或当前CS和IP压入栈中
(2)转移。call指令不能短转移,除此之外,call指令转移的方法跟jmp指令的原理相同。

1. call 标号

        call 标号 是根据位移进行进转移的call指令,实现的是段内转移,指令功能:将当前IP压入栈中,然后转移到标号处执行指令。其对寄存器操作的原理如下:

(1)(sp) = (sp) - 2                       ;栈顶开辟2个字节的空间
         ((ss)*16+(sp)) = (IP)             ;栈顶的值 = (IP)
(2)(IP) = (IP) + 16位位移           ;修改IP值

tips:

16位位移 = 标号处的地址 - call指令后的下一条指令的首地址
16位位移用补码的形式表示,范围在 -32768 ~ 32767
16位位移由编译器编译时算出

所以,CPU执行call 标号指令时,相当于执行:

(1)push IP
(2)jmp near ptr 标号

assume cs:code, ss:stack
stack segment
    db 16 dup (0)
stack ends
code segment
start:
    mov ax, 0
    call s      ;执行该指令的内部逻辑步骤:(1) pop IP(即指向inc ax指令的首地址); 
                ;                       (2)IP = IP + (s标号处指令的首地址 - call s指令的下一条指令(即 inc ax指令)的首地址)
    inc ax
s: 
    pop ax

    mov ax, 4c00h
    int 21h
code ends
end start

从以上运行结果分析

(1)16位位移 = s标号处指令的首地址 - call s指令的下一条指令的首地址 = 0007h - 0006h = 0001h
(2)call s,编译成 call 0007,对应的机器码:E80100(低字节序),其中最低位:E8是操作码,0001是16位位移
(3)执行 call s 指令,IP = 0006h压入栈,然后 IP = IP + (0007h - 0006h) = 0006h + 0001h = 0007h
(4)程序转移到s标号处,即pop ax 处执行,得到:ax = 0006h

2. call far ptr 标号

        call far ptr 标号 是转移的目的地址在指令中的call指令,实现的是段间转移,指令功能:将当前CS压入栈中,然后再将当前IP压入栈中,最后转移到标号处执行指令。其对寄存器操作的原理如下:

(1)(sp) = (sp) - 2                       ;栈顶开辟2个字节的空间
         ((ss)*16+(sp)) = (CS)            ;当前栈顶的值 = (CS)
         (sp) = (sp) - 2                       ;栈顶再开辟2个字节的空间
         ((ss)*16+(sp)) = (IP)             ;当前栈顶的值 = (IP)
(2)(CS) = 标号所在段的段地址
         (IP) = 标号在段中的偏移地址

所以,CPU执行call far ptr 标号指令时,相当于执行:

(1)push CS
         push IP
(2)jmp far ptr 标号

assume cs:code, ss:stack
stack segment
    db 16 dup (0)
stack ends
code segment
start:
    ;初始化栈
    mov ax, stack       ;ax = 204D
    mov ss, ax          ;初始化栈:设置栈段地址ss = 204D
    mov sp, 16          ;设置栈顶地址sp = 16

    mov ax, 0
    call far ptr s      ;(1)push CS (2)push IP (3)CPU转移到标号S处执行指令
    inc ax
s:
    pop ax              ;IP的值出栈
    add ax, ax
    pop bx              ;CS的值出栈
    add ax, bx          
    mov ax, 4c00h
    int 21h
code ends
end start

(1)程序分析

        程序包括16个字节的栈段(stack segment ... stack end)和代码段 (code segment ... code ends) 。end start 指明程序开始执行时,从代码段的 start 标号处开始执行,start标号在代码段中的首地址处,所以 IP = 0000h

(2)代码执行过程分析:

a) 调试程序(父进程)把我们的程序(子进程)加载进内存,并设置CS:IP = 204E:0000,CPU开始执行我们的指令代码。

b) mov ax, stack       ;ax = 204Dh
    mov ss, ax            ;初始化栈:设置栈段地址ss = 204Dh
    mov sp, 16           ;设置栈顶地址sp = 16

c) mov ax, 0             ; ax = 0h
    call far ptr s          ; (1)push CS (2) push IP (3)CPU转移到标号S处执行指令
    inc ax

d) s:
    pop ax              ;IP的值出栈,ax = 0010h
    add ax, ax        ; ax = 0020h
    pop bx              ;CS的值出栈,bx = 204Eh
    add ax, bx        ; ax = ax + bx = 0020h + 204Eh = 206Eh       

3. call 16位寄存器

        call 16位寄存器 是转移的目的地址在寄存器中的call指令,实现的是段内转移,指令功能:将当前IP压入栈中,然后转移到寄存器中指明的目的地址处执行指令。其对寄存器操作的原理如下:

(1)(sp) = (sp) - 2                       ;栈顶开辟2个字节的空间
         ((ss)*16+(sp)) = (IP)             ;栈顶的值 = (IP)
(2)(IP) = (16位寄存器)               ;修改IP值

CPU执行call 16位寄存器指令时,相当于执行:

(1)push IP
(2)jmp 16位寄存器

assume cs:code, ss:stack
stack segment
    db 16 dup (0)
stack ends
code segment
start:
    ;初始化栈
    mov ax, stack
    mov ss, ax
    mov sp, 16

    mov ax, 14
    call ax         ;(1)push IP (2)CPU转到 (ax寄存器) 处执行指令
    inc ax
    mov bp, sp
    add ax, [bp]

    mov ax, 4c00h
    int 21h
code ends
end start

(1)程序分析

        程序包括16个字节的栈段(stack segment ... stack end)和代码段 (code segment ... code ends) 。end start 指明程序开始执行时,从代码段的 start 标号处开始执行,start标号在代码段中的首地址处,所以 IP = 0000h

(2)代码执行过程分析:

a) 调试程序(父进程)把我们的程序(子进程)加载进内存,并设置CS:IP = 204E:0000,CPU开始执行我们的指令代码。

b) mov ax, stack       ;ax = 204Dh
    mov ss, ax            ;初始化栈:设置栈段地址ss = 204Dh
    mov sp, 16           ;设置栈顶地址sp = 16

c) mov ax, 14           ; ax = 000Eh
    call ax                  ; (1)push IP (2)CPU转到 (ax寄存器) 处执行指令
    inc ax

d) mov bp, sp           ; bp = sp = 000Eh
    add ax, [bp]          ; ax = ax + ss:[bp] = 000Eh + 000Dh = 001Bh

4. call word ptr 内存单元地址

        call word ptr 内存单元地址 是转移的目的地址在内存中的call指令,实现的是段内转移,指令功能:将当前IP压入栈中,然后转移到内存中指明的目的地址处执行指令。其对寄存器操作的原理如下:

(1)(sp) = (sp) - 2                       ;栈顶开辟2个字节的空间
         ((ss)*16+(sp)) = (IP)             ;栈顶的值 = (IP)
(2)(IP) = (内存单元地址)           ;修改IP值

CPU执行 call word ptr 内存单元地址 指令时,相当于执行:

(1)push IP
(2)jmp word ptr 内存单元地址

例如,下面的指令

mov sp = 16
mov ax = 0008h
mov ds:[0], ax
call word ptr ds:[0]

执行后,(IP) = 0008h, (sp) = 000Eh

5. call dword ptr 内存单元地址

        call dword ptr 内存单元地址 是转移的目的地址在内存中的call指令,实现的是段间转移,指令功能:将当前CS压入栈中,然后再将当前IP压入栈中,最后转移到内存中指明的目的地址处执行指令,在指明的内存单元地址中,高字(2字节)内存中存放的是目的段地址(CS),低字(2字节)内存中存放的是目的偏移地址(IP)。其对寄存器操作的原理如下:

(1)(sp) = (sp) - 2                       ;栈顶开辟2个字节的空间
         ((ss)*16+(sp)) = (CS)            ;当前栈顶的值 = (CS)
         (sp) = (sp) - 2                       ;栈顶再开辟2个字节的空间
         ((ss)*16+(sp)) = (IP)             ;当前栈顶的值 = (IP)
(2)(CS) = 内存单元地址[2]
         (IP) = 内存单元地址[0]

所以,CPU执行call dword ptr 内存单元地址指令时,相当于执行:

(1)push CS
         push IP
(2)jmp dword ptr 内存单元地址

例如,下面的指令

mov sp, 16
mov word ptr ds:[0], 0
mov ax, 204Eh
mov ds:[2], ax
call dword ptr ds:[0]

执行后,(CS) = 204Eh, (IP) = 0000h, (sp) = 000Ch

参考文献

《汇编语言(第4版)》王爽

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2049658.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

柔性超级电容器咋储能?生物聚合物在其中起啥作用?有啥挑战?

*本文只作阅读笔记分享* 一、引言 随着对化石燃料影响的日益关注,开发用于先进电化学能量存储设备的绿色和可再生材料变得至关重要。超级电容器因其出色的寿命、安全性和宽温度操作范围等优势而成为有前途的储能候选者。柔性超级电容器特别适合为轻质可穿戴电子设…

xss GAME (xss漏洞攻击1-8)

目录 xss网页链接 第一关 第二关 第三关 ​编辑第四关 ​编辑第五关 ​编辑第六关 第七关 第一种 Function构建函数 第二种 tostring parseInt 第三种 silce() ​编辑第八关(安全过滤框架 dom破坏) xss网页链接 XSS Game - Learning XSS Ma…

linux之网络子系统-GSO/TSO 源码分析

一、GSO/TSO GSO 目前在内核5.10.* 版本时,已经是合入主线,就是对TCP/UDP都支持并且在网络协议栈GSO功能是默认打开的。虽然可以通过ethtool -K 网卡名 gso off 关闭,但是在L3/L4还是走GSO逻辑,关不掉。我目前是没有找到内核源码…

NextJs - 服务端/客户端组件之架构多样性设计

NextJs - 服务端/客户端组件之架构多样性设计 前言一. 架构设计1.1 SSR流式渲染常见错误设计之 - 根页面同步阻塞1.2 架构设计之 - 客户端组件依赖于服务端组件数据① 使用 Redux 完成数据共享 1.3 架构设计之 - 单页内的分步骤跳转① 如何做到服务端组件和客户端组件之间的切换…

libevent之android与鸿蒙编译过程

背景 最近基于libevent开发了一个端侧的缓存代理库,先是基于macOS编译开发的,基本0问题,后来移植到鸿蒙与android时遇到一些编译链接问题。 libevent版本如下: 软件版本号libevent-2.1.8 android编译 编译环境 android studio…

EmguCV学习笔记

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 笔者的博客网址:https://blog.csdn.net/uruseibest 本教程将分为VB.Net和C#两个版本分别进行发布。 教程VB.net版本请…

Go Roadmap-Basics中文笔记

Go Roadmap-Basics 地址:https://roadmap.sh/golang 简介:Github star No.6 学习路线 Go 中译版 Learn the Basics Go特点:静态类型,运行速度快,编译语言,编译速度快,自动垃圾回收&#xff…

【2】初识JVM

目录 一.什么是JVM 二.JVM的功能 2.1即时编译 三.常见的JVM​编辑 ​编辑 总结​编辑 一.什么是JVM 二.JVM的功能 2.1即时编译 三.常见的JVM 总结

Spring MVC Controller返回json日期格式配置失效的解决办法

如题&#xff0c;Spring MVC 4.3.0版本&#xff0c;配置jackson读写json。Controller层方法返回值对象包含java.util.Date类型的属性&#xff0c;并且在applicationContext.xml中配置了jackson的日期格式&#xff1a; <mvc:annotation-driven><mvc:message-converters…

【ARM+Codesys 客户案例 】RK3568/A40i/STM32+CODESYS在工厂自动化中的应用:PCB板焊接机

现代化生产中&#xff0c;电子元件通常会使用自动化设备来进行生产&#xff0c;例如像PCB&#xff08;印刷电路板&#xff09;的组装。但是生产过程中也会面临一些问题&#xff0c;类似于如何解决在PCB板上牢固、精准地安装各种组件呢&#xff1f;IBL Lttechnik GmbH公司的CM80…

什么是OpenTiny?

OpenTiny 是一套企业级的 Web 前端开发解决方案&#xff0c;提供跨端、跨框架的 UI 组件库和低代码引擎&#xff0c;帮助开发者高效构建 Web 应用 。企业运用开发中&#xff0c;可以利用 OpenTiny 的以下核心组件和优势&#xff1a; TinyVue 组件库&#xff1a;一个丰富的组件库…

AWS boto3 脚本访问 AWS 资源

AWS boto3 脚本访问 AWS 资源 引言boto3主要功能常见用例安装和基本使用 boto3.Client() 低级客户端基本用法关键参数 boto3.resource() 高级客户端常见参数用法 boto3.resource VS boto3.client相似点不同点总结 关于身份验证凭证隐式身份凭证显式身份验证凭证assuem role如何…

对比各类 AWS MySQL 升级方案及原理

搞了好几个月的MySQL升级终于接近尾声&#xff0c;进入总结梳理阶段~ 本文主要对比升级期间用到的三种方案&#xff1a; 本地升级蓝绿升级API同步升级 对比项 \ 升级方式本地升级蓝绿升级API同步升级停机时间长&#xff0c;3-5分钟不可读写较短&#xff0c;约15秒实例变为只…

Delphi 实现JSON序列化和反序列化的功能以及源码探究

目录 一、JSON序列化和反序列化简介 二、Delphi序列化的两种方式 1、TJson的使用 2、TJsonSerializer的使用 3、使用注意事项 三、Delphi与GO序列化效率对比 1、GO语言JSON序列化方法 2、Delphi 与 GO 序列化效率对比 四、Delphi序列化源码初探 五、Delphi 序列化的优…

NGINX 之 location 匹配优先级

章节 1 NGINX 的源码安装 2 NGINX 核心配置详解 3 NGINX 之 location 匹配优先级 4 NGINX 基础参数与功能 目录 1 location 基础语法 1.1 location 语法说明表 1.2 URI部分简单介绍 2 location 匹配优先级 2.1 URI匹配的规则与顺序 2.2 精确匹配(location /1.txt) 2.3 区…

hutool发邮件功能如何配置SMTP服务器参数?

hutool发邮件的教程指南&#xff1f;hutool发邮件性能优化方法&#xff1f; Hutool作为一个轻量级的Java工具库&#xff0c;其邮件发送功能因其简单易用而受到广泛关注。AokSend将详细介绍如何通过配置SMTP服务器参数来实现Hutool发邮件的功能。 hutool发邮件&#xff1a;优势…

LinuxKernel开发

Linux Kernel简介 0. Linux历史 Linux内核&#xff08;英語&#xff1a;Linux kernel&#xff09;是一种开源的类Unix操作系统宏内核。整个Linux操作系统家族基于该内核部署在传统计算机平台&#xff08;如个人计算机和服务器&#xff0c;以Linux发行版的形式[7]&#xff09;…

【Unity实战】NavMeshAgent实现Strafe固定朝向移动

众所周知&#xff0c;NavMeshAgent一旦设定了destination&#xff0c;它就会直奔目标。但是在一些场景中&#xff0c;比如NPC是个射手&#xff0c;除了瞄准玩家&#xff0c;也需要走位。如果不加以处理&#xff0c;我们恐怕会遇见瞄准IK和朝向…难以言表的表现&#xff0c;直接…

达梦数据库的系统视图v$datafile

达梦数据库的系统视图v$datafile 达梦数据库的V$DATAFILE 是一个重要的系统视图&#xff0c;提供了有关数据库数据文件的信息。 V$DATAFILE 系统视图 V$DATAFILE 视图用于显示数据库中每一个数据文件的详细信息。通过查询这个视图&#xff0c;数据库管理员可以了解数据文件的…

从零搭建xxl-job(六):xxl-job执行器服务端的简单搭建

经过前面的学习&#xff0c;相信大家对XXL-JOB调度中心的核心知识点和定时任务的调度流程已经了如指掌了&#xff0c;接下来&#xff0c;我们的重心就要从调度中心过渡到定时任务程序了&#xff0c;接下来&#xff0c;我会为大家搭建起一个简易的可运行的定时任务的体系&#x…