深入浅出,快速安装并了解汇编语言

1.什么是汇编语言

了解汇编语言需要先从了解机器语言开始,在计算机发展的初期阶段,机器语言是计算机直接理解和执行的二进制代码语言,其核心特点包括直接执行性、资源高效性、学习难度大以及平台依赖性。它主要由指令码构成,这些指令码包括操作码和操作数,用于指示计算机执行的具体操作。当时的程序员会将二进制指令编码打孔在纸带上,然后将这些纸带送入计算机进行读取和执行。
下图就是一段纸带程序
在这里插入图片描述
这种方式非常繁琐且容易出错,因为程序员需要记住每个操作的二进制代码,为了简化编程过程,汇编语言应运而生。为了简化编程过程,研究人员开始使用助记符(mnemonics)来代表机器指令。这些助记符通常是简短的英文缩写,易于记忆和理解。随着助记符的使用,需要一种工具将这些助记符转换为机器语言。这种工具被称为汇编器(assembler)。汇编器可以将用助记符编写的程序(汇编语言)转换为机器语言,从而使得编程更加高效和便捷。
在这里插入图片描述
早期的汇编语言起源于20世纪50年代,由IBM工程师为IBM 704计算机开发,与特定计算机架构紧密相关。汇编程序的雏型在EDSAC上诞生,采用单字母指令码、十进制地址和终结字母组成。首个汇编程序是50年代中期的符号优化汇编程序(SOAP),专为IBM650计算机设计,旨在优化磁鼓中指令的分布以提高效率。随后,IBM704计算机的符号汇编程序(SAP)成为汇编程序发展的重要里程碑,其模型至今影响深远。
随着计算机技术的发展,汇编语言逐渐标准化,并出现了多种不同的汇编语言,以适应不同的计算机架构。例如,x86架构有其特定的汇编语言,而ARM架构也有其自己的汇编语言。现代汇编语言常用于需要直接操作硬件或对性能要求极高的场合,如操作系统内核开发、嵌入式系统编程等。
这里我们使用NASM(Netwide Assembler),这是一款基于8086x86-64平台的汇编语言编译程序,它支持x86与x64架构的CPU(但不支持ARM架构),并可以在Linux、Mac OS X、Windows等操作系统上运行。NASM的语法被设计得简单易懂,并且支持大量的文件格式,如COFF、ELF、Mach-O等。

2.安装NASM

Windows系统安装NASM汇编语言

大家可以在NASM汇编语言代码官网查看安装方法和文档NASM官网
Windows系统可以直接下载.exe安装包Windows_64安装包下载
在这里插入图片描述
安装完成后将nasm.exe文件的安装路径添加到path环境中即可,安装完成后在cmd终端输入nasm -v查验下是否安装成功
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Linux系统安装NASM汇编语言

在Linux中安装NASM更为简单,只需要一行命令:
sudo apt install nasm nasm -v

3.编写第一个汇编语言代码

按照惯例,第一个程序依旧是输出"hello world"。

; hello.asm
section .datahello db 'Hello GGBond!', 0x0asection .textglobal _start_start:mov eax, 4          mov ebx, 1          mov ecx, hello     mov edx, 14         int 0x80          ; exit(0)mov eax, 1          xor ebx, ebx      int 0x80  

代码结构如下:

  1. 数据段

    • hello:这是一个字节数组,存储了字符串'Hello GGBond!'和一个换行符(ASCII码为0x0a)。
  2. 代码段

    • global _start:指示链接器(linker)程序的入口点是_start标签。
    • _start标签下的指令是程序开始执行的地方。
    • 首先,通过一系列mov指令将系统调用sys_write的参数准备好:
      • eax:系统调用号(4表示sys_write)。
      • ebx:文件描述符(1表示标准输出)。
      • ecx:指向要写入数据的指针(hello数组的地址)。
      • edx:要写入的数据长度(14个字节,包括字符串和换行符)。
    • 使用int 0x80触发系统调用,执行写入操作。
    • 接着,准备sys_exit系统调用的参数:
      • eax:系统调用号(1表示sys_exit)。
      • ebx:退出状态(使用xor ebx, ebx清零,表示正常退出)。
    • 最后,再次使用int 0x80触发系统调用,终止程序。

接下来编译运行这段代码:
先将hello.asm汇编源代码文件编译成名为hello.o的ELF格式目标文件

nasm -f elf -o hello.o hello.asm

最后使用LD链接器来将目标文件链接成最终的可执行文件

 ld -m elf_i386 -o hello hello.o

运行可执行文件后即可在终端输出"hello world"了

./hello

4.在主程序中引用子程序

