汇编语言(Assemble Language)学习笔记(更新中)

news2025/1/15 20:58:15

零.学习介绍和使用工具

【1】我们使用的教材是机械工业出版社的《32位汇编语言程序设计第二版》。
指导老师是福州大学的倪一涛老师。
这门课程教授的是Intel 80*86系列处理器的32位汇编。我们现在的处理器都兼容这个处理器。

这篇博客只是大二下汇编语言学习的总结,用于基础入门。

【2】环境和工具:

电脑系统:Windows11
VC6和Devc++:用于看c语言对应的汇编,便于研究(也可以直接使用里面的g++)
汇编器:masm6.15--编译汇编,将汇编程序执行
调试器:ollydbg

工具的使用这里省略。

【3】汇编指令的执行过程:

一.从机器语言到汇编语言

程序设计语言是人与计算机沟通的语言,程序员利用它进行软件开发。通常人们习惯使用类似自然语言的高级程序设计语言,如C,C++,Basic,Java等。
高级语言需要翻译为计算机能够识别的指令(机器语言),才能被计算机执行。机器语言是一串0和1组成的二进制代码,如果直接用它来编写程序太过于晦涩难懂且开发效率极低,称为低级语言。
于是我们将二进制底阿妈的指令和数据用便于记忆的符号(助记符,Mnemonic)表示就形成汇编语言(Assembly),所以汇编语言是一种面向机器的低级程序设计语言,也称为低层语言。

二.寄存器与存储

【1】存储有分为外存储器和内存储器。外存储器就是磁盘。而内存储器就是寄存器,内存(分为主存和缓存)。这里重点介绍一下寄存器。

【2】寄存器分类

【3】通用寄存器(重点)

32为兼容16位和8位。所以我们寄存器写EAX或AX都可以。EAX和AX可以分为AH和AL也就是高低两个寄存器。其他也是这样。

地址指针寄存器尽量不要用,很容易导致程序出错。

数据寄存器的习惯用法:

【4】段寄存器和专用寄存器(一般在系统内核用到,我们用不到,了解即可)

三.汇编指令

0.概述

汇编语言由以下3类组成:
1.汇编指令(机器码的助记符)
2.伪指令(由编译器执行)
3.其它符号(由编译器识别)

汇编语言的核心是汇编指令,它决定了汇编语言的特性。
具体语法:

1.注释

汇编语言分号后面是注释。

2.基本框架

例:

include irvine32.inc    ; 包含 Irvine32 库,提供 32 位输入输出功能
.data                   ; 定义数据段,这里定义的数据是存储在内存中
...                     ; 数据定义,这里省略
.code                   ; 定义代码段
main proc               ; 主过程开始
     ...                ; 执行过程,这里省略
     exit               ; 调用 Irvine32 库中的 exit 函数,程序退出
main endp               ; 主过程结束
end  main               ; 程序结束

3.数据的定义

在汇编语言中,不同的数据类型用来表示不同长度的数据。常见的数据类型,如:
BYTE:一个字节(8位)
WORD:一个字(16位)
DWORD:双字(32位)【也可以是dd】
QWORD:四字(64位)

.data
a dword 1

如果数值不确定,可以用?代替值

.data
a dword ?

4.通用数据处理指令

【1】传送指令mov

传送指令MOV把一个字节,字或双字的操作数从源位置传送至目的位置,可以实现常数,通用寄存器,主存(内存)之间的数据的传送。

例:

但是mov的两个参数不能都是常数或内存。

【2】堆栈操作指令push和pop

【3】与算数相关的指令--add,sub,mul等

基本格式也是add 目的操作数 源操作数。上面指令的两个参数也一样不能都是常数或内存。

【4】某个值+1

例:inc eax 

5.函数初步--函数的使用

【1】汇编中也有函数,将一系列操作进行封装。

函数调用指令:Call f

【2】比如输入输出整数的函数:

(1)输入输出整数--ReadInt和WriteInt
格式:

注:这里我们使用函数之前,要将输出的目标整数先存入eax中。另外这里我们输入输出使用的函数是Irvine32 库,它提供 32 位输入输出功能。

