深入理解计算机系统——汇编基础

news2025/5/12 8:19:46

文章目录

  • 寄存器
  • 数据格式
    • mov操作
  • push,pop
  • call,ret
  • leave,enter
  • 算术和逻辑操作
    • 一元操作
    • 二元操作
    • 移位操作
  • 特殊的算术操作
  • 控制
    • 条件码
    • 访问条件码
    • 跳转
      • 很好的例题
    • 翻译条件分支
    • 循环
    • 条件传送指令
    • switch
  • 函数堆栈
    • 递归的过程
  • 数组
  • 数据结构
    • 结构体
    • 联合
  • 使用GDB调试
  • 缓冲区溢出
  • 使用GDB调试
  • 缓冲区溢出


原文链接:原文链接


自己复习的时候,把题目写一下,会更好的理解一下
根据我的经验,画栈帧图的时候,ebp esp画在图的右侧比较好——栈帧从上到下地址是递减的,右侧就是表示的低地址
参考书籍:列举不分先后

  1. 深入理解计算机系统(原书第2版)
  2. 庖丁解牛Linux内核分析
  3. Linux内核完全解剖

寄存器

32位:

  • 数据寄存器

eax ebx ecx edx
eax通常作为函数的返回值

  • 指针寄存器

esp指向栈顶
ebp指向栈底

  • 变址寄存器

esi edi

  • 段寄存器

    es
    cs代码段寄存器
    ss堆栈段寄存器
    ds数据段寄存器
    fs
    gs

  • 指令指针寄存器

eip存储下一条指令的地址

  • 标志寄存器

EFlags
注意:局部变量保存在寄存器中
上面的e就是扩展,16位的变成了32位
image.png

数据格式

字节b——1字节
字w——2字节
双字l——4字节

立即数:一个数加上$符号——$12
直接寻址:如果是寄存器,那么操作数就是寄存器存储的数——%eax;如果是一个数(地址)的话,操作数就是地址指向的那块内存的数据——0x324
间接寻址:寄存器里的数据指向的内存数据——(%eax)
其他的形式:

2(%eax)%eax里面的值加2的和作为地址,该地址指向的内存数据
3(%eax,%ebx)两个寄存器里面值相加、再加上3的和作为地址,该地址指向的内存数据
3(%eax,%ebx,2)%eax+%ebx*2+3的和作为地址,指向的内存数据

mov操作

movd移动一个字节
movw移动一个字
movl移动2字
其他的汇编指令和这类似,下文不再论述

movl $123 %eax//立即数存入eax
movl 0x123 %eax//0x123地址处的数存入eax,比如0x123地址处的内存数据为1,那么eax就存1
movl (%ebx) %eax//ebx里面的数作为地址,把该地址处的数存入eax
//剩下的可以根据上面的数据格式就可以懂了
  • movs符号扩展——补符号位

movsbw一字节符号扩展到字,
movsbl一字节符号扩展到两字
movswl字符号扩展到两字

  • movz零扩展——补0

同上,只不过是零扩展。

push,pop

  • push压栈

pushl %eaxesp先减4,然后把eax的值压入栈顶

  • pop出栈

popl %eax把栈顶的数移入eax寄存器中,esp加4

pushl %ebp
movl %esp,%ebp

所有函数的头两条指令都是为了初始化自己的堆栈空间

call,ret

函数调用指令,调用该地址
call 0x12345
执行该操作会做出两个动作
把当前的%eip的值压栈,然后把0x12345放入eip
为什么要这样呢?
eip压栈是保存旧的函数栈帧,因为eip保存的是计算机要执行的下一条指令,使函数调用完成之后,可以继续回到原来的函数栈帧中继续执行代码。

执行指令ret——函数返回指令
执行该指令之后,把call压入的eip的数据(当前栈顶的第一个存储单元),重新弹回eip中
*表示不存在实际对应的指令
image.png
eip不能被程序员直接修改,只能通过专用指令(call,ret,jmp)等间接修改

把程序计数器放在整数寄存器的唯一方法

	call next
next:
	popl %eax

leave,enter

leave指令用来撤销函数栈帧的,等价于下面两条指令:

movl %ebp,%esp
popl %ebp

