汇编语言学习 下

news2025/1/16 20:14:32

本文承接汇编语言学习笔记 上

上篇文章记录了汇编语言寄存器,汇编语言基本组成部分,数据传送指令,寻址指令,加减法指令,堆栈,过程,条件处理,整数运算的内容

高级过程

大多数现代编程语言在调用子程序的时候会把参数压入对战

子程序也常常把局部变量压入堆栈

  • 子程序在C和C++中被称为函数
  • 在Java中被称为方法
  • 在宏汇编程序(MASM)中被称为过程

堆栈帧

堆栈参数

堆栈帧是一块堆栈保留区域

存放

  • 被传递的实际参数
  • 子程序的返回值
  • 局部变量
  • 被保存的寄存器

创建步骤

  1. 将被传递的实际参数压入堆栈
  2. 当子程序被调用时,该子程序的返回值压入堆栈
  3. 子程序开始执行的时候,EBP被压入堆栈
  4. 设置EBP等于ESP,EBP成为子程序所有参数的引用基址
  5. 如果有局部变量,修改ESP在堆栈中为其预留空间
  6. 需要保留的寄存器,将它们压入堆栈

Fastcall调用方式

顾名思义,是一种希望快速的调用方式

我们来分析一下这个调用方式: 

调用自过程的时候,需要首先将参数传入EAX,EBX,ECX,EDX,少数情况还会传入ESI,EDI

我们知道寄存器是CPU内部的原件,堆栈在内存上,寄存器调用明显更快

但是我们知道通用寄存器很少,很多都有特定的功能,乘法需要用到EAX,还有许多寄存器用来循环数值和参与计算的操作数

因此寄存器不可能一直存放传递给过程的参数

在过程调用之前, 存放参数的寄存器需要首先入栈,然后向其分配过程参数

但是这些额外的入栈操作会让代码变得混乱,还有可能消除性能优势

值传递

一个参数通过数值传递时,该值的副本会被压入堆栈

.data
val1 DWORD 3
val2 DWORD 6
.code
push val2
push val1
call AddTwo

引用传递

通过引用来传递的参数包含的是对象的地址

push OFFSET val2
push OFFSET val1

传递数组

将数组的地址压入堆栈 

不愿意采用将每个数组元素压入堆栈的原因是这样很慢而且浪费堆栈空间

访问堆栈的参数

1.将传递的参数压入堆栈,调用子过程

2.EBP寄存器存放的是原来栈帧的基址,我们需要现将EBP压入栈保存

3.然后将当前的ESP作为新的栈帧的基址

示例

int AddTwo(int x,int y)
{
    return x+y;
}

将EBP入栈,设置ebp位esp的值

AddTwo PROC
    push ebp
    mov ebp,esp

ADD(5,6)

6

[EBP+12]
5[EBP+8]
返回地址[EBP+4]
EBPmov ebp,esp

这样通过当前EBP和偏移量就能访问传入的参数和原来的ebp(返回地址)

显式的堆栈参数

堆栈参数的引用表达式形如[esp+8],称它们为显式的堆栈参数

清除堆栈

子程序返回时,必须将参数从堆栈中删除

否则会导致内存泄露,堆栈会被破坏

C调用方式-cdecl

用于C和C++语言

子程序的参数按逆序入栈

解决了运行时堆栈的问题

在调用子过程后,紧跟一条语句让堆栈指针ESP加上一个数,该数的值即为子程序参数所占的堆栈空间

main PROC
    push 6
    push 5
    call AddTwo
    add esp,8
    ret
main ENDP

能将参数从堆栈中删除

STDCALL调用规范

给RET指令添加了一个参数,使程序在返回调用过程的时候,ESP会加上这个参数

这个添加的整数和过程参数占用的堆栈空间字节数相等

AddTwo PROC
    push ebp
    mov ebp,esp
    mov eax,[ebp+12]
    add eax,[ebp+8]
    pop ebp
    ret 8
