- UID
- 2927
注册时间2005-8-29
阅读权限20
最后登录1970-1-1
以武会友
该用户从未签到
|
;以下为\masm32\tutorial\console\demo1\hello.asm中的内容:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; Build this with the "Project" menu using
; "Console Assemble and Link"
;
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include \masm32\include\windows.inc ; always first
include \masm32\macros\macros.asm ; MASM support macros
; -----------------------------------------------------------------
; include files that have MASM format prototypes for function calls
; -----------------------------------------------------------------
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
; ------------------------------------------------
; Library files that have definitions for function
; exports and tested reliable prebuilt code.
; ------------------------------------------------
includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.code ; Tell MASM where the code starts
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
start: ; The CODE entry point to the program
print chr$("Hey, this actually works.",13,10)
exit
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
end start ; Tell MASM where the program ends
;可以用Quick Editor(masm32安装目录中qeditor.exe)来构建这个程序
;必需先File->Set Current Directory(或直接Ctrl+F12)设置为hello.asm所在目录
;然后Project->Console Assenble and Link就可以构建了
;这是一个工作在控制台下的程序,打开一个cmd窗口,切换到生成的hello.exe所在目录
;运行之后显示:Hey, this actually works.
;print是一个宏,在maxros.asm中定义如下,这个文件已经被包含进来了
;include \masm32\macros\macros.asm ; MASM support macros
print MACRO arg1:REQ,varname:VARARG ;; 显示一个0结束的字符串
invoke StdOut,reparg(arg1)
IFNB <varname>
invoke StdOut,chr$(varname)
ENDIF
ENDM
;调用StdOut函数,在控制台显示一个字符串
;repareg是一个宏,在maxros.asm中定义如下,这个文件已经被包含进来了
; -----------------------------------------------------------
; This macro replaces quoted text with a DATA section OFFSET
; and returns it in ADDR "name" format. It is used by other
; macros that handle optional quoted text as a parameter.
; -----------------------------------------------------------
reparg MACRO arg
LOCAL nustr
quot SUBSTR <arg>,1,1
IFIDN quot,<"> ;; if 1st char = "
.data
nustr db arg,0 ;; write arg to .DATA section
.code
EXITM <ADDR nustr> ;; append name to ADDR operator
ELSE
EXITM <arg> ;; else return arg
ENDIF
ENDM
;如果arg是一个字符串地址,直接返回这个地址,
;如果arg是一个"字符串",在.data中声明并返回
;这个偏移地址
;chr$是一个宏,在macros.asm中定义如下
chr$ MACRO any_text:VARARG
LOCAL txtname
.data
txtname db any_text,0
.code
EXITM <OFFSET txtname>
ENDM
;chr$("Hey, this actually works.",13,10)
;经编译器处理后变为
;.data
;txtname db Hey, this actually works.",13,10,0
;.code
;并返回textname的偏移给print继续展开
;invoke StdOut,addr textname
;exit是一个宏,在macros.asm中定义如下
; --------------------------------------------------------
; exit macro with an optional return value for ExitProcess
; --------------------------------------------------------
exit MACRO optional_return_value
IFNDEF optional_return_value
invoke ExitProcess, 0
ELSE
invoke ExitProcess,optional_return_value
ENDIF
ENDM
;exit直接展开为
;invoke ExitProcess, 0
;关于宏的详细参考D:\masm32\help\masm32.hlp中的MACRO Reference
;也可以参考也可以参考masm程序员指南.
;StdOut是一个自定义的库函数,源码在\masm32\m32lib\stdout.asm
;这是对操作系统中有关控制台操作的封装。
; #########################################################################
.386
.model flat, stdcall
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
StrLen PROTO :DWORD
.code
; #########################################################################
StdOut proc lpszText:DWORD
LOCAL hOutPut :DWORD
LOCAL bWritten :DWORD
LOCAL sl :DWORD
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hOutPut, eax
invoke StrLen,lpszText
mov sl, eax
invoke WriteFile,hOutPut,lpszText,sl,ADDR bWritten,NULL
mov eax, bWritten
ret
StdOut endp
; #########################################################################
end
;源码中还用到了一个自定义的库函数StrLen源码在\masm32\m32lib\strlen.asm
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.486
.model flat, stdcall
option casemap :none ; case sensitive
.code
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
align 4
StrLen proc item:DWORD
; -------------------------------------------------------------
; This procedure has been adapted from an algorithm written by
; Agner Fog. It has the unusual characteristic of reading up to
; three bytes past the end of the buffer as it uses DWORD size
; reads. It is measurably faster than a classic byte scanner on
; large linear reads and has its place where linear read speeds
; are important.
; -------------------------------------------------------------
mov eax,[esp+4] ; get pointer to string
push ebx
lea edx,[eax+3] ; pointer+3 used in the end
@@:
mov ebx,[eax] ; read first 4 bytes
add eax, 4 ; increment pointer
lea ecx,[ebx-01010101h] ; subtract 1 from each byte
not ebx ; invert all bytes
and ecx,ebx ; and these two
and ecx, 80808080h
jz @B ; no zero bytes, continue loop
test ecx,00008080h ; test first two bytes
jnz @F
shr ecx,16 ; not in the first 2 bytes
add eax,2
@@:
shl cl,1 ; use carry flag to avoid branch
sbb eax,edx ; compute length
pop ebx
ret 4
StrLen endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
end
;GetStdHandle和WriteFile是操作系统kernel32.dll提供的函数这可查MSDN
;或者在MSHELP中找到相关C语言描述。
;最后这个程序被编译器编译成什么样子呢?
;用OllyDBG打开看一下
00401005 >/$ >jmp start
0040100A | >int3
0040100B | >int3
0040100C | >int3
0040100D | >int3
0040100E | >int3
0040100F | >int3
00401010 >|> >push offset ??0019 ; print chr$("Hey, this actually works.",13,10)
00401015 |. >call StdOut
0040101A |. >push 0 ; exit
0040101C \. >call ExitProcess
;下面是Stdout
00401028 >/$ >push ebp
00401029 |. >mov ebp, esp
0040102B |. >add esp, -0C
0040102E |. >push -0B ; /DevType = STD_OUTPUT_HANDLE
00401030 |. >call GetStdHandle ; \GetStdHandle
00401035 |. >mov [ebp-4], eax
00401038 |. >push dword ptr [ebp+8]
0040103B |. >call StrLen
00401040 |. >mov [ebp-C], eax
00401043 |. >push 0 ; /pOverlapped = NULL
00401045 |. >lea eax, [ebp-8] ; |
00401048 |. >push eax ; |pBytesWritten
00401049 |. >push dword ptr [ebp-C] ; |nBytesToWrite
0040104C |. >push dword ptr [ebp+8] ; |Buffer
0040104F |. >push dword ptr [ebp-4] ; |hFile
00401052 |. >call WriteFile ; \WriteFile
00401057 |. >mov eax, [ebp-8]
0040105A |. >leave
0040105B \. >retn 4
;下面是StrLen
00401060 >/$ >mov eax, [esp+4]
00401064 |. >push ebx
00401065 |. >lea edx, [eax+3]
00401068 |> >/mov ebx, [eax]
0040106A |. >|add eax, 4
0040106D |. >|lea ecx, [ebx+FEFEFEFF]
00401073 |. >|not ebx
00401075 |. >|and ecx, ebx
00401077 |. >|and ecx, 80808080
0040107D |.^>\je short 00401068
0040107F |. >test ecx, 8080
00401085 |. >jnz short 0040108D
00401087 |. >shr ecx, 10
0040108A |. >add eax, 2
0040108D |> >shl cl, 1
0040108F |. >sbb eax, edx
00401091 |. >pop ebx
00401092 \. >retn 4
;宏减少了击键次数,在一定程度上提高了可读性
;对于工具的使用应该更多关注官方发布的手册 |
|