(2)输出字符--WriteString,输出edx中存储内存地址指向的变量

案例:打印hello world

include irvine32.inc  ; 包含 Irvine32 库

.data
    hello_msg byte "Hello World!", 0  ; 存储要显示的字符串
.code
main proc
    mov edx,offset hello_msg   ; 将要显示的字符串地址存储在 edx 中
    call WriteString           ; 调用 Irvine32 函数 WriteString 输出字符串
    exit                       ; 退出程序
main endp

end main

注:.data 部分用于声明和初始化数据段(存储在内存中的变量)。

在这里,hello_msg db "Hello World!", 0 这行代码的含义是:

(1)hello_msg:变量名称。
(2)byte:byte是一个伪指令,表示内存开辟一个字节的空间存储变量。
(3)"Hello World!":这是要存储的字符串数据,即 "Hello World!"。
(4)0:这里的 , 0 表示以 0 结尾,用于表示字符串的结束。在汇编语言中,定义字符串要在后面自己加上0当作终止符。

(5)offset:offset是来获取内存地址的。因为writeString需要的是变量地址,而不是变量,所以这里字符串不能直接mov edx, hello_msg。而应该使用offset关键字来获取变量的地址放入edx中,这里存的是地址而不是值。
当然mov edx, hello_msg也不会成功,因为字符串“hello world”是byte类型,只有8位,所以mov要用movzx。【还有一个movsx是带符号位的】

这行代码的作用是定义了一个以 "Hello World!" 结尾的字符串并将其存储在内存中,然后将其地址放在edx中,然后调用WriteString函数去内存中找到地址对应的字符串将其输出。

(3)输出换行

call Crlf       ;输出换行

6.定义数组

【1】定义数组

.data
a dd 1,2,3,4,5,6,7

如果要数组一次性赋值:

.data
a dd 10 dup(0)

【2】访问数组

访问第一个元素

include irvine32.inc
.data
    a dword 1, 2, 3, 4, 5, 6, 7
.code
start:
    mov eax, a
    call writeint
    exit
end start

注:writeint的本质是读取eax的四个字节,然后将这四个字节的数据转化为int值。
mov eax, a是将第一个元素的值放入eax中。

数组第i个元素访问:

include irvine32.inc
.data
    a dword 1, 2, 3, 4, 5, 6, 7
.code
start:
    mov eax, a+i*4
    call writeint
    exit
end start

还有一种a+i*4更加好看更接近c++的写法就是a[i*4],一般我们都这样写。
注:[]这个加不加知识规范的问题,a+i*4和[a+i*4]实际上和a[i*4]是一致的。

include irvine32.inc
.data
    a dword 1, 2, 3, 4, 5, 6, 7
.code
start:
    mov eax, a[i*4]
    call writeint
    exit
end start

7.分支和循环结构的汇编实现

【0】基础--比较和跳转指令

一般使用比较和跳转实现分支结构

比较指令: cmp x,y
跳转指令: jmp, jXXX(ja, jb, jz)

cmp x, y:执行操作 x-y (x与y的值不变),根据操作结果改变EFLAG相应的位。
jmp是无条件跳转,而jXXX是有条件跳转。

比如

ja loc: 若x与y是无符号数(程序员定义)且 x>y,则程序跳转到地址loc处执行。
jz/je loc: 若x与y是无符号数(程序员定义)且 x==y,则程序跳转到地址loc处执行
jb loc: 若x与y是无符号数(程序员定义)且x<y,则程序跳转到地址loc处执行
jg loc: 若x与y是有符号数(程序员定义)且 x>y,则程序跳转到地址loc处执行
jz/je loc: 若x与y是符号数(程序员定义)且 x==y,则程序跳转到地址loc处执行
jl loc: 若x与y是无符号数(程序员定义)且 x<y,则程序跳转到地址loc处执行

jge loc 有符号数x>=y

jle loc 有符号树x<=y

【1】分支结构汇编实现--实际是比较和跳转

分支结构案例:求整数 a与b最大值,并在屏幕中输出最大值