在汇编语言中,实现一个主文件调用多个子文件的方法通常是通过使用包含指令(如 .include%include)来引入其他文件中的代码,这些文件可以包含函数、宏、常量定义等。
这里先新建三个.asm文件
main.asm:主文件。sub1.asm:子文件1。sub2.asm:子文件2。

; 主文件 main.asm
section .datasection .bsssection .textglobal _start_start:call sub1_functioncall sub2_functionmov eax, 1         xor ebx, ebx        int 0x80         %include "sub1.asm"
%include "sub2.asm"
; 子文件1 sub1.asm
section .text
sub1_function:mov eax, 4        mov ebx, 1          ; 文件描述符mov ecx, message1   ; 消息地址mov edx, len1       ; 消息长度int 0x80            ; 中断调用retsection .data
message1 db 'Hello from sub1!', 0xA
len1 equ $ - message1
; 子文件2 sub2.asm
section .text
sub2_function:mov eax, 4        mov ebx, 1        mov ecx, message2   mov edx, len2      int 0x80          retsection .data
message2 db 'Hello from sub2!', 0xA
len2 equ $ - message2

文件编写完成后,使用 nasm 汇编器将每个 .asm 文件编译成目标文件(.o 文件),再使用 ld 链接器将所有目标文件链接成一个可执行文件 main。

nasm -f elf32 main.asm -o main.o
nasm -f elf32 sub1.asm -o sub1.o
nasm -f elf32 sub2.asm -o sub2.o
ld -m elf_i386 -o main main.o sub1.o sub2.o
./main

5.NASM汇编常用指令表

NASM汇编只要指令分为:数据传输指令、算术指令、逻辑指令、控制转移指令、字符串指令与其他指令

指令含义应用方法
mov移动数据到寄存器或者内存mov destination, source:将source的内容复制到destination中,操作字长由参数字长决定。例如,mov eax, ebxebx的值移动到eax寄存器中。
lea加载有效地址lea des, src:将src的有效地址加载到des中。例如,lea eax, [ebx+8]ebx+8的内存地址加载到eax寄存器中。
inc操作数增加1inc destination:将destination的值增加1。例如,inc eaxeax的值增加1。
dec操作数减1dec destination:将destination的值减少1。例如,dec ebxebx的值减少1。
add加法add destination, source:将source的值加到destination上。例如,add eax, ebxebx的值加到eax上。
sub减法sub destination, source:从destination中减去source的值。例如,sub eax, ebxeax中减去ebx的值。
adc带进位加法adc destination, source:将source的值加到destination上,并加上进位标志位。例如,adc eax, ebxebx的值加到eax上,并加上之前的进位。
sbb带进位减法sbb destination, source:从destination中减去source的值,并减去进位标志位。例如,sbb eax, ebxeax中减去ebx的值,并减去之前的进位。
mul无符号乘法mul multiplier:将ALAX中的值与multiplier相乘,结果存储在AXDX:AX中。例如,mul ebxALAX中的值与ebx相乘。
imul有符号乘法imul multiplier:与mul类似,但处理有符号数。例如,imul ebxALAX中的值与ebx相乘。
div无符号除法div divisor:将AXDX:AX中的值除以divisor,商存储在ALAX中,余数存储在AHDX中。例如,div ebxAXDX:AX中的值除以ebx
idiv有符号除法idiv divisor:与div类似,但处理有符号数。例如,idiv ebxAXDX:AX中的值除以ebx
cmp比较两个数cmp destination, source:比较destinationsource的值,并设置标志寄存器。例如,cmp eax, ebx比较eaxebx的值。
jmp无条件跳转jmp label:无条件跳转到label指定的地址。例如,jmp start跳转到标签start处。
je/jz跳转,如果相等/零je/jz label:如果零标志位(ZF)被设置,则跳转到label。例如,je equal_label在相等时跳转。
jne/jnz跳转,如果不相等/非零jne/jnz label:如果零标志位(ZF)未被设置,则跳转到label。例如,jne not_equal_label在不相等时跳转。
jg/jnle跳转,如果大于/不小于等于jg/jnle label:如果有符号数大于且溢出标志位(OF)未设置或符号标志位(SF)与零标志位(ZF)不同,则跳转到label。例如,jg greater_label在大于时跳转。
jge/jnl跳转,如果大于等于/不小于jge/jnl label:如果有符号数大于等于或溢出标志位(OF)与符号标志位(SF)相同,则跳转到label。例如,jge greater_equal_label在大于等于时跳转。
jl/jnge跳转,如果小于/不大于等于jl/jnge label:如果有符号数小于且溢出标志位(OF)被设置或符号标志位(SF)与零标志位(ZF)相同,则跳转到label。例如,jl less_label在小于时跳转。
jle/jng跳转,如果小于等于/不大于jle/jng label:如果有符号数小于等于或溢出标志位(OF)与符号标志位(SF)不同,则跳转到label。例如,jle less_equal_label在小于等于时跳转。
ja/jnbe跳转,如果无符号数大于/不小于等于ja/jnbe label:如果无符号数大于且没有借位(CF=0)且零标志位(ZF)未被设置,则跳转到label。例如,ja above_label在无符号数大于时跳转。
jae/jnb跳转,如果无符号数大于等于/不小于jae/jnb label:如果无符号数大于等于或没有借位(CF=0),则跳转到label。例如,jae above_equal_label在无符号数大于等于时跳转。
jb/jnae跳转,如果无符号数小于/不大于等于jb/jnae label:如果无符号数小于且有借位(CF=1),则跳转到label。例如,jb below_label在无符号数小于时跳转。
jbe/jna跳转,如果无符号数小于等于/不大于jbe/jna label:如果无符号数小于等于或有借位(CF=1)且零标志位(ZF)被设置,则跳转到label。例如,jbe below_equal_label在无符号数小于等于时跳转。
loop循环指令loop label:循环执行指令,每次循环ecx寄存器减1,当ecx为0时跳出循环。例如,loop start循环执行到ecx为0。
and逻辑与and operand1, operand2:对operand1operand2执行逻辑与操作,结果存储在operand1中。例如,and eax, ebxeaxebx进行逻辑与操作。
or逻辑或or operand1, operand2:对operand1operand2执行逻辑或操作,结果存储在operand1中。例如,or eax, ebxeaxebx进行逻辑或操作。
xor逻辑异或xor operand1, operand2:对operand1operand2执行逻辑异或操作,结果存储在operand1中。例如,xor eax, ebxeaxebx进行逻辑异或操作。
test测试(逻辑与,不修改操作数)test operand1, operand2:对operand1operand2执行逻辑与操作,但结果不存储,只设置标志寄存器。例如,test eax, ebx测试eaxebx的逻辑与结果。
not逻辑非not operand:对operand执行逻辑非操作。例如,not eaxeax的值取反。
shl左移shl operand, count:将operand的值左移count位。例如,shl eax, 1eax的值左移1位。
shr右移shr operand, count:将operand的值右移count位。例如,shr eax, 1eax的值右移1位。
sal算术左移(与shl相同)sal operand, count:将operand的值左移count位,并符号扩展。例如,sal eax, 1eax的值左移1位。
sar算术右移sar operand, count:将operand的值右移count位,并符号扩展。例如,sar eax, 1eax的值右

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2.2_3 纠错编码—海明码