enter指令用来建立函数栈帧,等价于下面两条指令:

pushl %ebp
movl %esp,%ebp

算术和逻辑操作

leal加载有效地址,其实和movl的意思差不多,但是它根本就没有引用存储器。
leal的用法

leal -8(%ebp) ,%eax它表达的意思是把ebp-8数据的地址赋给eax——eax中的值就是ebp-8
movl -8(%ebp) ,%eax它表达的意思是把ebp-8处的数据赋给eax——eax中的值(ebp-8)

一元操作

inc x自加1 x+1
dec x自减1 x-1
neg x变负 -x
not x取补 ~x

二元操作

add
sub
xor异或
or
and

移位操作

sal``shl左移
sar算术右移——补符号位
shr逻辑右移——补0

特殊的算术操作

imull S这个发现只有一个操作数,S乘以eax寄存器中的值,结果是有符号的64位的,前32位放在edx中,后32位放在eax中。
mull S和上面的一样,只不过是无符号64位的。说明i表示的是有符号
imull S,D这个就是普通的乘法,S*D->D,32位的
cltd转为4字(64位)——把eax寄存器中的值转成64位,前32位存在edx,后32位存在eax中。
idivl S有符号除法,edx:eax组成的64位数除以S,商存在eax中,余数存在edx中
divl S无符号除法,和上面一样

控制

条件码

image.png
下面两个指令只设置条件码
image.png
对应cmp指令,如果两个数相等,指令会将零标志设置为1

访问条件码

常用的三种方法:

  1. 根据条件码的组合,将一个字节设置为0或者1,2
  2. 可以条件跳转到程序的某个其他的部分
  3. 可以条件的传送数据

image.png
set指令的后缀不表示操作的数大小

跳转

跳转指令,跳转到标志的地方
image.png
上面这个就是跳转到.L1的位置

jmp无条件跳转
jmp *%eax用寄存器eax中的值作为跳转目标
jmp *(%eax)寄存器eax里面的值作为地址,把改地址指向的内存空间的数据当作跳转目标

image.png

image.png
当执行与PC(当前指令的下一条指令)相关的寻址的时,程序计数器的值是跳转指令后面的那条指令的地址,而不是跳转指令本身的地址。
image.png

jle后面的地址是怎么得到的呢?很简单——PC的值加上0d

很好的例题

image.png

翻译条件分支

咱就是说,条件跳转是真的狗,具体怎么狗的,看下面这道题目:
image.png
注意:以下解释,如果读者看不懂,自己做一下实验即可。
总结:每对if-else的第一个条件,其实是跳转到else执行的。(也就是说,第一条跳转指令是跳转到else的地方)这种情况初学者不是很了解。(先进行不满足条件的跳转)
其他是对源代码进行改写,变成goto语句,这样就方便理解了。

  1. eax寄存器存x
  2. edx寄存器存y
  3. x与-3的关系,进行设置条件码,怎么设置的咱就别管理——一定注意是后面与前面的数比较
  4. 该汇编是根据条件码进行跳转,我们不管条件码。结合3,它的意思是,如果x>=-3,跳转到.L2。但是,实际的C语言中,没有该条件。该语句其实是执行的else语句。你品,你细品。

.L2之后就是正常跳转,因为这个是一组条件语句
13,14:x>2跳转到.L5
如果不满足条件:执行15条语句,该语句其次才对应着c语言的第一条语句——val=x^y

上面是把条件中的else中的代码完成了
从第5条汇编语句开始就是执行的if里面的代码
下面这个语句一看是比较,。。。。。。。,这咋又是一组if-else
5,6:x<=y,跳转到.L3。也就是说,y<x执行的才是if语句
下面就不讲了,没有什么难的了。期末一定会考的哦

image.png

循环

汇编中没有循环,而是用条件+跳转组成实现的。
其他的循环会先转换成do-while的形式,然后再编译成机器代码。
转换成goto形式比较好理解

条件传送指令

image.png
解释一下下面语句
image.png

switch

image.png

p146页,第5句话表示的跳转到switch的默认位置
第6句话,表示间接跳转,可以看数组那一节
第3,4句话,表示把n值减100,目的就是为了把传入的值(变成索引之后)控制在0~6范围内

