5.1 汇编语言:汇编语言概述

news2024/11/23 6:52:11

汇编语言是一种面向机器的低级语言,用于编写计算机程序。汇编语言与计算机机器语言非常接近,汇编语言程序可以使用符号、助记符等来代替机器语言的二进制码,但最终会被汇编器编译成计算机可执行的机器码。

相较于高级语言(如C、Python等),汇编语言学习和使用难度相对较大,需要对计算机内部结构、指令集等有深入的了解,以及具有良好的编程习惯和调试能力。但对于需要对计算机底层进行操作的任务,汇编语言是极其高效的,因为其可以实现对计算机底层资源的精细控制,极大地提高了计算机运行效率。

尽管在当今计算机界已经不再使用汇编语言来开发程序,但作为一名安全从业者掌握汇编语言将会是高手与专家之间最大的差距,汇编语言作为底层语言,具有直接访问计算机硬件和系统资源的能力,因此在系统级漏洞挖掘、内核安全、计算机反病毒等领域中具有非常重要的作用。

以下是关于汇编语言的应用场景:

  • 系统级漏洞挖掘:许多系统级漏洞,如堆栈溢出、整数溢出等,都是由于程序员没有理解底层操作系统和硬件的工作原理而导致的。因此,理解汇编语言可以帮助安全研究人员更好地了解底层的操作系统和硬件原理,从而更好地挖掘漏洞。

  • 内核安全:汇编语言是编写内核模块或驱动程序所必需的语言,例如,Linux内核中的大部分代码都是使用汇编语言实现的。因此,对于理解内核原理和进行内核安全研究来说,掌握汇编语言非常重要。

  • 计算机反病毒:许多计算机病毒和恶意软件都使用汇编语言编写,因此掌握汇编语言可以帮助研究人员更好地理解这些恶意软件的工作原理和行为,并提高反病毒软件的捕获率和准确性。

总之,熟练掌握汇编语言对于进行系统级漏洞挖掘、内核安全研究、计算机反病毒等领域都非常有帮助。虽然汇编语言相对来说比较底层和难以理解,但是深入掌握汇编语言将会极大地提高软件安全研究人员的技能和水平,让读者从一个高手蜕变成一名安全专家。

本章中所提到的汇编语言为Windows汇编,在Windows平台下读者可使用MASM工具对汇编语言进行编译测试,也可以使用通用的集成开发环境实现编译,笔者推荐使用RadASM工具,RadASM 是一个面向汇编编程的开发环境,提供了一系列工具和功能,用于编写、调试和优化汇编语言程序。该工具具有良好的可定制性和扩展性,且能提供丰富的工具和功能,方便程序员进行汇编语言的开发和调试工作。

1.1 RadASM

当读者准备好开发环境后可打开RadASM工具,选择文件新建工程按钮,并选择ConsoleApp选项填入自定义工程名称并一直点击下一步即可,当读者进入到主页面后会看到如下图所示的窗体,其中最右侧则是我们的项目目录,该目录下的Resources则是我们需要测试代码的地方,读者可自行点开*.asm文件并在此处写代码,当读者需要编译代码可使用快捷键Ctrl+Shift+V快速构建,也可点击右上角的编译构建按钮自行构建;

使用Win32汇编语言做开发其开发感觉与高级语言基本一致,并没有像大家想象中的那么困难,唯一的区别只是在高级语言中可以很容易实现的语句,而到了汇编语言这里将会变得较为繁琐,读者只要认真理解汇编语言中的每一条指令所代表的含义,则同样可以灵活的运用汇编语言开发大型项目,首先笔者来解释一下关于上述图片中代码的具体含义;

根据上述代码中第一行的定义.386p代表了指令集的选择,此处代表我们选用Intel 80386处理器的指令集,其中的p则代表将代码对齐到32位指令上,接着看第二行.model flat, stdcall此处代表了调用约定采用stdcall模式,并设置代码和数据段都使用平坦模型(flat model)来处理内存,第三行option casemap:none代表后续程序不区分大小写,当有了上述这三行定义后汇编语言的预定义部分也就结束了。