AddTwo ENDP

局部变量

在子过程中创建的变量

局部变量在ebp下

void Mysub()
{
    int X=10;
    int Y=20;
}

每个变量的存储大小都要向上取整保存为4的倍数

两个局部变量一共保留8个字节

MySub PROC
    push ebp
    mov ebp,esp
    sub esp,8
    mov DWORD PTR [ebp-4],10
    mov DWORD PTR [ebp-8],20
    mov esp,ebp
    pop ebp
    ret
MySub ENDP

从堆栈中删除局部变量,只需要执行:

mov esp,ebp

esp向上移动=内存释放

可以给局部变量的偏移量定义一个符号,在代码中使用这些符号

X_local EQU DWORD PTR [ebp-4]
Y_local EQU DWORD PTR [ebp-8]

MySub PROC
    push ebp
    mov ebp,esp
    sub esp,8
    mov X_local,10
    mov Y_local ,20
    mov esp,ebp
    pop ebp
    ret
MySub ENDP

保存和恢复寄存器

子程序在修改寄存器之前将它们的当前值保存到堆栈

通常在ebp入栈,设置ebp等于esp之后,相关寄存器入栈

栈帧
解释说明
传递的参数[EBP+8]

返回地址

[EBP+4](原来栈帧的EBP)
EBP

当前栈帧的EBP

ECX
EDX当前ESP指向的位置

EBP被初始化之后,整个过程中它的值将保持不变

ECX,EDX入栈并不影响EBP按照原来的偏移量访问传递的参数

引用参数

引用参数通常是基址-偏移量寻址方式进行访问

每个引用参数都是一个指针

.data
count=100
array WORD count DUP(?)

.code
push OFFSET array
push count
call ArrayFill
ArrayFill PROC
    push ebp
    mov ebp,esp
数组偏移量
数组长度

返回地址

EBP

LEA指令

返回间接操作数的地址

C代码:

void makeArray()
{
    char myString[30];
    for(int i=0;i<30;i++)
        myString[i]='*';
}

等效的汇编代码:

makeArray PROC
    push ebp
    mov ebp,esp
    sub esp,32                ;mystring位于EBP-30的位置
    lea esi,[ebp-30]          ;加载mystring的地址
    mov ecx,30                ;设置循环计数器
L1: mov BYTE PTR [esi],'*'    ;填充一个位置为'*'
    inc esi                   ;指向下一个元素
    loop L1                   ;循环30次,直到ecx是0
    add esp,32                ;恢复esp
    pop ebp
    ret
makeArray ENDP

ENTER指令

为被调用过程自动创建堆栈帧

包含三个操作

  • 把EBP入栈        push ebp
  • 把ebp设置为堆栈帧的基址        mov ebp,esp
  • 为局部变量保留空间          sub esp,numbytes

ENTER有两个操作数,一个是常数,是局部变量保存的堆栈空间(字节),第二个参数定义了过程的词法嵌套级

ENTER numbytes,nestinglevel

MySub PROC
    enter 0,0

等效于:

MySub PROC
    push ebp
    mov ebp,esp
MySub PROC
    enter 8,0

等效于:

MySub PROC
    push ebp
    mov ebp,esp
    sub esp,8

LEAVE指令

结束一个过程的堆栈帧,与ENTER是相对应的操作

直接上代码理解

MySub PROC
    enter 8,0
    .
    .
    leave
MySub ENDP

等效于:

MySub PROC
    push ebp
    mov ebp,esp
    sub esp,8
    .
    .
    mov esp,ebp
    pop ebp
    ret
MySub ENDP

前一篇文章汇编语言学习笔记 上

已将基本的汇编语言语法总结了一遍

暂时不更新

未完待续

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

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

相关文章

通信原理简明教程 | 信号、信道与噪声