算法设计:

if a > b then 
    max=a 
else 
    max=b

分支具体思路:

c++中的写法
if(a<b){
    Block1
}else{
    Block2
}

转化为比较和跳转指令实现

if a<b goto L1
    Block2
    goto final
L1:    
    Block1
final:

但是上面并没有Block1和Block2的顺序并没有和我们c++的正常逻辑一一对应
当我们真正去写的时候会发现有点麻烦,一般写的时候会将比较条件反转,也就是像下面这样

if a>=b goto L1
    Block1
    goto final
L1:    
    Block2
final:

代码实现题目:

include irvine32.inc  ; 包含 Irvine32 库

.data
    a DWORD 0x10    ;DWORD,双字32位,0x10是16进制的10
    b DWORD 0x20

.code
main PROC
    mov eax, a
    cmp eax, b
    jna maxb 
    jmp final 
maxb: 
    mov eax, b
final : 
    call writeint
exit
main ENDP
END main

【2】循环结构汇编实现--实际是判断

循环结构案例

在内存中存有10个整数,求这10整数 最大值,并在屏幕中输出最大值

算法设计:

循环结构具体思路:

c语言中:
for(i=0;i<n;i++){
    Block;
}

循环的本质是if判断:
if(i<n){
    Block;
    i++;
}

i=0
L0: if(i<n) goto L1
    goto final
L1: Block
    i++
    jmp L0
final:

将比较条件反转,更简单书写,简化代码
i=0;
L0: if(i>=n)
    goto final
    Block
    i++
    jmp L0
final:

代码实现:

main proc
    mov eax, arr[0];eax存放最大值
    mov esi, 0; esi存放数组元素下标
L0: 
    cmp esi, 10
    jge final
    cmp eax, arr[esi*4]
    jge L1
    mov eax,arr[esi*4];
L1: 
    add esi, 1;
    jmp L0
final: 
    call writeint
exit
main endp

8.函数详解--自定义函数

1.用于模块化、是重要的封装机制
2.函数定义方式与执行逻辑
3.参数传递方法:
【1】内存变量(数据段)方式--简单说就是在.data下定义全局变量,所有函数都可以用。一般定义全局变量不好。
【2】寄存器方式--简单说就是将数据存放在寄存器中,然后函数要用去寄存器取。
【3】栈方式--将数据放在栈中,pop和push。

一般的话不用第一种,用第二和第三种。考试一般用第二种

案例:插入排序

这里就是采用第二种方式,每次调用函数之前先将参数存入寄存器中,后面函数执行的时候再去寄存器取。和ReadInt等差不多。

include irvine32.inc
.data
	arr1 dword 10 dup(?)
	arr2 dword 20 dup(?)
.code 
main proc
	mov edx,offset arr2
	mov ecx,20
	call buildArray
		
	mov edx,offset arr2
	mov ecx,20
	call outputArray 
	call crlf
		
	mov edx,offset arr2
	mov edi,20
	call insertSort 
		
	mov edx,offset arr2
	mov ecx,20
	call outputArray
exit
main endp

insertSort proc
	mov ebx,1		
startFor:
	cmp ebx,edi
	jge endFor
	mov ecx,[edx+4*ebx]  
      	mov esi,ebx
	sub esi,1 
startWhile:			
	cmp esi,0
	jl  endWhile
	cmp [edx+4*esi],ecx
	jle endWhile	 
	mov eax,[edx+4*esi];eax=arr[j]	          
	mov [edx+4*esi+4],eax
        sub esi,1
        jmp startWhile
endWhile:
        mov [edx+4*esi+4],ecx		          
        add ebx,1
        jmp startFor        
endFor:
	ret
insertSort endp

outputArray proc
	mov esi,0
startFor:
	cmp  esi,ecx
	jge  endFor		
	mov  eax,[edx+4*esi]
	call writedec
	mov  al,' '
	call writechar		
	add  esi,1
	jmp  startFor
endFor:
	ret
outputArray endp

buildArray proc	
	mov esi,0