接着就是比较熟悉的定义语法了,这里的include/includelib分别代表头文件以及库文件的引用,如果读者需要调用Windows系统内的函数定义,则此处的头文件则是必须要包含windows.inc以及kernel32.inc头的,此外还需要导入kernel32.lib库来完成头文件功能的导入;

  • .data:定义已初始化变量。该指令定义了一个16位的可赋值变量Main,并将其初始化为1024。
  • .data?:定义未初始化变量。该指令定义了一个32位的未初始化变量lyshark。
  • .const:定义常量。该指令定义了一个以0h(十六进制)为结尾的字符串常量var1,内容为“lyshark”。
  • .code:代码段开始。该指令表示代码段的开始。

接下来就是main PROC以及main ENDP定义了,此处的定义部分读者可理解为int main()函数,此处的功能同样是定义主程序入口和结束,而当我们需要编写应用程序时只需要在上方不同的段内填充参数即可,其开发流程可以与高级语言一致。

1.2 汇编中的变量

MASM 定义了多种内部数据类型,每种数据类型都描述了该类型的变量和表达式的取值集合,汇编语言中数据类型的基本特征是以数据位数为度量单位,8,16,32,48,64,80位,而除此之外其他的特征如(符号,指针,浮点数)主要是为了方便我们记忆变量中存储的数据类型,如下表中所定义的部分,则是IEEE委员会发布的标准内部数据类型;

数据类型作用(无符号)数据类型作用(有符号)
BYTE8位无符号整数SBYTE8位有符号整数
WORD16位无符号整数SWORD16位有符号整数
DWORD32位无符号整数SWORD32位有符号整数
FWORD48位整数(远指针)QWORD64位整数定义
REAL432位(4字节)短实数REAL864位(8字节)长实数

数据类型定义语句为变量在内存中保留存储空间,并且可以选择为变量指定一个名字,在汇编语言中所有的数据无非就是BYTE的集合,数据的定义语句格式如下;

[变量名] 数据定义伪指令 初始值[....]

在数据定义语句中使用BYTE(定义字节)SBYTE(定义有符号字节)伪指令,可以为每一个或多个有符号或无符号字节分配存储空间,每个初始值必须是8位整数表达式或字符常量,例如下面的定义:

.data
  var1 BYTE 'A'      ; 定义字符常量
  var2 BYTE ?        ; 定义未初始化变量
  var3 BYTE 0        ; 最小的无符号字节常量
  var4 BYTE 255      ; 最大的无符号字节常量
  var5 SBYTE -128    ; 最小的有符号字节常量
  var6 SBYTE +127    ; 最大的有符号字节常量

如果一条数据定义语句中有多个初始值,那么标号仅仅代表第一个初始值的偏移,如下我们首先定义一个BYTE数组,然后通过反汇编查看地址的偏移变化就能看到效果啦:

.data
  list BYTE 10,20,30,40,50

00E71000 | B8 0030E700        | mov eax,main.E73000                 | E73000=10
00E71005 | B8 0130E700        | mov eax,main.E73001                 | E73001=20
00E7100A | B8 0230E700        | mov eax,main.E73002                 | E73002=30
00E7100F | B8 0330E700        | mov eax,main.E73003                 | E73003=40
00E71014 | B8 0430E700        | mov eax,main.E73004                 | E73004=50

并非所有的数据定义都需要标号,如果想继续定义以list开始的字节数组,可以在随后的行上接着上面的定义:

.data
  list BYTE 10,20,30,40,50
  list BYTE 60,70,80,90,100

当然除了定义整数字符以外,还可以定义字符串,要想定义字符串应将一组字符用单引号或双引号括起来,最常见的字符串是以空格结尾0h,在C/C++中定义字符串无需添加结尾0h,这是因为编译器会在编译的时候自动的在字符串后面填充了0h,在汇编语言中我们需要手动添加字符串结尾的标志,以告诉汇编器字符串的结束。

.data
  string1 BYTE "hello lyshark",0h
  string2 BYTE "good night",0h

00F23000  68 65 6C 6C 6F 20 6C 79 73 68 61 72 6B 00 67 6F hello lyshark.go 
00F23010  6F 64 20 6E 69 67 68 74 00 00 00 00 00 00 00 00 od night........ 

字符串也可以占用多行,而无须为每行都提供一个编号,如下代码也是合法的:

.data
  string1 BYTE "welcom to the Demo program"
      BYTE "created by lyshark",0dh,0ah,
      BYTE "url:lyshark"
      BYTE "send me a copy",0dh,0ah,0

十六进制0dh,0ah也称为CR/LF(回车换行符),或者是行结束的字符,在向标准输出设备上写的时候,回车换行符可以将光标移动到下一行的开头位置,从而继续填充新的字符串。

有时我们需要初始化一些空值的内存空间,在为内存地址分配空间的时候,DUP伪指令就显得尤为重要,初始化和未初始化数据均可使用DUP指令定义,其定义语法如下:

.data
  string1 BYTE 20 DUP(0)       ; 分配20字节,全部填充0
    BYTE 20 DUP(?)             ; 分配20字节,且未初始化
    BYTE 50 DUP("stack")       ; 分配50字节,"stackstack..."

.data
  smallArray DOWRD 10 DUP(0) ; 分配40字节
  bigArray DOWOR 5000 DUP(?) ; 分配20000字节

除了上面的例子以外,我们也可以直接定义常量,常量是不可以动态修改的数据类型,一般情况下一旦定义,那么在程序运行期间不可以被修改,常量的定义很简单,只需要将.data换成.const即可。

.const
  var1 BYTE  "hello world",0h   ; 初始化为BYTE的字符串
  var2 DWORD 10                 ; 初始化为10的DWORD类型
  var3 DWORD 100 dup(1,2)       ; 200个DWORD的缓冲区
  var4 BYTE  1024 dup(?)        ; 1024字节的缓冲区
  var5 BYTE "welcome",0dh,0ah,0 ; 0dh,0ah为换行符

有时我们需要计算一个指定数组的所占空间的大小,但手动计算显得特别麻烦,此时我们可以使用MASM提供的$符号来进行数组大小的计算过程,如下定义汇编器会将其进行预处理后回写到变量中存储。

.data
  list BYTE 10,20,30,40,50
  listsize = ($ - list)       ; 计算字节数据大小

.data
  list WORD 1000h,2000h,3000h,4000h
  listsize = ($ - list) /2    ; 计算字数据大小

.data
  list DWORD 100000h,200000h,300000h,400000h
  listsize = ($ - list) /4    ; 计算双字数据大小

.data
  MyString BYTE "hello lyshark",0h
  MyString_len = ($ - MyString)

1.3 标准输入与输出

在汇编语言中,有时我们需要获取到数据的输入输出,由于汇编中并不存在屏幕打印功能,此处如果读者需要使用此功能,则必须调用系统所提供的库函数来实现,一般要想实现输入输出有多种图形,具体来说,StdInStdOut分别代表标准输入流和标准输出流;WriteFile函数用于向文件或其他输出设备写入数据;crt_scanfcrt_printf是格式化输入/输出函数,这些库函数的调用都可以使用invoke这个伪指令来实现,invoke是MASM中提供的调用关键字,使用它可实现调用各类API函数的目的。

StdIn/StdOut

如果读者需要使用该函数输出,则需要包含masm32.inc头文件,该头文件为汇编语言程序员提供了一组常用的宏和函数,在这个头文件中,定义了StdIn、StdOutStdErr三个宏,它们分别代表标准输入流、标准输出流和标准错误流。

使用masm32.inc中的这些宏,可以方便地将输入输出重定向到控制台或文件中,而无需直接调用Windows API函数。例如,可以使用StdIn宏从控制台读取用户输入,使用StdOut宏向控制台输出字符流。这些宏的使用方式与在C语言中使用 stdin 和 stdout 类似。

下面是一些示例代码,使用masm32.inc头文件来实现标准的输入输出:

  .386
  .model flat, stdcall
  
  include masm32.inc
  include kernel32.inc
  includelib masm32.lib
  includelib kernel32.lib

.data
  len equ 20
  OutText dw ?
  ShowText db "请输入一个数: ",0

.code
  main PROC
    invoke StdOut, addr ShowText    ; 输出提示信息
    invoke StdIn, addr OutText,len  ; 等待用户的输入
    invoke StdOut, addr OutText     ; 输出刚才输入的内容
    ret
  main ENDP
END main

crt_printf/crt_scanf