目录 1、海明码的纠错过程 2、海明距离 3、确认检验码位数 4、确定校验码和数据的位置 5、求出校验码的值 6、检错并纠错 方法一 方法二 1、海明码的纠错过程 2、海明距离 两个合法编码(码字)的对应比特取值不同的比特数称为这两个码字的海明距离(码距),一…

1992-2021年 各省市县经过矫正的夜间灯光数据(GNLD、VIIRS)区域汇总:省份、城市、区县面板数据

1992-2021年 各省市县经过矫正的夜间灯光数据(GNLD、VIIRS)区域汇总:省份、城市、区县面板数据 .r.rar https://download.csdn.net/download/2401_84585615/90001905 从1992年至2021年,中国各省份、城市及区县的夜间灯光数据经过…

微信小程序上传微信官方审核流程(1)

1,打开微信开发者工具 2,微信开发者工具右上角有一个上传按钮,点击上传按钮 3,点击完上传按钮会弹出一个上传成功的提示,点击提示框中的确定按钮 4,点击完确定按钮后会显示填写版本好和项目备注 5&#x…

快速获取镜像包的方法

1、当我们需要在无网络的环境中,在Docker环境中安装某个镜像时,需要先下载这个镜像包后,再上传 2、下面以在minio为例 在有网络的电脑中使用使用命令下载 docker pull minio/minio将下载好的tar包保存到指定的目录下 save -o /home/cl/app…

11 —— 打包模式的应用

需求:在开发模式下想让webpack使用style-loader进行css样式的处理;让它把css代码内嵌在js中;在生产模式下提取css代码 —— 判断当前运行命令时所在的环境 方案:借助cross-env全局软件包,设置参数区分打包运行环境 …

docker容器化部署springboot项目

前言 docker安装 下载官网 选择自己的系统 然后安装文档内给的命令按顺序执行即可。设置仓库,安装docker. 一、更换镜像源 一般情况下,docker原本自带的镜像网站不一定连的上,就很容易导致下载镜像失败,因此需要换源. 创建/etc/docker/daemon.json并填入数据…