startFor:
	cmp esi,ecx
	jge endFor
	mov eax,1000
	call randomRange
	mov [edx+4*esi],eax		
	add esi,1
	jmp startFor
endFor:
	ret
buildArray endp

end main

注:ret是函数返回,后面可以接参数。而exit是程序退出。

proc代表函数开始,endp代表函数结束。

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

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

相关文章

城乡居民基本医疗信息管理系统|基于Springboot的城乡居民基本医疗信息管理系统设计与实现(源码+数据库+文档)

城乡居民基本医疗信息管理系统目录 目录 基于Springboot的城乡居民基本医疗信息管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、病例管理 2、医院资讯信息管理 3、医院资讯类型管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选…

第十四次CCF-CSP(第二题 买菜、第四题 再卖菜)

第十四次CCF-CSP 第二题 买菜 原题链接&#xff1a;3263. 买菜 - AcWing题库 思路分析 简单来说&#xff0c;就是给出两组区间的集合A,B 求出两集合中相交区间的部分的长度&#xff0c;注意若区间 [s,t] 是相交的&#xff0c;则长度为 t-s 。 思路一 因为数据量比较小&am…

传输层的UDP协议

1. UDP协议报文格式 1.1 16位端口号 UDP协议报文中&#xff0c;端口号占2个字节&#xff0c;包括 源端口号 和 目的端口号。 1.2 16位UDP长度 UDP报文长度为2个字节 &#xff0c;即UDP数据报长度为0~65535&#xff0c;也就是64kb。 1.3 16位UDP检验和 数据在网络传输的…

Opencv4.5读取视频文件失败的原因

0. 写在前面 这篇短文是对上期编译的一个补充&#xff1a;Windows11OpenCV4.5Qt5.9.1安装教程_opencv4.5.4 windows11安装-CSDN博客 1. 问题现象 上篇博文是读取图片数据成功&#xff0c;结果今天做项目&#xff0c;测试视频文件和录像时&#xff0c;发现capture.isOpened()返…

ROS2组件component自定义实现

ROS2系列文章目录 ROS2中nav_msgs/msg/Path 数据含义及使用 ROS2中std_msgs/msg/Header 数据含义及使用 ROS中TF变换详解 ROS2中launch编写及参数含义&#xff08;launch.xml、python&#xff09; 提示&#xff1a;阅读并实践本文档后&#xff0c;将掌握并理解ros1中nodele…

Python面向对象析构函数你学会了吗?

​ 当我第一次接触Python面向对象编程时&#xff0c;我完全被析构函数的概念给搞懵了。但是&#xff0c;随着我深入研究&#xff0c;我发现它其实并没有那么复杂。 1.析构函数是什么 析构函数是Python面向对象编程中的一个重要概念&#xff0c;它是在对象生命周期结束时自动调…

网工内推 | 浪潮原厂售前、方案经理,上市公司大平台,最高20K

01 浪潮集团 招聘岗位&#xff1a;售前经理 职责描述&#xff1a; 1、负责数字生态、数字教育、工业互联网、数字乡村、智慧城市、智慧交通等数字经济领域解决方案的售前工作&#xff0c;包括但不限于融合方案编制、项目调研、订制文档输出及客户咨询支持。 2、负责与公司各产…

数据完整性

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 数据完整性 数据完整性是关系数据库的一个重要特征&#xff0c;一般包含实体完整性、参照完整性和用户自定义完整性 3 种 实体完整性 实体完整性&#xff1a;规定表中的每…

VXLAN学习笔记

声明&#xff1a;该博客内容大部分参考参考链接整理 什么是VXLAN&#xff1f; VXLAN(Virtual Extensible LAN)即虚拟扩展局域网&#xff0c;是大二层网络中广泛使用的网络虚拟化技术。在源网络设备与目的网络设备之间建立一条逻辑VXLAN隧道&#xff0c;采用MAC in UDP的封装方…

Python的asyncio 多线程

