CH3、Windows汇编基础
.386
.model flat,stdcall
option casemap:none
定义程序使用的指令集、工作模式
相应的还有:.8086,.486,.586,.586p
内存模式有很多,如:
tiny small medium compact large huge flat
汇编经常遇到这样的代码:
mov ax,DATA
mov ds,ax
作用是给DS赋值。参考前面描述CPU结构的知识,知道不能直接写成
mov ds,DATA
但对于.model flat模式,MASM自动做了下面的定义:
ASSUME CS:flat, DS:flat, ES:flat, SS:flat, FS:ERROR,GS:ERROR
flat是内存平坦模式,意思是段寻址4G空间。
因此,CS,DS,ES,SS可以在程序中平坦使用。使用FS和GS则会报错。
.model 语句用于指定调用规则,即子程序的调用方式。就是说明了在调用API时的参数传递次序和堆栈平衡的方法。
option casemap:none 说明程序对大小写敏感。注意,Windows API是大小写敏感的,因此这里这么定义。
使用includelib 链接需要用到的lib库,如:
includelib user32.lib
对于所有要用到的库函数,在程序的开始部分必须预先声明。包括:
函数名称 PROTO[调用规则]:[第一个参数类型][,:后续参数类型]
全部声明所用到的Api函数显然很麻烦,因此可以使用include把声明包括进来,用法和C一样。
.data
数据段
.code
代码段,遇到end代码段结束。
.stack [堆栈大小]
定义堆栈段
有的变量一开始并不赋值,在程序运行过程中才赋值,因此放到:
.data?中。
如果定义一个缓冲区,则:
buffer byte 65536 dup(?)
定义固定变量,程序运行过程中不再修改:
.const
==========
一段Hello World例子代码
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.386
.model flat,stdcall
option casemap:none
MessageBoxA PROTO :dword , :dword, :dword, :dword
MessageBox equ <MessageBoxA>
includelib user32.lib
NULL equ 0
MB_OK equ 0
.stack 4096
.data
szTitle byte 'Hi!',0
szMsg byte 'Hello world!',0
.code
start:
invoke MessageBox, NULL, offset szMsg, offset szTitle, MB_OK
ret
end start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
编译指令:
ml /coff hello.asm /link /subsystem:windows
操作数的寻址方式:
1、 立即数寻址,操作数是常数
mov AL,0
mov EAX, 0fffffffH
2、 寄存器寻址,不和内存打交道。
MOV EAX, EBX
除了1、2两种外,其它寻址都要和内存打交道。
3、 直接寻址,给出操作数的内存地址。
定义变量dVar,寻址时
MOV EAX, dVar
MOV dVar, EBX
这相当于在C语言里用指针赋值一样
4、 寄存器间接寻址,地址在寄存器中。
MOV ESI, 00404011H
MOV EAX, [ESI]
5、 寄存器相对寻址,地址是寄存器和一个立即数相加得到的结果。
MOV ESI,00404011H
MOV EAX,[ESI + 4]
6、 基址变址寻址,地址是两个寄存器相加的结果。
MOV ESI, 0040200AH
MOV EBX,4
MOV EDI,[EBX + ESI]
7、 基址变址相对寻址,两个寄存器相加后再加一个立即数
MOV ESI, 0040200AH
MOV EBX,4
MOV EDI,[EBX + ESI + 4]
8、 基址变址比例相对寻址,变址寄存器需要乘以一个比例数。
MOV ESI, 0040200AH
MOV EBX,4
MOV EDI,[EBX*2 + ESI + 4]
段超越
为了确定内存中的地址,还需要借助段寄存器。
如果在基址寄存器中用了ESP(保存栈顶偏移)和EBP(栈数据访问),则段寄存器中的内存操作数在SS中,这是一种默认。
使用段超越前缀能够改变寻址方式中的默认使用的段寄存器。
MOV EAX, CS:[EDI] ;默认是DS
MOV EBX, ES:[ESP – 4] ;默认是SS
MOV DS: [EBP] ,ECX
CS段只能用来读取数据,因此只能作为源操作数的段前缀
MOV CS:[0040200AH] , EAX
Windows 32环境中,FS段保存系统使用的一些信息,如果要访问,必须明确指出段寄存器为FS。另外,Win32环境下,CS、DS、ES、SS在内存中指向同一个段,大小为4G,程序中一般不需要使用段超越前缀。
数据定义
二进制:后跟b/B、0001b
八进制:后跟o、33o
十进制:后跟D、27d
十六进制:后跟H、2Ah
程序中可以指明默认使用16进制数
.radix 16
简单数据类型
类型 助记符 简写 占用字节数 范围
字节 BYTE DB 1 0~255
字 WORD DW
双字 DWORD DD
远字 FWORD DF
四字 QWORD DQ
十字 TBYTE DT
有符号字节 SBYTE
有符号字 SWORD
有符号双字 SDWORD
定义变量:
[变量名] 助记符 表达式,[,表达式]
表达式是 ? 则不进行初始化
数组定义
ch DWORD 50 DUP (0)
定义ch为数组,共50个元素,每个元素初始值为0。
DUP是重复数据操作符。可以嵌套
ch DWORD 3 DUP (2 DUP (-1,-2))
相当于char ch[3][2], ch[0] = {-1,-2},ch[1] = {-1,-2} 。。。。
伪操作符,不真正生成数据。
PTR ,作用有二,
一是临时改变变量类型:
dVar DWORD 01020304H
MOV AX , WORD PTR dVar
MOV DX, WORD PTR dVar + 2
如果不用PTR就会报错,因为AX是16位,而dVar是双字类型。
MOV BYTE PTR dVar + 1 , 0FFH
MOV BYTE PTR dVar + 3 , 12H
将dVar的第一字节设置成0ffH,第三字节设置成12H。
作用二,指明操作传递的数据类型
有些语句能够知道传递的类型,比如
MOV AL , 0 ;传一个字节
MOV AX , [EBX] ;传一个字
但下面的语句就不知道了:
MOV [EBX] , 0
需要这样写:
MOV BYTE PTR [EBX] , 0
EQU,相当于C语言的#define
比如:
NULL EQU 0
MB_OK EQU 0
等于符号 =
为一个变量或者表达式定义一个等价符号名。
I = 100
DwFirst DWORD I
I = I + 1
DwSecond DWORD I
$ 当前地址计数器值
MOV EAX , $
EAX中是该指令所在的地址。
注意,程序中的每一行都有一个地址。
ORG 为程序的地址计数器赋值
aVar BYTE 01h
ORG $ + 10
bVar BYTE 02h
计数器当前值的基础上增加了10。
Offset 取地址
下面两条语句是等价的
dVar3 DWORD wVar2
dVar3 DWORD offset wVAr2
下面语句不等价
MOV EBX , dVar2
MOV EBX , offset dVar2
Type 返回变量占用字节数
Length 返回变量用DUP重复的数目,无重复返回1。
Size 返回type * length的值
操作符
算术操作符
+ - × / MOD
MOV EAX , 4 * 5
MOV EAX , OFFSET dVar2 – 10
Mov eax , 30 / 8
Mov eax , 30 mod 8
逻辑操作符
AND OR XOR NOT
关系操作符
EQ(等于) NE(不等于) LT(小于) LE(小于等于) GT(大于) GE(大于等于)
关系成立,结果为真,关系不成立,结果为假。
寻址问题
在实际寻址时,操作数类型很关键,比如:
MOV AL , -1
MOV AX , -1
MOV EAX , -1
同样是-1,但第一个-1 = 0FFH,第二个-1 = 0FFFFH,第三个-1 = 0FFFFFFFFH 。
数组元素的访问
可以这样定义变量
bVar byte 01h , 02h , 03h , 04h
wVar word 0101h , 0102h , 0103h , 0104h
dVar dword 01010101h , 01010102h , 01010103h , 01010104h
访问时
mov ebx , 2
mov al , bVar[ebx] ; al 中为03h
mov ax , wVar[ebx * 2] ; 加入比例因子,ax 中为0103h
mov eax , dVar[ebx * 4] ;
分享到:
相关推荐
### 汇编语言学习笔记知识点总结 #### 一、汇编语言概述 - **学习目标**:通过学习汇编语言,可以获得底层编程的实践经验,深入理解计算机如何执行程序的基本原理。 - **学习原则**:确保完全掌握了当前知识点后再...
汇编语言学习笔记---傻瓜式学汇编(共63页) 本文档是汇编语言学习笔记,涵盖了从基本的编程环境搭建到深入理解汇编语言的数据、顺序程序设计、分支结构程序设计、循环、数组及指针、函数、结构等方面的知识点。 ...
汇编语言学习笔记。
汇编语言学习笔记.zip
学习汇编语言,可以帮助我们理解计算机底层的工作机制,掌握指令集的运用,以及如何直接与硬件进行交互。以下是根据书中的内容进行的详细知识点解析: 1. **汇编语言基础**: - 汇编语言是一套指令集,对应于机器...
2024年我的汇编语言学习笔记
《汇编语言学习笔记》是基于王爽的经典教材编写的,涵盖了汇编语言的基础知识、CPU工作原理、寄存器的使用、程序设计以及内存访问等多个方面。以下是对这些知识点的详细阐述: 首先,汇编语言由三类指令组成:汇编...
110805026840769汇编语言学习笔记.md
学习汇编语言需要系统性和实践性。以下是一些建议,可以帮助您快速入门:首先,了解汇编语言的基本概念。汇编语言是一种低级语言,它直接使用计算机的机器语言指令来控制计算机的行为。汇编语言的主要特点是使用符号...
汇编语言学习笔记 (2).zip
《C28系列DSP汇编语言学习笔记》是针对德州仪器(TI)的C28x系列数字信号处理器(DSP)的一份详细教程,旨在帮助读者深入理解和掌握C28x DSP的汇编语言编程技术。汇编语言是低级编程语言,与硬件紧密相连,能实现...
### 汇编语言的基本学习笔记 #### 编译的例子(#3) 汇编语言是一种低级编程语言,它直接对应计算机硬件系统架构,并且几乎是一对一地映射为机器语言指令。编译的例子部分可能包括了如何将简单的汇编语言程序编译...
这份"80X86汇编语言程序设计学习笔记"是针对Intel 80X86系列处理器的汇编语言编程进行详细阐述的学习资料,适合对汇编语言感兴趣的程序员或计算机科学学生进行复习和深化理解。 80X86汇编语言的核心是基于Intel的...
### 汇编语言学习笔记知识点详解 #### 一、编程环境的搭建 汇编语言的学习首先需要构建一个良好的编程环境。本节介绍了一个典型的汇编语言开发环境配置过程: - **MASM32**: MASM32是Microsoft提供的一个免费的...
笔记涵盖了汇编语言的基础知识、寄存器、存储器、指令系统、地址总线、数据总线、控制总线、内存地址空间等多方面的内容,为学习汇编语言的学生和开发者提供了详细的参考 materials。 基础知识 汇编语言是一种低级...
4. **学习汇编语言的重要性** - **理解计算机底层**:学习汇编有助于理解计算机如何执行指令,对操作系统和编程有更深层次的认识。 - **优化技巧**:掌握汇编语言,程序员可以更好地识别并优化性能瓶颈,尤其是在...