32位汇编与16位汇编的改变
1寄存器的变化
32位寄存器兼容16位寄存器,例如EAX 的低16位变为AX了,其余的寄存器同理
注意:现在32位中的段寄存器给操作系统使用,所以有了权限一说
EAX EBX ECX EDX ESI EDI ESP EBP ;八个寄存器,都是32位寄存器,占4个字节
EIP EFLAGES ;特殊寄存器
CS ES SS DS GS FS ;其中GS FS是新增加的寄存器,这些段寄存器,并不是4个字节(32位的)还是以前16位的
注意:32位汇编内存是4G,而32位汇编寻址能力也是0-FFFFFFFF(2的32次方等于4G),所以32位没有分段的概念,但是有分区的概念,分区与分段不同就是多了保护属性
2分区
1常量区
2 数据区(初始化数据区和未初始化数据区)
3代码区 (没有栈区,栈区由编译器维护,编译器分配)
32位汇编的语法
32位汇编有伪指令的概念
硬指令:硬指令是在程序运行期间由计算机来执行的,如push ,mov等指令
伪指令:伪指令(伪操作)是在汇编程序对源程序进行汇编时处理的操作,完成诸如数据定义、存储器分配、指示程序开始结束等功能 如.model .code等
1伪指令
.386 ;定义指令集
.model FLAT,STDCALL ;内存平坦模式(表示内存是连续的,因为不能分段了) ,设置了调用约定以后声明函数就不需要设置调用约定了
option casemap:none ;告诉编译器程序大小写敏感,因为win32API大小写敏感
;定义常量区
.const
;定义数据区
.data
.data?;加?号表示未初始化
g_data dw ? ;数据的申请必须是? 也就是未初始化的
;两者的区别
;初始化的数据,不过你定义数据的时候,是否给? 都会写的EXE(PE文件中)
;未初始化的数据, 定义数据的时候只能给? 不在PE文件中保存
;定义代码区
.code
;使用伪指令proto函数声明
MyAdd PROTO stdcall n1:dword,n2:dword
;函数调用
invoke MyAdd,1,2
;函数实现,参数是n1,n2,指明的大小是DWORD(4个字节的),这里没有写调用约定,上面写了默认的调用约定了,也可以加调用约定
MyAdd PROC n1:dword,n2:dword
mov eax,n1
add eax,n2
ret
MyAdd endp ;函数定义的结束标志
语法
列出一些基本语法,具体的语法自行百度
;定义结构体类型
Date STRUCT
year dd ?
month dd ?
day dd ?
Date ends
;数据区
.data
g_data dw 0 ;定义全局变量
;代码区
.code
START proc ;函数入口点
local @date:Date ;定义结构体局部变量
mov @date.year, 1 ;初始化结构体
mov @date.month, 2
mov @date.day, 3
;条件
.if n1>n2 && n1>n3
代码
.endif
;循环
.while TRUE
.endw
START endp
end START
32位汇编弹框例子
写32位汇编和写c差不多,只要有库和头文件就可以调用,我是配置好了lib,所以直接包含库就可以调用win32 api
.386 ;386指令集
.model FLAT,STDCALL ;内存平坦,
OPTION CASEMAP:none ;区分大小写
;包含库
includelib user32.lib
includelib kernel32.lib
MB_OK equ 0
NULL equ 0
MessageBoxA proto stdcall ,:dword,:dword,:dword,:dword ;函数声明
ExitProcess proto stdcall , :dword
;常量区
.const
TITLE1 db "Win32", 0
MSG1 db "Hello World!", 0
;代码区
.code
START proc
invoke MessageBoxA, NULL, offset MSG1, offset TITLE1, MB_OK
call ExitProcess
START endp
end START