-- 多线程、进程、协程是什么就不讲了&#xff0c;&#xff08;就是你理解的一边呼吸&#xff0c;一边看文章&#xff09; 仅解决问题的话&#xff0c;下边两篇不用看&#xff0c; Python 中的 async await 概念-CSDN博客 再深一点的看这个 Python中的多线程、进程、协程、…

Vue.js+SpringBoot开发个人健康管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 健康档案模块2.2 体检档案模块2.3 健康咨询模块 三、系统展示四、核心代码4.1 查询健康档案4.2 新增健康档案4.3 查询体检档案4.4 新增体检档案4.5 新增健康咨询 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…

【项目设计】基于Httplib和Mysql的视频播放

项目源码&#xff08;绝对可以直接运行&#xff09; 一、项目介绍 1. 对视频播放系统的认识 搭建视频共享播放服务器&#xff0c;可以让所有人通过浏览器访问服务器&#xff0c;实现视频的上传查看&#xff0c;以及管理并播放的功能。主要是完成服务器端的程序业务功能的实现…

腾讯云轻量4核8G12M服务器性能如何?价格感人

腾讯云轻量4核8G12M服务器配置446元一年&#xff0c;646元12个月&#xff0c;腾讯云轻量应用服务器具有100%CPU性能&#xff0c;系统盘为180GB SSD盘&#xff0c;12M带宽下载速度1536KB/秒&#xff0c;月流量2000GB&#xff0c;折合每天66.6GB流量&#xff0c;超出月流量包的流…

springboot276基于JS的个人云盘管理系统的设计与实现

个人云盘管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装个人云盘管理系统软件来发挥其…

开发反应式API

开发反应式API 开发反应式API1 使用SpringWebFlux1.1 Spring WebFlux 简介1.2 编写反应式控制器 2 定义函数式请求处理器3 测试反应式控制器3.1 测试 GET 请求3.2 测试 POST 请求3.3 使用实时服务器进行测试 4 反应式消费RESTAPI4.1 获取资源4.2 发送资源4.3 删除资源4.4 处理错…

大话设计模式——7.抽象工厂模式(Abstract Factory Pattern)

1.介绍 抽象工厂模式是工厂模式的进一步优化&#xff0c;提供一个创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们具体的类。属于创建型模式。 UML图&#xff1a; 2.示例 车辆制造工厂&#xff0c;不仅可以制造轿车也可以用来生产自行车。 1&#xff09;Abs…

【技术类-02】python实现docx段落文字的“手动换行符(软回车)”变成“段落标记(硬回车)”

作品展示 背景需求&#xff1a; 制作周计划时&#xff0c;需要将周计划docx内所有的表格里的手动换行符&#xff08;软回车&#xff09;”变成“段落标记&#xff08;硬回车&#xff09;”&#xff0c; 全部改成段落标记&#xff08;硬回车&#xff09; 但是19份docx每份都要打…

人工智能入门学习笔记1:什么是人工智能

一、什么是人工智能 人工智能(Artificial Intelligence)&#xff0c;是一个以计算机科学&#xff08;Computer Science&#xff09;为基础&#xff0c;由计算机、心理学、哲学等多学科交叉融合的交叉学科、新兴学科&#xff0c;研究、开发用于模拟、延伸和扩展人的智能的理论、…

day06、07-MySQL

文章目录 一、MySQL概述1.1 安装1.2 数据模型1.3 SQL简介1.3.1 SQL通用语法1.3.2 分类 二. 数据库设计-DDL2.1 项目开发流程2.2 数据库操作2.2.1 查询数据库2.2.2 创建数据库2.2.3 使用数据库2.2.4 删除数据库 2.3 图形化工具2.3.1 介绍2.3.2 安装2.3.3 使用2.2.3.1 连接数据库…

Docker 容器化技术:构建高效、可移植的开发环境和部署流程|Docker 网络

为了支持网络协议栈的多个实例&#xff0c;Linux 在网络协议栈中引入了网络命名空间。这些独立的协议栈被隔离到不同的命名空间中&#xff0c;处于不同命名空间中的网络协议栈是完全隔离的&#xff0c;彼此无法通信。通过对网络资源的隔离&#xff0c;就能在一台宿主机上虚拟多…