汇编学习笔记(1)-汇编介绍

 

前言

汇编的学习记录,主要理一下学习路线及思路,细节方面可能不会做太详细的介绍,需要的还要查专业文档。开始要了解一下汇编之前,至少有一门高级语言的编程经验,要对操作系统、计算机结构有个大概的认识,这里不做这个方面的介绍。


一、汇编是什么?

汇编是最接近机器语言,可以直接操控硬件设备,处理速度快,体积小,多应用于核心算法,驱动开发,嵌入式设备等,它有大量的指令集构成,不同的CPU架构的指令集不同,所以汇编不具备移植性(指令也可以理解为助记符,针对机器码而言)。汇编主要的两个工具程序:汇编器(把汇编文字转换成机器码)、链接器(把多个汇编器编译的文件合成可执行的汇编程序)。

二、学习步骤

 

1.搭建汇编环境

硬件:准备32位 或64位 windows 的电脑,

软件:在win10 (64位)系统环境下搭建的汇编环境,下载dosbox,地址:DOSBox0.74-3-win32-installer.exe,masm32为汇编编译器,下载地址:masm32

详细使用过程到:win10汇编环境的搭建

2.语言层级,以及虚拟机

虚拟机就是运作在计算机中的程序,或者用来模拟物理机或虚拟计算机来执行其他的软件的程序。

编译器运行在计算机中,执行某种语言的编译工作,使其成为可执行的程序

编译器自举原理,假设A(初级),B(低级),C(高级)语言,首先使用机器码编写A-A编译器,随后发明了B语言,就用A语言完成A-B的编译器编译程序使用A-A完成编译于是就诞生了A-B编译器,随后用B语言开发出B-B的编译器程序用A-B完成编译,结果诞生B-B编译器,诞生C语言后,用就先编写B-C编译器,之后用C语言开发出C-C编译程序,用B-C完成编译,就诞生了C-C的编译器,这个就实现了编译器的自举。(可以理解为一种语言的诞生就是先诞生可在机器上运行的编译器)

 

VM0 直接代表物理机,一般有硬件实现。

理解语言层级:机器码>指令集架构(ISA)>汇编语言>高级语言。

与实际机器和语言相对,用 Level 2 表示 VM2,Level 1 表示 VM1,如下图所示。计算机数字逻辑硬件表示为 Level 1 机器。其上是 Level 2,称为指令集架构(ISA, Instruction Set Architecture) 。

3.了解CPU 基本架构图

  1. 汇编是理解计算机工作原理的最好语言,需要具备一定的计算机硬件结构知识,下面微机的基本设计。中央处理单元(CPU)是进行算术和逻辑操作的部件,包含了有限数量的存储位置——寄存器(register),一个高频时钟、一个控制单元和一个算术逻辑单元。
  2. 程序的执行及传输主要借助寄存器完成,通用寄存器主要用于算术运算和数据传输 ,标志寄存器EFLAGS主要对一些特殊的状态进行标记,指令寄存器EIP
32位通用寄存器
EAXEBP
EBXESP
ECXESI
EDXEDI

 

其中以EAX为例,低16又分为 AX寄存器,AX的16位又分AH 高8位,AL低8位,可以处理8位的值

32位标识16位高8位低8位
EAXAXAHAL
EBXBXBHBL
ECXCXCHCL
EDXDXDHDL

 

另外一些寄存器处理32位的同时,还可处理16位的值。

32位16位32位16位
EBPBPESISI
ESPSPEDIDI
16位段寄存器
CSES
SSFS
DSGS
标志寄存器EFLAGS
溢出方向中断符号零置为辅助进位奇偶进位标志位单步
OFDFIFSFZFAFPFCFTF

其他还有8个64位MMX 寄存器 和 8 个 128 位 XMM 寄存器, MMX 寄存器支持称为 SIMD(单指令,多数据,Single-Instruction,Multiple-Data)的特殊指令进行一些多媒体处理和应用通信处理;XMM寄存器被用于 SIMD 流扩展指令集。后面用到时再做名称介绍。

4.汇编语言示例

第一个汇编程序,进行简单的认识。

;进行两个数相加

