飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2754|回复: 2

源码阅读之hello.asm

[复制链接]

该用户从未签到

发表于 2006-9-29 13:51:08 | 显示全部楼层 |阅读模式
;以下为\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

;宏减少了击键次数,在一定程度上提高了可读性
;对于工具的使用应该更多关注官方发布的手册
PYG19周年生日快乐!

该用户从未签到

发表于 2007-1-26 20:47:21 | 显示全部楼层
支持一下,楼主应该讲解的再详细点
PYG19周年生日快乐!

该用户从未签到

发表于 2007-1-26 22:46:55 | 显示全部楼层
支持一下。。。。。
PYG19周年生日快乐!
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表