当前位置: 首页 > news >正文

带你玩转汇编

一.寄存器分类

在这里插入图片描述

控制寄存器控制运行模式

二.通用寄存器

1、理论知识

在这里插入图片描述

rax          64位  8B   只有64位CPU才有eax       32位  4B   32位,64位CPU都有ax     16位  2B   16位,32位,64位CPU都有al   8位  1B   8位,16位,32位,64位CPU都有ah   8位  1B   8位,16位,32位,64位CPU都有

注意:只有rax,rbx,rcx,rdx有ah/bh/ch/dh高八位寄存器

在这里插入图片描述

特殊用途:

1.rax:用于函数返回值的接收
2.rcx:循环次数,this指针(C++)
3.rsi:source 源数据
4.rdi:destination 目的数据
5.rbp,rsp:栈寄存器
6.esp:栈顶
7.ebp:栈底

2.小例子

使用汇编写出以下代码:
int a=10;
a +=1;

1.用多个寄存器实现

xor eax,eax
mov eax,0x0A
add eax,1
mov [ebp-8],eax

2.只用一个寄存器实现
xor eax,eax
xor ebx,ebx
mov eax,0x0A
mov ebx,0x01
add eax,ebx
mov [ebp-8],eax

3.跳转指令

跳转指令:

短跳转:call,jmp,jcc
长跳转:中断,跨段

三.执行流基本结构

函数调用前后栈是不变的

int main()
{
00831750  push        ebp  
00831751  mov         ebp,esp  
00831753  sub         esp,0CCh  
------------------------------------------开辟栈栈帧00831759  push        ebx  
0083175A  push        esi  
0083175B  push        edi  
-----------------------------------------保存现场0083175C  lea         edi,[ebp-0Ch]  
0083175F  mov         ecx,3  
00831764  mov         eax,0CCCCCCCCh  
00831769  rep stos    dword ptr es:[edi]  
0083176B  mov         ecx,offset _FEA7E5C2_main@c (083C008h)  
00831770  call        @__CheckForDebuggerJustMyCode@4 (0831307h)  
-----------------------------------------初始化开辟的栈空间int a = 0;
00831775  mov         dword ptr [a],0  return 0;
0083177C  xor         eax,eax  }
0083177E  pop         edi  
0083177F  pop         esi  
00831780  pop         ebx 
-----------------------------------------恢复现场 00831781  add         esp,0CCh  
00831787  cmp         ebp,esp  
00831789  call        __RTC_CheckEsp (0831230h)  0083178E  mov         esp,ebp  
00831790  pop         ebp  
-----------------------------------------恢复栈帧00831791  ret     ;和call对应,拿到返回地址
-----------------------------------------返回

esp:栈顶
ebp:栈底

mov esp,ebp
pop ebp
leave可以代替这两条,命令(复杂指令集)

四.栈指令

运行模式:
实模式       16      2B
保护模式     32      4B
长模式       64      8B

1.push:把数据压入栈,栈后移(减小)

栈顶指针先移动,然后赋值sub esp,4mov dword ptr[esp],10

2.pop:取出数据,栈前移(增大)

先取值,栈顶指针在移动
mov eax,[esp]
add esp,4

3.jmp:无条件跳转

jmp  地KERNEL_ARRD             段内跳  短跳
jmp  CODE_SELECTOR:KERNEL_ARRD 跨段跳  长跳

4.call

1.会把call指令的下一条指令地址压入栈
2.跳转到函数里面

5.ret

 1.取到栈顶的地址,且栈前移(增大)2.回到地址的位置

五.小案例

给出一下C语言,转化成汇编语言

void text() {int a = 9;if (10 == a){a = 100;}else{a = 1000;}}int main(int argc,char* argv[])
{text();return 0;
}

汇编:

global texttext:push ebp     ;保存main的栈底mov  ebp,esp ;将main栈顶赋值给text栈底mov [esp-8],0x0Amov eax,[esp-8]cmp eax,0X0Ajne .smov [esp-8],OX64jmp .r.smov [esp-8],0X3E8
.r      mov eax,[esp-8] ;保存返回值到eax寄存器中leave           ;mov esp,ebp;popebpret             ;返回main:call text     ;将下一条指令的地址压入栈中,跳转到text函数ret

六.函数调用约定

堆栈平衡(平栈):

(1)调用者平栈:外平栈      add esp,4
(2)被调用者平栈:内平栈    ret 8

调用约定:

研究调用约定主要研究,传参方式(栈传参,寄存器,栈+寄存器)和传参顺序,平栈方式

32Bit:
1.__cdecl:(X86)默认约定

text(0x11,0x22,0x33);
002D1DE1  push        33h  
002D1DE3  push        22h  
002D1DE5  push        11h  
002D1DE7  call        _text (02D13BBh)  
002D1DEC  add         esp,0Ch    ;一个参数4字节一共12字节

栈传参,从右到左,外平栈

2.__stdcall:windows动态链接库

00BF1DE1  push        33h  
00BF1DE3  push        22h  
00BF1DE5  push        11h  
00BF1DE7  call        _text@12 (0BF13C0h)

栈传参,从右到左,内平栈

3.__fastcall

