从今天起开始学习intel汇编(一)汇编语言基础

来源:互联网 发布:gom引擎源码 编辑:程序博客网 时间:2024/05/21 15:49

引言:汇编是一种与机器硬件密切相关的语言,他也是一些高级语言编译过程中的一个中间结果, 汇编语言与机器语言比较接近,几乎是一一对应的关系。学习汇编语言可以让我们更好的理解计算机原理和操作系统原理。更重要的是在逆向分析,破解程序,发现漏洞,以及网络渗透攻击中,熟悉汇编是必备的一门基础语言。从今天起我开始要学习intel汇编,使用NASM汇编器。汇编编译器有很多种,导致汇编指令也很多,但是精通一种,学习其他完全不成问题。

一  内容首先来看下一条完整指令的组成部分, 标号(可选) 指令助记符(必须)操作数(通常是必须)注释(可选)

1.标号

  标号是标记指令会数据的标示符,表明了该指令会数据的地址

     数据标号:表示了变量的地址,为在代码中引用该变量提供方便,例如下面定义了一个名为count的变量

     count DWORD 100

     汇编器为每个标号分配一个数值地址,在一个标号后定义多个数据项是可以的,他们在内存中相互挨着

     array DWORD 1024, 2048

      DWORD 4069, 8192

      代码标号:程序代码区中的标号必须以冒号结尾   

      target:

      mov ax, bx

      jmp target

 2.指令助记符是一个简单的单词, 它表明了这条指令做什么操作例如:

     mov 将一个值赋值到另一地方去

     add 将2个值相加

     sub 相减

     mul 相乘

     jmp 跳转到另一地方执行

     call 调用一个过程

     NOP 空操作指令, 占一个字节,什么也不做

 3.操作数:一条汇编指令可以有0-3个操作数,每个操作数可能是寄存器,内存,常量表达式或者I/O端口

 4.注释:作者对程序的解释,以;字符开始为单行注释  以comment伪指令开始, 后面接一个用户自定义符号,结尾以用户相同自定义符号结尾

     comment !

     this line is a comment

!

二  一个汇编例子 addsub

TITLE Add and Subtract              (AddSub.asm)
INCLUDE Irvine32.inc
.code
main PROC
mov eax,10000h; EAX = 10000h
add eax,40000h; EAX = 50000h
sub eax,20000h; EAX = 30000h
call DumpRegs
exit
main ENDP
END main

 使用vs2005编译该代码,需要在网上下载intel汇编程序设计这本书的源代码,然后配置vs2005

 首先简历一个vc++空工程


然后添加一个C++源文件, 并将后缀名改为.asm

然后右键解决方案下面你的项目,点击属性,在弹出的对话框中选择最下面的microsoft macro assembler  然后在选择  general ->Include path,  选择你下载的源码的文件夹,这样就配置好了汇编头文件路径

  然后属性->链接器->输入->附加依赖项 添加C:\irvine\Irvine32.lib。

  最后属性->链接器->系统->子系统 选择 控制台(/SUBSYSTEM:CONSOLE);

  好了可以编译运行了。

  TITLE位指令将整行标为注释

  INCLUDE 伪指令从Irvine32.inc文件中复制信息

  .code标记代码段的开始

  main proc  proc 用来标记一个过程的开始

mov eax,10000h; EAX = 10000h
add eax,40000h; EAX = 50000h
sub eax,20000h; EAX = 30000h
这些
是一些操作

  call DumpRegs  调用函数显示寄存器的值 这是一个Irvine32.inc自定义函数

  exit退出程序 是Irvine32.inc定义的一个命令

  END main  end伪指令表明该行是汇编源程序的最后一行,编译器将忽略改行后面的所有内容,其后的标示符main 是程序启动过程的名字

三  汇编-连接-执行

步骤1:程序员使用文本编辑器创建ASCII文本文件,称为源文件

步骤2:编译器读取源文件,并生成目标文件(.OBJ)

步骤3:链接器读取目标文件并检查是否调用了链接库中的过程,链接器从库中复制所需的过程并将其同目标文件合并在一起生成可执行文件。

步骤4:操作系统装载器将和执行文件装入内存,并使CPU转移到程序的起始地址开始执行

四 内部数据类型

BYTE 8位无符号整数

SBYTE 8位有符号整数

WORD 16位无符号整数

SWORD 16位有符号整数

DWORD 32位无符号整数

  SDWORD 32位有符号整数

FWORD 48位整数

QWORD 64位整数

TBYTE 80位整数

REAL4 32位短实数

REAL8 64位长实数

REAL10 80位扩展精度实数

五 数据定义语句

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

  变量名:数据定义中赋予变量的名字是可选的

数据定义伪指令:可以使内部数据类型, 也可以是 DB DW DD DQ DT

  初始值:可以使0, 如果有多个初始值,要用,好分开,如果不想初始化变量,可以使用?

1.定义BYTE和SBYTE数据

value1 BYTE ‘A’ 字符常量

  value2 BYTE 0 最小无符号常量

value3 SBYTE -127

value6 BYTE ? 随机初始值

变量名是一个标号, 标记了该变量相对于其所在段的偏移,

  2.多个初始值

如果数据定义语句中有多个初始值,那么标号仅仅代表第一个初始值的偏移

  list BYTE 10,20,30,40

  并非所有的数据定义都需要标号

list BYTE 10,20,30,40

BYTE 50,60,70,80

3.定义字符串

想要定义字符串, 应将一组字符用单引号或者双引号括起来,以NULL(0)结尾

greeting BYTE "Good morning", 0

  greeting BYTE 'Good Night', 0

字符串可以占多行而无需额外制指定标号

greeting BYTE 'hello world'

BYTE 'this is intel assemble programming', 0

4.DUP指令

  给内充赋予相同的值

  BYTE 20 DUP(0) ;为20字节内存分配0

  BYTE 4 DUP(hello); 分配4个连续的hello, 也就是4*sizeof(hello)字节数

定义DWORD WORD QWORD都可BYTE一样

5.未初始化数据的声明

.data?可以用来声明未初始化数据段,可以减小编译后的尺寸

.data?

array byte 5000 dup(?)

五.符号常量

  通过将标识符与整数表达式文本联系起来而创建的,与保留村粗空间的变量不同,符号常量不占用任何实际的存储空间,它仅在编译期间使用,在运行期间不能更改

1. 等号伪指令

名字 = 表达式

当汇编程序时,所有出现名字的地方都由汇编器在预处理阶段替换为表达式,count = 500 mov ax, count 编译会生成 mov ax, 500

使用这种形式,更有利于维护和阅读。如果程序中使用了10次count ,以后想改变只需改一个地方。

2.计算数组和字符串的大小

list BYTE 10, 20, 30, 40

ListSize = 43

手动计算数组大小不好,我们可以让编译器自动为我们计算, 可以用$符号,当前程序语句的地址偏移值

list BYTE 10, 20, 30, 40

ListSize = $ - list

  如果数组元素是16位, 要除以2, 如果是32位要除以4

lsit word 10, 20, 30, 40

ListSize = ($ - list)/2

3.EQU伪指令

可以将符号名用整数或者任意文本联系起来

name EQU expression name EQU symbol name EQU <text>

在第一种格式中,表达式必须是整数, 在第二种格式中, 符号必须是已用"="或者EQU定义的符号名;第三种格式中,尖括号内可以使任意文本,当定义非整数是,这就分 非常有用:PI EQU <3.14>

0 0
原创粉丝点击