文章目录1 信号与系统的基本概念2 傅里叶变换与信号的频谱2.1 信号的频谱2.2 傅里叶变换的常用性质2.3 信号的能量谱、功率谱与自相关函数2.4 信号的带宽3 线性系统与滤波器3.1 线性系统及其频率特性3.2 系统响应的频域求解3.3 滤波器2.4 信道及其特性4.1 信道的分类4.2 信道的…

兔年伊始谈闲书:三体-乌合之众-百年孤独 和《猫城记》(随笔)

引言 “ 各位读者&#xff0c;我们都兔年大吉&#xff0c;新春快乐。我本想写一篇《公有云换帅转舵后的错误经验和正经歪念》&#xff0c;但刚过年就炮火味十足&#xff0c;觉得有失体面。所以就写了篇读书的散记杂记。本文和云计算行业完全无关&#xff0c;就是一个有常识性阅…

[数据结构基础]排序算法第一弹 -- 直接插入排序和希尔排序

一. 排序的概念及分类 1.1 排序的概念 排序&#xff0c;就是使一串数据&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 1.2 常见的排序算法 图1.1按照排序算法的思想&#xff0c;将排序分为四大类&#xff1a;插入排序、选择排序…

OpenGL相关库及其关系概述

目录 1、OpenGL 2. .GLUT 3、Freeglut 4、glew 5、glfw 6、glad 1、OpenGL OpenGL只有框架没有实现&#xff0c;换句话说就是OpenGL只有函数声明没有源文件实现&#xff0c;类似于接口和虚函数。所有的实现是显卡生产商提供。比如NVIDIA或者AMD就要自己实现OpenGL函数内容…

前后端登录逻辑讲解-本文使用RSA加密过程-附代码

文章目录一、项目环境二、生成公钥私钥1.生成私钥2.查看私钥3.生成公钥4.查看公钥三、安装依赖包四、自测加解密1.纯前端自测2.前后端联调①前端登录代码改为&#xff1a;②后端登录接口代码&#xff1a;③验证五、与数据库密码进行对比&#xff08;数据库是进行了bcryptjs加密…

关于非授权访问的逻辑漏洞挖掘

简介 挖洞的时候日常笔记&#xff0c;很多细节都写得不好&#xff0c;师傅们不要介意 开始 获取目标&#xff1a;https://fofa.info/ 在fofa上输入body“后台登录”&#xff0c;可以看到一大堆目标&#xff0c;今天我打算去测试逻辑漏洞 进入目标地址 随意输入用户名和密码&…

Python LC Loan贷款数据集 统计分析 数据挖掘 研究报告

实验代码&#xff1a;https://download.csdn.net/download/Amzmks/87396462 首先读表 将有空值的列和完全相同的列删除 将数值型数据单独挑出来 将数值型数据从string转为float 用方差阈值法筛选特征较为明显的部分数值型数据 将文本型数据单独挑出来 去除所有的可能的头…

计算机存储系统

前言何为存储系统&#xff1f;存储系统是指计算机中由存放程序和数据的各种存储设备、控制部件及管理信息调度的设备&#xff08;硬件&#xff09;和算法&#xff08;软件&#xff09;所组成的系统。为何需要存储系统&#xff1f;信息是人类认知外界的方式&#xff0c;最初的信…

对CAS的理解

CAS的概念&#xff08;compare and swap&#xff09;:比较并交换我们首先要明白&#xff0c;自旋是一个纯用户态的操作&#xff0c;本身并没有进行加锁&#xff0c;所执行的代码&#xff0c;是在并发环境下执行的&#xff0c;没有锁。我们举一个例子来说明自旋加CAS的作用&…

Day05 C++STL入门基础知识三——String容器(上)概念-构造-赋值-拼接-查找-替换【全面深度剖析+例题代码展示】