main PROC                    ;程序入口
    mov eax, 1b              ;将数字 1 送入 eax 寄存器
    add eax, 10b             ;eax 寄存器加 2
    INVOKE ExitProcess, 0    ;程序结束
main ENDP                    ;结束标记符

 

指令结构解析为:操作指令 目标,源   (注意之间的空格)

目标统一为操作数分为三类:

  • 立即数——用数字文本表达式

  • 寄存器操作数——使用 CPU 内已命名的寄存器

  • 内存操作数——引用内存位置
     

指令本次使用到 mov ,add ,MOV 指令将源操作数复制到目的操作数,add对目标操作数数加上源操作数,源操作数不变 后面我们会进行更多的指令介绍。

main 为程序命名,

PROC 为伪指令,进行一些程序标注作用,程序执行时,进行标注说明,汇编设计支持多种伪指令操作,后面会一一介绍。

INVOKE ExitProcess 调用结束过程返回系统操作权。

5.汇编基础操作符

这里已高级语言的语法为引去理解倒推理并理解汇编语言,程序的编写离不开条件判断,或 、非 逻辑,就是以汇编为基础进行再次封装的结果,或者叫编写,先介绍指令类型。在从简单的指令开始介绍基础逻辑运算。

一条指令有四个组成部分:

  1. 标号(可选)

  2. 指令助记符(必需)

  3. 操作数(通常是必需的)

  4. 注释(可选)

[标号: ] 指令 [操作数] [;注释]

标号(label)是一种标识符,是指令和数据的位置标记。标号位于指令的前端,表示指令的地址。同样,标号也位于变量的前端,表示变量的地址。标号有两种类型:数据标号和代码标号。

数据标号标识变量的位置,它提供了一种方便的手段在代码中引用该变量。比如,下面定义了一个名为 count 的变量:

汇编器为每个标号分配一个数字地址。可以在一个标号后面定义多个数据项。在下面的例子中,array 定义了第一个数字(1024)的位置,其他数字在内存中的位置紧随其后:

array DWORD 1024, 2048
DWORD 4096, 8192

程序代码区(指令所在区段)的标号必须用冒号(:)结束。代码标号用作跳转和循环指令的目标。例如,下面的 JMP 指令创建一个循环,将程序控制传递给标号 target 标识的位置:

target:
mov ax,bx
...
jmp target

代码标号可以与指令在同一行上,也可以自己独立一行:

L1: mov ax, bx
L2 :

标号命名规则要求,只要每个标号在其封闭子程序页中是唯一的,那么就可以多次使用相同的标号

指令助记符,就是汇编定义的具体某项功能操作的短单词,如上面示例的:add,mov,jmp等。

操作数是输入输出的数值,每个指令后跟操作数为0~3个,操作数可以是寄存器、内存操作数、整数表达式和输入输出端口生成内存操作数有不同的方法,使用变量名、带方括号的寄存器等。变量名代表变量地址,并指示计算机使用给定地址的内存内容

示例操作数类型示例操作数类型
22整数常量eax寄存器
1+1整数表达式array内存

注释有两种指定方法:

单行注释,用分号(;)开始。汇编器将忽略在同一行上分号之后的所有字符。

块注释,用 COMMENT 伪指令和一个用户定义的符号开始。汇编器将忽略其后所有的文本行,直到相同的用户定义符号出现为止。

;这是单行注释

COMMENT !
        这是多行注释
        这是多行注释
!

 

伪指令 (directive) 是嵌入源代码中的命令,由汇编器识别和执行。伪指令不在运行时执行,但是它们可以定义变量、宏和子程序;为内存段分配名称,执行许多其他与汇编器相关的日常任务。

默认情况下,伪指令不区分大小写。例如,.data,.DATA 和 .Data 是相同的。


下面的例子有助于说明伪指令和指令的区别。DWORD 伪指令告诉汇编器在程序中为一个双字变量保留空间。另一方面,MOV 指令在运行时执行,将 myVar 的内容复制到 EAX 寄存器中:

myVar DWORD 26             ;定义常量26
mov eax,myVar              ;把myvar 送到寄存器eax

 