00AC3E71  push        33h  
00AC3E73  mov         edx,22h  
00AC3E78  mov         ecx,11h  
00AC3E7D  call        @text@12 (0AC13C5h) 

前两个寄存器,其余的栈传参,从右到左,内平栈

64Bit:
Windows:__fastcall

text(0x11,0x22,0x33,0x44,0x55,0x66,0x77);
00007FF7142E1B83  mov         dword ptr [rsp+30h],77h  
00007FF7142E1B8B  mov         dword ptr [rsp+28h],66h  
00007FF7142E1B93  mov         dword ptr [rsp+20h],55h  
00007FF7142E1B9B  mov         r9d,44h  
00007FF7142E1BA1  mov         r8d,33h  
00007FF7142E1BA7  mov         edx,22h  
00007FF7142E1BAC  mov         ecx,11h  
00007FF7142E1BB1  call        text (07FF7142E13A2h)  

前六个寄存器,其余的栈传参,从左到右,内平栈
Linux: AMD64 ABI

七.内联汇编

使用场景:

1.直接访问底层硬件
2.使用特定的处理器指令
3.性能优化
4.实现特殊的程序逻辑

Linux内联语法:

在 Linux 中,内联汇编语法通常使用 asm 关键字来嵌入汇编代码到 C/C++ 程序中。内联汇编语法的基本格式如下:

asm("assembly code" : output : input : clobbered);

其中,assembly code 是要嵌入的汇编代码,output 是输出操作数,input 是输入操作数,clobbered 是会被修改的寄存器。

  • assembly code:这里放置你的汇编代码。
  • output:声明输出变量,可以是寄存器或内存地址。
  • input:声明输入变量,可以是寄存器或内存地址。
  • clobbered:声明可能被修改的寄存器。

示例1:

int myFunction(int arg1, int arg2);int main() {int arg1 = 1;int arg2 = 4;int add = 0;asm volatile ("push $100\n"         // 将 arg2 压入栈"push $200\n"         // 将 arg1 压入栈"call myFunction\n"   // 调用 myFunction函数"add $8, %%esp\n"     // 平栈:"=eax"(add)          //接收返回值: : );printf("%d\n",add);return 0;
}int myFunction(int arg1, int arg2) {return arg1-arg2;
}

示例2


int myFunction(int arg1, int arg2);int main() {int arg1 = 1;int arg2 = 4;int add = 0;asm volatile ("push %[arg2]\n"                     // 将 arg2 压入栈"push %[arg1]\n"                     // 将 arg1 压入栈"call myFunction\n"                  // 调用 myFunction"add $8, %%esp\n"                    // 平栈:"=eax"(add)                         //接受返回值: [arg2] "r" (arg2),[arg1] "r" (arg1)    //传入值重名[],随机寄存器: );printf("%d\n",add);return 0;
}int myFunction(int arg1, int arg2) {return arg1-arg2;
}

相关文章:

  • 单片机原理及应用:定时器/计数器综合应用
  • BioTech - 蛋白质结构、核酸结构、小分子构象的预测
  • npm run dev,vite 配置 ip 访问
  • 怎么把身份证压缩到200k以下?一分钟教你如图片压缩
  • 人工智能技术的应用
  • 重生奇迹mu敏弓加点攻略
  • PHP 正则表达式(PCRE)
  • 新一代通信协议 - Socket.D
  • javascript编程求三个数中最大的数
  • Pandas实战100例 | 案例 43: 数据排序
  • EtherCAT主站SOEM -- 16 --Qt-Soem通过界面按键控制电机转圈圈PV模式
  • 在开发时如何决定使⽤哪种数据类型?
  • 基于网络爬虫的租房数据分析系统
  • 简单谈一谈pytorch中混合精度训练(torch.cuda.amp)的功效及命令行参数解析器的使用
  • Spring整理-Spring Bean的作用域
  • python3.6+scrapy+mysql 爬虫实战
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Angular数据绑定机制
  •  D - 粉碎叛乱F - 其他起义
  • docker容器内的网络抓包
  • ES6系列(二)变量的解构赋值
  • express.js的介绍及使用
  • Linux CTF 逆向入门
  • Linux链接文件
  • PermissionScope Swift4 兼容问题
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 初识 webpack
  • 当SetTimeout遇到了字符串
  • 机器学习 vs. 深度学习
  • 前端之Sass/Scss实战笔记
  • 如何实现 font-size 的响应式
  • 微信开放平台全网发布【失败】的几点排查方法
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • #传输# #传输数据判断#
  • (3)(3.5) 遥测无线电区域条例
  • (6)添加vue-cookie
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (四)库存超卖案例实战——优化redis分布式锁
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)3D模板阴影原理
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .gitignore文件—git忽略文件
  • .md即markdown文件的基本常用编写语法
  • .Net CF下精确的计时器
  • .NET Core 实现 Redis 批量查询指定格式的Key
  • .NET Core实战项目之CMS 第一章 入门篇-开篇及总体规划
  • .net MySql
  • .NET 中各种混淆(Obfuscation)的含义、原理、实际效果和不同级别的差异(使用 SmartAssembly)
  • .NET中的Event与Delegates,从Publisher到Subscriber的衔接!
  • /etc/fstab和/etc/mtab的区别
  • /etc/shadow字段详解