首页 > 代码库 > 80x86汇编

80x86汇编

db定义字节类型变量,一个字节数据占1个字节单元,读完一个,偏移量加1

dw定义字类型变量,一个字数据占2个字节单元,读完一个,偏移量加2

dd定义双字类型变量,一个双字数据占4个字节单元,读完一个,偏移量加4

汇编程序的框架:
.386
.model flat, stdcall
.data
.code
start:
end start
应用程序的执行是从 END 定义的标识符后的第一条语句开始的。在上面的框架程序中就是从 START 开始。程序逐条语句执行一直到遇到 JMP,JNE,JE,RET 等跳转指令。这些跳转指令将把执行权转移到其他语句上,若程序要退出 Windows,则必须调用函数 ExitProcess。

ExitProcess proto uExitCode:DWORD

上面一行是函数原型。函数原型会告诉编译器和链接器该函数的属性,这样在编译和链接时,编译器和链接器就会作相关的类型检查。 函数的原型定义如下:

FunctionName PROTO [ParameterName]:DataType,[ParameterName]:DataType,...

简言之,就是在函数名后加伪指令PROTO,再跟一串由逗号相隔的数据类型链表。在前面的 ExitProcess 定义中,该函数有一个 DWORD 类型的参数。当您使用高层调用语句 INVOKE 时,使用函数原型定义特别有用,您可以简单地认为 INVOKE 是一个有参数类型检查的调用语句。譬如,假设您这样写:

call ExitProcess

若您事先没把一个DWORD类型参数压入堆栈,编译器和链接器都不会报错,但毫无疑问,在您的程序运行时将引起崩溃。但是,当您这样写:

invoke ExitProcess

连接器将报错提醒您忘记压入一个 DWORD 类型参数。所以我建议您用 INVOKE 指令而不是CALL去调用一个函数。INVOKE 的语法如下:

INVOKE expression [,arguments]

expression 既可以是一个函数名也可以是一个函数指针。参数由逗号隔开。大多数API函数的原型放在头文件中。 如果您用的是 hutch 的 MASM32,这些头文件在文件夹MASM32/include 下, 这些头文件的扩展名为 INC,函数名和 DLL 中的函数名相同,譬如:KERNEL32.LIB 引出的函数 ExitProcess 的函数原形声明于kernel.inc中。您也可以自己声明函数原型。 在我的教学课程中都使用 hutch 的windows。inc,这些头文件您可以从http://win32asm.cjb.NET下载。

好,我们现在回到ExitProcess 函数,参数uExitCode 是您希望当您的应用程序结束时传递 Windows 的。 您可以这样写:

invoke ExitProcess,0

把这一行放到开始标识符下,这个应用程序就会立即退出 Windows,当然毫无疑问个应用程序本身是一个完整的 Windows 程序。

.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

.data
.code
start:
invoke ExitProcess,0
end start

 

要访问某一个存储单元总是属于某个段,通过偏移找到指定的存储单元。
物理地址 = 段值 *16 + 偏移

CF是进位标志,
PF是奇偶标志
AF是辅助进位标志
ZF是零标志
SF是符号标志
OF是溢出标志.


esp执行cpu下次要执行的地址,EBP寄存器里存储的是是栈的栈底指针,通常叫栈基址.
ESP寄存器里存储的是在调用函数fun()之后,栈的栈顶。

80x86汇编