image.png

.L7中的7表示数组中有7个标号(有的值可能不存在)
画红线的地方,表示真实的下标(对应c语言的)——当然这是注解,实际是看不见的
根据上面所示101这个是不存在的,因为是默认跳转,104、106公用一个跳转,说明其中一个不存在break语句

image.png

函数堆栈

什么叫做栈帧?

单个函数调用操作所使用的栈部分被称为栈帧结构(以后画右侧,看文章最前面的说明
image.png

对于32位的x86cpu来说,通过堆栈来传参的方法是从右到左的——即在准备调用的时候,从右到左进行参数的压栈操作
如:
swap(a,b)pushl bpushl a

64位的不同,这里不做讨论
函数的返回值用eax进行保存的,如果要返回多个值,那么它保存的就是那块空间的地址

我们知道vc6.0(骨灰级编译器)在声明变量的时候,全部的变量要声明在最前面?
为什么会这样呢?
因为早期的编译器不够智能,不能智能的预留空间,所以要求程序员在最前面声明,这样在建立函数堆栈的时候,就会一个一个进行空间的申请。

我们需要确定在一个函数调用其他函数的时候,被调用者不会修改或者覆盖调用者所用到的寄存器内容。
因此InterCPU采用统一惯例
惯例指明:
寄存器eax``edx``ecx的内容由调用者自己负责——也就是说,被调用者,可以随意的修改
寄存器ebx``esi``edi的值必须由被调用者来负责——也就是说,被调用者使用这些寄存器的时候,必须先进行保存,退出时进行恢复。当然寄存器ebp``esp也遵守这个

看下面这份汇编代码:
image.png
我们发现栈帧开辟了24字节,但是我们只使用了16个字节,还有8个字节永远不会使用
为什么呢?
gcc坚持一个函数使用的所有栈空间必须是16字节的整数倍,(24虽然不是整数倍,但是看是所有,还要加上保存的ebp和返回值,这两个总共8字节,也就是32)

一个函数的栈帧包含这几个部分:

  1. 建立部分——初始化栈帧
  2. 主体部分——执行过程的计算
  3. 结束部分——恢复栈的状态,以及过程返回

对于释放栈帧可以用leave的方法,也可以用一个或者2个popl指令。这两种都可以,看见知道是什么意思就行。

递归的过程

直接看题目解释:
image.png
这里的条件判断不会那么狗,就是很直接的。
下面对汇编语句进行解释:

  1. ebx=x
  2. eax=0
  3. 检测
  4. 如果x==0,跳转到.L3
  5. eax=x
  6. eax=x>>1
  7. 该行是准备参数的过程,把eax的值放入栈顶
  8. 递归开始
  9. edx=x
  10. edx=x&1
  11. eax为返回值,eax=(edx+eax)=(x&1)+rv

数组

直接上例子:结果是指针,存入eax中;结果是整型,存入ax中。
image.png

关键部分解释(其实是复习一下c语言的知识):
指针加一个数,那么该指针的值为:地址加上这个数乘以类型的大小
例:
short p[5]p的地址为xp,那么p+i的值就是xp+2*i

二维数组:
记住这个公式:

T D[R][C]

&D[i][j]=xd+L(C*i+j)//L是T的类型

数据结构

这里主要说的是:结构体、联合体

结构体

我们访问结构体中的字段的时候,用的是结构体的地址加上适当的偏移
image.png
比如上面这个%eax*4就是找到数组第i个元素相对于数组首元素的偏移量,加上8就是相对于结构体首地址的偏移量,最后加上%edx就是最终的地址。
看看这个例子:
image.png

联合

在使用联合的时候主要注意将各种不同大小的数据类型结合在一起的时候,字节顺序的问题是很重要的

其实和结构体差不多。直接做个例题就行,看下面的例题:
image.png
image.png

关于数据的对齐,我在C语言结构体https://code-child.cn/post/192中已经进行了说明。
通常在汇编代码中,会有这样的命令:.align 4表示遵守4字节对齐的限制。

使用GDB调试

除了下面表中的,还可以看我之前写的文章https://code-child.cn/post/148
也可以在线查找进行调试:

  1. gdb 程序——开始调试
  2. help all

image.png

缓冲区溢出

明。
通常在汇编代码中,会有这样的命令:.align 4表示遵守4字节对齐的限制。

使用GDB调试

除了下面表中的,还可以看我之前写的文章https://code-child.cn/post/148
也可以在线查找进行调试:

  1. gdb 程序——开始调试
  2. help all

[外链图片转存中…(img-SHtIiDdW-1685751716219)]

缓冲区溢出

我们在vs下面使用scanf``gets``strcpy等库函数的时候,经常说他们是不安全的,为什么这么说呢,因为它们不进行检查栈帧空间的大小,一直写或者进行其他操作,就会越过栈帧的给它们开辟的空间,导致发生可怕的操作。
看下面的练习题
image.png
image.png

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

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

相关文章

信息与编码SCUEC DDDD 期末复习整理(1)

1.1948年&#xff0c;美国数学家香农发表了题为“通信的数学原理”的论文&#xff0c;从而创立了信息论。 2.不可能事件的自信息量是&#xff08;∞&#xff09;&#xff0c;必然事件的自信息量是&#xff08;0&#xff09; 3. 4.差错控制的主要方式有前向纠错方式FEC&#x…

线程的创建(Runnable,Future,CompletionService,CompletableFuture的辨析)

直接使用Thread 直接让某个类继承Thread类&#xff0c;复写run方法&#xff0c;外部调用的时候直接调用start方法。 因为java的单继承模式&#xff0c;但是我们一般不直接使用这种方法。 使用Runnable Slf4j public class MyTask implements Runnable {Overridepublic void …

Vue+springboot餐厅美食菜品评价系统4d5g9

餐厅是一个传统的行业。随着当今社会的发展&#xff0c;时代的进步&#xff0c;行业也在发生着变化&#xff0c;单就点菜这一方面&#xff0c;菜品评价正在逐步进入人们的生活。传统的菜品评价&#xff0c;不仅会耗费大量的人力、时间&#xff0c;有时候还会出错。网上可以解决…

ORTP库局域网图传和VLC实时预览

​ 1.ORTP的引入 1.1、视频网络传输的2种方式 (1)基于下载&#xff1a;http or ftp&#xff08;网站播放视频&#xff0c;追求清晰度&#xff0c;哪怕时间晚一点&#xff09; (2)基于实时&#xff1a;RTP/RTSP/RTCP&#xff08;直播、监控&#xff0c;追求实时&#xff0c;…

Linux 实操篇-组管理和权限管理

Linux 实操篇-组管理和权限管理 Linux 组基本介绍 在linux 中的每个用户必须属于一个组&#xff0c;不能独立于组外。在linux 中每个文件有所有者、所在组、其它组的概念。 所有者所在组其它组改变用户所在的组 文件/目录所有者 一般为文件的创建者,谁创建了该文件&#x…

First Order Motion Model for Image Animation 笔记

First Order Motion Model for Image Animation 摘要 Image animation consists of generating a video sequence so that an object in a source image is animated according to the motion of a driving video. Our framework addresses this problem without using any a…

表情识别(从原理到代码安装)

1. 项目介绍 面青识别(face_classification )是一个基于深度学习的面部表情识别项目,它使用 Keras 和 TensorFlow 框架来实现模型的训练和预测。该项目的主要目标是在图像或视频中检测并识别人脸表情,并将其分类为七种不同的情绪类别:生气、厌恶、害怕、高兴、平静、伤心…

JVM学习笔记(完结)

类加载与字节码技术 1、类文件结构 通过 javac 类名.java 编译 java 文件后&#xff0c;会生成一个 .class 的文件&#xff01; 以下是字节码文件&#xff1a; 0000000 ca fe ba be 00 00 00 34 00 23 0a 00 06 00 15 09 0000020 00 16 00 17 08 00 18 0a 00 19 00 1a 07 00…

全面大涨原因!多家基金解读

周五&#xff01;大涨&#xff01; 6月2日&#xff0c;A股以强势反弹结束本周的交易&#xff0c;整体全面上行&#xff0c;几乎所有主流指数都收涨。沪指高开高走&#xff0c;深成指、创业板指涨超1%。总体来看&#xff0c;个股涨多跌少&#xff0c;两市超3300股处于上涨状态。…

Linux4.4网页与安全优化

文章目录 计算机系统5G云计算第一章 LINUX Apache网页与安全优化一、网页压缩1.检查是否安装 mod_deflate 模块2.如果没有安装mod_deflate 模块&#xff0c;重新编译安装 Apache 添加 mod_deflate 模块3.配置 mod_deflate 模块启用4.检查安装情况&#xff0c;启动服务5.测试 mo…

redis第三章-redis集群redisCluster

1.redis集群模式比较 &#xff08;1&#xff09;哨兵模式 哨兵模式是利用哨兵来做主从切换的&#xff0c;当主节点发生故障的时候&#xff0c;通过哨兵去选取出一个从节点作为主节点&#xff0c;但本身哨兵的配置还是有些麻烦&#xff0c;并且实际上哨兵的性能和高可用性一般…

chatgpt赋能python:使用Python创建结构体:完全指南

使用Python创建结构体&#xff1a;完全指南 在Python编程领域&#xff0c;结构体是一种非常方便和有用的数据类型&#xff0c;用于存储和组织相关变量。在本篇文章中&#xff0c;我们将讨论如何使用Python创建结构体。让我们开始吧&#xff01; 什么是结构体&#xff1f; 结…

shell学习

1、/etc/hosts的作用 Windows下的目录C:\Windows\System32\drivers\etc\hosts Linux下目录/etc/hosts 如 我们在/etc/hosts文件中添加一行 39.156.66.10 taobao.com 原理是&#xff0c;我们在浏览器输入 taobao.com&#xff0c;那么网站就可以打开百度的网站 但是现实是网…

7大常用ES6特性,助力你写出更现代化的JavaScript

文章目录 1. 模板字符串2. 箭头函数3. let 和 const4. 解构赋值5. 函数默认参数6. 模块化7. Promise 1. 模板字符串 模板字符串是一种新的字符串类型&#xff0c;它允许你在字符串中插入变量&#xff0c;方便了JavaScript开发者的开发体验。 ES6的模板字符串&#xff08;Templa…

demo:搜索帮助出口

写报表&#xff0c;用到搜索帮助&#xff0c;太久不写了&#xff0c;忘了&#xff0c;然后简单测了下。 当然方法很多&#xff0c;我只是突然想起这个东西来了&#xff0c;就测了下&#xff0c;条条大路通北京&#xff0c;想咋实现就咋实现吧&#xff0c;实现了就得了~ 代码很简…

chatgpt赋能python:Python代码教你删除空文件夹——让你的电脑系统更健康

Python代码教你删除空文件夹——让你的电脑系统更健康 作为一名有着10年python编程经验的工程师&#xff0c;我发现在电脑里存储着太多的空文件夹时会对电脑系统造成负面影响。空文件夹占用了硬盘空间&#xff0c;这可能导致你的电脑运行缓慢或者存储空间不足。因此&#xff0…

Qt下使用Sqlite数据库实现图像的读写显示

系列文章目录 提示&#xff1a;这里是该系列文章的所有文章的目录 第一章&#xff1a; Qt连接Sqlite3并使用Qtableview实时显示数据&#xff0c;重写QSqlQueryModel实现文本居中 第二章&#xff1a; Qt下使用Sqlite数据库实现图片的读写显示 文章目录 系列文章目录前言一、初始…

python3.10在centos下安装以及配置

python在centos下安装以及配置 1.背景 centos下默认的都是python2.7下载需要更换为3.x使用&#xff0c;目前大部分应用都是基于pyhton3了 具体步骤&#xff1a; 先按装openssh 不安装会报错 而且要安装高版本 要不然不兼容 报错如&#xff1a; WARNING: pip is configured …

chatgpt赋能python:Python创建程序的SEO指南

Python创建程序的SEO指南 Python是一种流行的高级编程语言&#xff0c;被广泛用于开发Web应用程序、人工智能、数据分析和科学计算等领域。在创建Python程序时&#xff0c;也要考虑SEO因素&#xff0c;以优化网页在搜索引擎结果中的排名。本文将介绍如何创建具有SEO友好性的Py…

软考A计划-电子商务设计师-电子商务系统开发知识

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…