除了使用MASM定义的宏之外,读者也可以使用C语言库函数中的一些输出函数,为了使用crt_printf,需要在程序中包含msvcrt.inc头文件,并将msvcrt.lib库作为链接器参数之一。然后,可以使用crt_printf宏来输出格式化的文本信息到控制台或文件中。

下面是一个简单的使用crt_printf的示例程序:

  .386
  .model flat, stdcall
  
  include msvcrt.inc
  includelib msvcrt.lib
  
.data
  PrintText db "EAX=%d;EBX=%d;EDX=%d | InPut ->: ",0
  ScanFomat db "%s",0
  PrintTemp db ?
.code
  main PROC
    mov eax,10
    mov ebx,20
    mov ecx,30
    invoke crt_printf,addr PrintText,eax,ebx,ecx        ; 打印提示内容
    invoke crt_scanf, addr ScanFomat, addr PrintTemp    ; 输入内容并接收参数
    invoke crt_printf, addr PrintTemp                   ; 输出输入的内容
    ret
  main ENDP
END main

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/9d939a6f.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

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

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

相关文章

紧跟老板思维,这款数据可视化工具神了

在今时今日,依靠大数据可视化分析工具做出一张形象直观、符合企业审美的数据可视化分析报表都不是什么难事,难就难在于做出一张能够紧随老板思维变化展开可视化分析的数据可视化分析报表。接下来要介绍的这款数据可视化工具就是这么一款神奇的BI工具&…

整理文件轻松搞定,教你如何将文件夹里的文件进行类型归类保存

大家好!相信大家在日常工作和学习中都会面临着大量的文件管理问题,如何高效地整理和保存文件成为了一大难题。幸运的是,不仅可以帮助你高效整理文件,还能实现文件的类型归类保存。 首先,我们要进入文件批量查询高手主…

七夕给TA满分宠爱!浪漫攻略为约会加分

浪漫的七夕将至,无论是异地恋人还是约会情侣,怎么能缺少节日仪式感~精心策划的约会计划,让浪漫“超级加倍”。 美好的二人世界,共度甜蜜时光,当然需要提前做好攻略,风和日丽的好天气能为约会加分不少。在规…

分享书架二维码 = 分享了10多本电子书

铁子们!告诉你一个实用的方法,分享一个书架就等于分享了10多本电子书,不用再一本一本的发送给客户啦! 方法如下: 1.首先打开FLBOOK电子杂志制作平台 2.我们开始上传自己的作品,选择PDF上传 3.进入编辑页面…

Python-主线程控制子线程结束-2

需求:主线程创建工作子线程和键盘输入监听子线程。 当用户输入 0 后, 工作子线程会收到停止信号并退出,此时键盘输入监听线程仍然运行; 当用户输入 1 后,会建立新的工作子线程; …

爆肝分享! 8款3D仿真软件推荐

当今,3D设计和制作已经成为许多领域中不可或缺的一部分,从建筑设计到电影制作,从游戏开发到工业设计,都需要强大的3D软件来实现想象中的世界。本文将介绍八款备受推崇的3D软件,这些软件不仅功能强大,而且易…

01、Cannot resolve MVC View ‘xxxxx前端页面‘

Cannot resolve MVC View ‘xxxxx前端页面’ 没有找到对应的mvc的前端页面。 代码&#xff1a;前端这里引入了 thymeleaf 模板 解决&#xff1a; 需要添加 thymeleaf 的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>s…

卷积神经网络——下篇【深度学习】【PyTorch】【d2l】

文章目录 5、卷积神经网络5.10、⭐批量归一化5.10.1、理论部分5.10.2、代码部分 5.11、⭐残差网络&#xff08;ResNet&#xff09;5.11.1、理论部分5.11.2、代码部分 话题闲谈 5、卷积神经网络 5.10、⭐批量归一化 5.10.1、理论部分 批量归一化可以解决深层网络中梯度消失和…

需求自动拆解子需求功能上线!自动估算再升级!

CoCode开发云旗下Co-Project V3.5智能项目管理平台正式发布&#xff0c;平台需求板块、估算板块以及需求分析工具全新升级&#xff1a;需求自动拆解为子需求&#xff0c;自动估算功能优化&#xff0c;需求分析工具界面优化。 需求自动拆解为多个子需求&#xff0c;有助于需求细…