汇编器伪指令的一个重要功能是定义程序区段,也称为段 (segment)。程序中的段具有不同的作用。如下面的例子,一个段可以用于定义变量,并用 .DATA 伪指令进行标识:

.CODE 伪指令标识的程序区段包含了可执行的指令

.STACK 伪指令标识的程序区段定义了运行时堆栈,并设置了其大小:

示例代码:

;相加操作
.386
.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD

.data
oneval DWORD 10001000h
twodval DWORD 22222222h
threeval DWORD 33333333h

sum DWORD 0

.code
main PROC
    mov eax,oneval 
    add eax,twodval 
    add eax,threeval 
    mov sum,eax

    INVOKE ExitProcess,0
main ENDP
END main

 

标识符(identifier)是由程序员选择的名称,它用于标识变量、常数、子程序和代码标签。

标识符的形成有一些规则:

  • 可以包含 1 到 247 个字符。

  • 不区分大小写。

  • 第一个字符必须为字母 (A---Z, a---z) A 下划线 (_)、@、? 或 $。其后的字符也可以是数字。

  • 标识符不能与汇编器保留字相同。

 

保留字(reserved words)有特殊意义并且只能在其正确的上下文中使用。默认保留字是没有大小写之分 。如,MOV 与 mov、Mov 是相同的。

保留字有不同的类型:

  • 指令助记符,如 MOV、ADD 和 MUL。

  • 寄存器名称。

  • 伪指令,告诉汇编器如何汇编程序。

  • 属性,提供变量和操作数的大小与使用信息。例如 BYTE 和 WORD。

  • 运算符,在常量表达式中使用。

  • 预定义符号,比如 @data,它在汇编时返回常量的整数值。

6. X86数据类型以及定义

由上面代码我们发现.adta区所定义的一些变量,变量就要有属于他的数据类型,下面表格展示了汇编器识别的一组内部数据类型,按数据大小、是否有符号,是整数还是实数来描述其类型。

BYTE    

 8 位无符号整数,B 代表字节

SBYTE    

8 位有符号整数,S 代表有符号

WORD    

16 位无符号整数

SWORD    

 16 位有符号整数

DWORD    

32 位无符号整数,D 代表双(字)

SDWORD    

32 位有符号整数,SD 代表有符号双(字)

FWORD    

48 位整数(保护模式中的远指针)

QWORD    

 64 位整数,Q 代表四(字)

TBYTE    

 80 位(10 字节)整数,T 代表 10 字节

REAL4    

32 位(4 字节)IEEE 短实数

REAL8    

64 位(8 字节)IEEE 长实数

REAL10    

 80 位(10 字节)IEEE 扩展实数

 

自动定义示例:

nume  DWORD 1234   ;定义32双字符常量

数据定义中至少要有一个初始值,多个初始值用  “,”逗号分隔。如果不想对变量初始化,可以用?号作为初始值,不论什么进制类似的数据最后都会由编译器转化位二进制

DUP 操作符使用一个整数表作为计数器,位多个数据分配存储空间。多用为字符串和数组分配存储空间

aa DWord  4 DUP (10)        

BYTE 20 DUP ( 0 )       ;20 个字节,值都为 0
BYTE 20 DUP ( ? )       ;20 个字节,非初始化
BYTE 4 DUP ( "STACK" )  ; 共20 个字节,byte 字长8等于一个字节,5个字符就是5个字节
word1 WORD 65535        ;最大无符号数
word2 SWORD -32768      ;最小有符号数
word3 WORD ?            ;未初始化,无符号

7.汇编语言的一些常量

有整数常量和实数常量,又分有符号和无符号等,字符常量,字符串常量等

整数常量有2.进制(1010b),8进制(755o),10进制(18901d),16进制(1F4Ah)表示方法

字符常量 "A","c"

字符串常量有 "sdfsdfsfdsf"

 

未完待续.....

总结

这次汇编就记录到里,大概对汇编的代码结构有了初步的了解,后续学习运算符及逻辑判断等指令本文大多是知识点理解,学习路线说明,以及归纳总结,详细的使用技巧还要查阅资料,这里说明指令集特别的琐碎,毕竟目的就是为了看的懂汇编程序,了解其运行原理,做到认识理解就达到了初级目标。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值