2024深育杯misc2

题目描述:攻击者远程服务器监听所用的端口是( )?请提交flag,例如端口号为80,则提交Sangfor{80} 附件解压打开是一个raw文件 用volatility3工具查看ip链接信息

UI自动化测试中公认最佳的设计模式-POM

一、概念 什么是POM? POM是PageObjectModule(页面对象模式)的缩写,其目的是为了Web UI测试创建对象库。在这种模式下,应用涉及的每一个页面应该定义为一个单独的类。类中应该包含此页面上的页面元素对象和处理这些元…

L14.【LeetCode笔记】返回倒数第k个节点

目录 1.题目 2.分析 思路 代码 提交结果 1.题目 面试题 02.02. 返回倒数第 k 个节点 实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。 注意:本题相对原题稍作改动 示例: 输入: 1->2->3->4->5 和 …

linux-进程间通信

进程的通信是两个或多个进程实现数据的交互,让不同的进程看到同一份资源,而这份资源是由操作系统创建管理的。如果让其中一个进程来提供的话会破坏该进程的独立性,因为这个进程内部的数据可以被其他进程看到,那这个独立性就遭到了…

基于阿里云服务器部署静态的website

目录 一:创建服务器实例并connect 二:本地文件和服务器share 三:关于IIS服务器的安装预配置 四:设置安全组 五:建站流程 六:关于备案 一:创建服务器实例并connect 创建好的服务器实例在云…

Java算法OJ(10)哈希表练习

目录 1.前言 2.正文 2.1俩数之和 2.2无重复字符的最长子串 2.3罗马数字转整数 2.4整数转罗马数字 3.小结 1.前言 哈喽大家好吖,今天来分享几道哈希表相关的练习题,操作比较基础但是思想比较重要,另外有许多思路与解法都是学习参照题解…

二叉树:堆的建立和应用

在建立堆之前,我们要知道什么是树和二叉树 树 树是一种非线性的数据结构,它是由n(n>0)个结点组成的一个具有层次关系的集合,之所以把它叫做树,是因为它长得像一棵倒挂的树,也就是根在上面&…

oracle的静态注册和动态注册

oracle的静态注册和动态注册 静态注册: 静态注册 : 指将实例的相关信息手动告知 listener 侦 听 器 , 可以使用netmgr,netca,oem 以及直接 vi listener.ora 文件来实现静态注册,在动态注册不稳定时使用,特点是:稳定&…

postgresql按照年月日统计历史数据

1.按照日 SELECT a.time,COALESCE(b.counts,0) as counts from ( SELECT to_char ( b, YYYY-MM-DD ) AS time FROM generate_series ( to_timestamp ( 2024-06-01, YYYY-MM-DD hh24:mi:ss ), to_timestamp ( 2024-06-30, YYYY-MM-DD hh24:mi:ss ), 1 days ) AS b GROUP BY tim…

调试器 gdb/cgdb 的使用

一. touch mycode.c vim mycode.c cgdb 下载 Ubuntu:sudo apt-get install -y cgdb Centos: sudo yum install -y cgdb Linux 下我们编译好的代码无法直接调试 g/gcc 默认的工作模式是release模式 程序要调试,必须是debug模式,编译时…

通过DataWorks实现MaxCompute跨项目迁移

本文为您介绍如何配置不同MaxCompute项目并实现数据迁移。 背景信息 本文使用的被迁移的原始项目为教程《简单用户画像分析(MaxCompute版)》中的WorkShop2023项目,您需要再创建一个迁移目标项目,用于存放原始项目的表、资源、配置…

【Linux】安装cuda

一、安装nvidia驱动 # 添加nvidia驱动ppa库 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update# 查找推荐版本 sudo ubuntu-drivers devices# 安装推荐版本 sudo apt install nvidia-driver-560# 检验nvidia驱动是否安装 nvidia-smi 二、安装cudatoolkit&…

Vue.js 学习总结(14)—— Vue3 为什么推荐使用 ref 而不是 reactive

前言 ref 和 reactive 是 Vue3 中实现响应式数据的核心 API。ref 用于包装基本数据类型,而 reactive 用于处理对象和数组。尽管 reactive 似乎更适合处理对象,但 Vue3 官方文档更推荐使用 ref。 我的想法,ref就是比reactive好用,…

ctfshow-Misc入门(1-16)

misc1 查看图片得到flag misc2 1、打开文本,发现以“塒NG”开头 3、修改文件格式为png格式 4、查看图片,得到flag *遇到的问题:无法直接修改后缀名 *解决方法:需要点击文件夹,然后点击查看,将文件拓…