文章目录1. 基本概念1.1 本质1.2 string与char*的区别1.3 特点2. 构造函数2.1 四种构造2.2 举例展示3. 赋值操作3.1 七种赋值函数原型&#xff08;operator等号赋值/assign成员函数赋值&#xff09;3.2 举例展示4. 拼接操作4.1 七种拼接函数原型4.2 举例展示5. 查找操作5.1 八种…

分布式概念

目录一、什么是分布式二、分布式与集群的关系三、软件架构演变四、RPC是什么1.RPC思想原理2.服务之间的交互可以用两种方式五、分布式思想与基本概念1.高并发2.高可用3.注册中心4.负载均衡5.服务雪崩6.熔断7.限流8.API网关9.服务跟踪10.弹性云一、什么是分布式 《分布式系统原…

Python流程控制语句之循环语句

上一篇&#xff1a;Python流程控制语句之选择语句 文章目录前言一、while 循环二、for 循环1. 进行数值循环2. 遍历字符串三、循环嵌套总结前言 生活中很多问题都无法一次解决&#xff0c;就像谚语所说&#xff1a;罗马不是一天建成的。一些事物必须周而复始地运转才能保证其存…

linux并发控制详解

目录 1.并发控制 1.1.并发概念 1.2.并发问题 2.多CPU核心 3.解决 4.中断屏蔽 5.原子操作 6.自旋锁 7.自旋锁衍生读写自旋锁 7.1.自旋锁与读写自旋锁的对比&#xff1a; 8.读写自旋锁衍生顺序锁 9.RCU 10.信号量 11.互斥体&#xff08;互斥锁&#xff09; 11.1.互…

2023起点上,一段迷茫的自我倾诉

大家新年快乐。 回顾记忆中渐渐远去的2022。 我曾想象随着一年过去我就能取得很大的进步&#xff0c;“彻底”改变自己的生活状态。其实不过幻想罢了&#xff0c;人才不会无缘无故进步呢。 我曾一度沉溺于网络世界中的关注&#xff0c;想象着自己将可以取得一些成就&#xff…

【每日一道智力题】三个火枪手(快来看人生哲理)

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a; &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是对我最大的激励…

Qt 之 QSystemTrayIcon

文章目录一、QSystemTrayIcon是什么二、属性三、公共类型四、信号提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、QSystemTrayIcon是什么 QSystemTrayIcon类为应用程序在系统托盘中提供一个图标。 如下图&#xff1a; 现代操作系统通常在桌面上提…

“深度学习”学习日记。与学习有关的技巧--Bacth Normalization

2023.1.25 现在已经学习过了&#xff0c;如果我们设置了合适的权重初始值&#xff0c;则各层的激活值分布会呈现适当的广度&#xff0c;从而可以时神经网络模型顺利的进行学习。 而 batch normalization算法 的思想就是为了使得各层有适当的广度&#xff0c;“强制性”地调整…

No package ‘vips‘ found系列问题解决方案

目录 系列报错集合 错误1 错误2 错误3 解决方案清单 系列报错集合 错误1 No package vips found Package vips was not found in the pkg-config search path. Perhaps you should add the directory containing vips.pc to the PKG_CONFIG_PATH environment variable N…

医疗实体及关系识别挑战赛

赛题概要 请本赛题排行榜前10的队友通过作品提交源代码&#xff0c;模型以及说明文档&#xff0c;截止时间为09/27/23:59:59.若文件过大&#xff0c;可发送至官网邮箱&#xff1a;AICompetitioniflytek.com。若截止时间内未提交&#xff0c;官方回通过电话联系相关选手&#x…

JavaEE8-Bean的生命周期

目录 1.Bean执行原理分析 2.Bean生命周期 2.1.实例化Bean&#xff1a;为Bean分配内存空间。&#xff08;相当于买房&#xff0c;从无到有&#xff09; 2.2.设置属性&#xff1a;Bean注入和装配。&#xff08;执行依赖类的注入&#xff1a;A需要使用B的方法&#xff0c;先初…