2023.8 - java - String类

字符串广泛应用 在 Java 编程中&#xff0c;在 Java 中字符串属于对象&#xff0c;Java 提供了 String 类来创建和操作字符串。 String str "Runoob"; 在代码中遇到字符串常量时&#xff0c;这里的值是 "Runoob"&#xff0c;编译器会使用该值创建一个 S…

Hbase分布式安装

一、环境准备 启动zookeeper 启动hdfs 二、安装 上传安装包 1、解压 tar -zxf hbase-2.2.2-bin.tar.gz -C /opt/installs/2、更名 mv hbase-2.2.2/ hbase3、配置环境变量 [roothadoop11 conf]# vim /etc/profile export HBASE_HOME/opt/installs/hbase export PATH$PATH:$…

python操作elasticsearch

python操作elasticsearch_一个高效工作的家伙的博客-CSDN博客 待更新

5.物联网LWIP之Socket编程优化与实现(补充4)

UDP编程模型 1.UDP C/S模型 2.UDP API socket int socket(int domain, int type, int protocol); domain: AF_INET 这是大多数用来产生socket的协议&#xff0c;使用TCP或UDP来传输&#xff0c;用IPv4的地址 AF_INET6 与上面类似&#xff0c;不过是来用IPv6的地址 …

开学什么电容笔便宜又好用?ipad可以用的手写笔

如今&#xff0c;随着人们生活的智能化&#xff0c;一些人已经把传统的手提电脑换成了平板电脑。无论是用iPad画图&#xff0c;还是用来写笔记&#xff0c;我觉得它都很方便&#xff0c;但苹果的Pencil却很贵&#xff0c;很多人买不起。根据我对电容笔的深刻理解&#xff0c;如…

Java 注解计算12生肖,java Data中获取年,根据生日日期获取生肖注解,根据输入时间获取生肖,自定义注解的方式获取生肖 根据年份时间获取十二生肖

最近&#xff0c;开发中需要增加生肖&#xff0c;但是不想增加字段&#xff0c;于是通过注解的方式&#xff0c;实现生日与生肖的转换。 话不多说&#xff0c;直接上代码&#xff0c;如下&#xff1a; 实体类中的字段&#xff0c;添加自定义注解&#xff08;ToChineseZodiacSe…

Echarts面积图2.0(范围绘制)

代码&#xff1a; // 以下代码可以直接粘贴在echarts官网的示例上 // 范围值 let normalValue {type: 内部绘制,minValue: 200,maxValue: 750 } // 原本的绘图数据 let seriesData [820, 932, 901, 934, 1290, 1330, 1320] let minData Array.from({length: seriesData.len…

Android创建签名文件,并获取签名文件MD5,SHA1,SHA256值

一、创建Android签名文件 使用Android Studio开发工具&#xff0c;可视化窗口进行创建 第一步&#xff1a;点击AndroidStudio导航栏上的 Build→Generate Signed Bundle / APK 第二步&#xff1a;选择APK选项 第三步&#xff1a;创建签名文件 第四步&#xff1a;输入创建签名的…

数字化系统如何让企业增收?数字化转型如何做到“业务为先”?

很多时候企业往往觉得自己一定要用更高端、更先进的系统才算是完成了数字化转型&#xff0c;但事实是这样的数字化转型往往伴随着大量时间、精力甚至是财力的投入&#xff0c;还一点收益都见不到。对于大部分企业来说&#xff0c;数字化转型是一个持久战&#xff0c;因此&#…

STL---list

目录 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用注意事项 2.list接口介绍及模拟实现 2.1构造​编辑 2.2容量 2.3修改 3.list迭代器 4.迭代器失效 5.模拟实现 6.vector和list的区别 1. list的介绍及使用 1.1 list的介绍 list的文档介绍 1. list是可以在常…

第十四课:采用 Qt 开发翻页/分页/多页窗体组件

功能描述&#xff1a;采用 Qt 开发一个翻页/分页/多页的窗体组件&#xff0c;封装为 QWidget 的子类&#xff0c;在你的应用程序中可直接使用。 一、最终演示效果 本次制作的翻页/分页/多页窗体组件是基于 Qt 开发&#xff0c;整个程序封装成 PageWidget 类&#xff0c;继承于…