注册 登录
编程论坛 汇编论坛

随心的Win32汇编作业本

随心 发布于 2008-09-09 02:38, 8602 次点击
第一个程序
程序代码:

;告诉编译器要使用80386的指令集
.386

;告诉编译器程序的模式,win32模式下只能使用flat模式,stdcall告诉编译器参数的传递模式
;参数的传递方式有三种,stdcall, c, pascal
;stdcall: 从右到左压入堆栈,
.model flat, stdcall

option casemap :none ; case sensitive 是否对大小写敏感

;调用API函数所必须的头文件
include        windows.inc
include        user32.inc
includelib    user32.lib
include        kernel32.inc
includelib    kernel32.lib

;.data 或 .data?

;指明了接下来是数据段,.data 定义了预定义的变量,
;.data?定义了未初始化的变量,
;两者的不同之处是 .data? 定义的变量并不占用 .exe 文件的大小,
;而是在程序执行时动态分配,
;所以开始是不指定初始值的数据可以放在 .data? 段中,
;如一个1K大小的缓冲区,放在 .data?中,程序将不会增加一个字节。
.data

szCaption db 'Win32汇编例子',0
szText db '我要学习Win32汇编!!',0


;.code
;指明了接下来是代码段,我们的所有代码都放在这里。
;最后的一句 start 语句指定了程序开始执行的语句。
;程序中的 ExitProcess 是一个标准的 Win32 API,
;对应 Dos汇编中的 int 20h 或 mov ah,4ch/int 21h,也就是程序退出。
;而 MessageBox 也是一个标准的 API,功能是在屏幕上显示一个消息框,
;还有要注意的是 invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK 语句中,
; MB_OK 和 NULL 已经预定义在 Windows.inc 中。
.code

start:
invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK
invoke ExitProcess,NULL

end start


[[it] 本帖最后由 随心 于 2008-9-19 03:55 编辑 [/it]]
37 回复
#2
ONEPROBLEM2008-09-09 07:27
同学评语:太认真了。请版主给他打满分。
#3
谁与争疯2008-09-09 20:14
校长评语:请该同学的班主任给予该同学跳级
#4
随心2008-09-10 00:53
第二个程序:Hello World!
程序代码:

DATAS  SEGMENT
     STRING  DB  'Hello Wowrld!',13,10,'$'    ;原来13 10是回车换行...
DATAS  ENDS

CODES  SEGMENT
     ASSUME    CS:CODES,DS:DATAS
START:
     MOV  AX,DATAS
     MOV  DS,AX
     LEA  DX,STRING
     MOV  AH,9
     INT  21H
   
     MOV  AH,4CH
     INT  21H
CODES  ENDS
    END   START

#5
随心2008-09-10 00:54
决定还是从DOS汇编学起
#6
随心2008-09-10 01:06
四楼的代码我注释了下,不知道有没有错
程序代码:

;数据段
DATAS  SEGMENT
     STRING  DB  'Hello Wowrld!',13,10,'$';定义一个字符串,13,10是回车换行的意思,字符串以'$'结尾
DATAS  ENDS

;代码段
CODES  SEGMENT
     ASSUME    CS:CODES,DS:DATAS    ;指定各段使用的寄存器
START:    ;程序开始
     MOV  AX,DATAS    ;开始数据段寻址
     MOV  DS,AX        ;mov指令不能直接将数据段地址直接写入DS,只能通过寄存器来写入
     
     
     LEA  DX,STRING    ;得到字符串变量地址
     MOV  AH,9
     INT  21H        ;调用21H中断的9号功能,用来显示字符串,好比C语言的puts();
   
     MOV  AH,4CH
     INT  21H        ;调用21H的4C功能,返回操作系统(DOS)
CODES  ENDS            ;;代码段结束
    END   START        ;;;指明程序的入口地址,相当于C里的main();    
#7
随心2008-09-10 01:45
第三个程序:两个数相加(3+5), -,-两个数相加要这么麻烦
程序代码:

;定义数据段
DATAS  SEGMENT
    FIVE  DB    5    ;定义一个字节型变量 BYTE FIVE = 5;
DATAS  ENDS

;定义堆栈段
STACKS  SEGMENT
      DB  128 DUP (?)    ;BYTE s[128];
STACKS  ENDS

;代码段开始
CODES  SEGMENT
     ASSUME    CS:CODES, DS:DATAS, SS:STACKS    ;指定各段使用的寄存器
START:

    MOV AX,DATAS
    MOV DS,AX        ;数据段寻址
   
    MOV AL,FIVE        ;int a = FIVE;
    ADD AL,3        ; a += 3;
    ADD AL,30H        ;30H:0的ASCLL值,??? 这里应该是类型转换吧?????/
   
    ;;开始显示
    ;2号调用:在显示器上显示输出单个字符,
    ;调用格式:mov dl, 要显示字符的ASCLL码值
    MOV DL,AL
    MOV AH,2
    INT 21H
   
    MOV AH,4CH
    INT 21H
CODES  ENDS
    END  START

#8
随心2008-09-10 01:55
第四个程序:
哇...原来Hello World也可以这样写
程序代码:

INCLUDE MACROOUT.LIB    ;调用汇编宏库
DATAS SEGMENT
    STRING  DB 'Hello World',13,10,'$'
DATAS ENDS
CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS
START:
    MOV AX,DATAS
    MOV DS,AX        ;数据段寻址
   
    OUTPUT STRING    ;调用OUTPUT宏来输出字符串
    MOV AH,4CH
    INT 21H
CODES ENDS

    END START

#9
随心2008-09-10 01:57
不过看起来那个宏只做了下面工作:
     LEA  DX,STRING
     MOV  AH,9
     INT  21H
一行换三行,值,不过要加include 语句
#10
liyanhong2008-09-10 07:32
#11
高阁逆风2008-09-10 09:15
#12
随心2008-09-10 23:03
第五个程序:从1加到100
这个程序是我在网上找的,然后自己做注释进行分析,看了一半看不下去了
先发上来,有时间继续看.
程序代码:

;***********   
  data segment   
  result dw ?   
  data ends   
  ;***********   
  code segment   
  assume cs:code,ds:data  
   
start:   
  push ds       ;
  sub ax,ax   
  push ax   
   
  mov ax,data     ;数据段寻址  
  mov ds,ax   
   
  mov cx,100      ;CX自动计数
  sub   ax,ax      ;清空AX,
lop:   
  inc ax   
  add bx,ax   
  loop lop       ;累加
   
  mov result,bx   ;保存结果
   
  mov ch,4
   
aa:   
  mov cl,4   
  rol bx,cl       ;取bx高4位
  
  mov al,bl       ;从这以后就看不明白了??????
  and al,0fh   
  add al,30h   
  cmp al,3ah   
  jl printit   
  add al,7h   
  
printit:  
  mov dl,result   
  mov ah,2   
  int 21h   
  dec ch   
  jnz aa   
   
  retf   
  code ends   
  ;***********   
  end start
#13
随心2008-09-10 23:07
一点感想:
汇编做一点点事都很麻烦,就像那个从1加到100的程序,如果用C很容易实现.
但我觉得汇编应该比C快.同样的C程序如果反汇编一下,应该要比汇编代码长得多吧.有时间试试.
我觉得汇编不是难的,不过重要的是把一些指令理解透彻了.
其实汇编很有意思
#14
你们都要疼我哦2008-09-11 00:01
汇编指令不是重点,不懂就查手册.
流程的理解和功能的分解是关键.

16位汇编我一点不会,不过从功能和流程上来蒙, aa那段属于printit输出部分,
dec ch   
jnz aa  
蒙得aa的作用大概是进行输出的转换.

继续蒙
add al,30h   
cmp al,3ah   
30H是啊四可码  表示0
39H是啊四可码  表示9  因为下面是jl,所以啊四可码加1,是3ah
上面2句是判断al中值是不是在0-9之间.

16位的一点不懂,只能蒙这些了. 蒙错了别扔砖头啊
#15
谁与争疯2008-09-11 00:15
30H是啊四可码  表示0
39H是啊四可码  表示9

啊四可码...

蒙,继续蒙。

新残中残脑残片 一片顶六片 没有最残 只有更残 你残 我残 大家残 大家残 才是真的残 残 残 残 残到姥姥家

我拿钢板砸你!!!
#16
随心2008-09-11 00:42
回复 14# 你们都要疼我哦 的帖子
14楼辛苦了,经过你的一阵子猛,我明白了
下面是我的注释,不知道还有没有错的地方
对了,这两句话很好,我记下了.
程序代码:

;***********   
  data segment   
  result dw ?   
  data ends   
  ;***********   
  code segment   
  assume cs:code,ds:data  
   
start:   
  push ds       ;
  sub ax,ax   
  push ax   
   
  mov ax,data     ;数据段寻址  
  mov ds,ax   
   
  mov cx,100      ;CX自动计数
  sub   ax,ax      ;清空AX,
lop:   
  inc ax   
  add bx,ax   
  loop lop       ;累加
   
  mov result,bx   ;保存结果
   
  mov ch,4
   
aa:   
  mov cl,4   
  rol bx,cl       ;取bx高4位
  
  mov al,bl       ;
  and al,0fh       ;
  add al,30h       ; 转化成ASCLL码
  cmp al,3ah       ; 是否小于'9'
  jl printit       ; 如果是,打印出来
  add al,7h       ; 加7就变成A B C D E F等值
  
printit:  
  mov dl,result   ; 把结果放入dl
  mov ah,2         ; 调用2号中断输出字符
  int 21h   
  dec ch             ; ch--
  jnz aa             ; 累加器不为0,则跳到aa继续执行
   
  retf             ; 退出
  code ends   
  ;***********   
  end start
#17
随心2008-09-11 00:43
论坛有问题,那两句话竟然没出来.在这里补上:

汇编指令不是重点,不懂就查手册.
流程的理解和功能的分解是关键.
#18
随心2008-09-11 01:20
学习汇编两天了:
有一点点感想,和一块学习的人分享
① 兴趣最重要
② 不要被汇编这个名词吓倒,其实不难,无非就是几个指令的组合
③ 不要局限于书本,多找代码看,找自己感兴趣的代码看
④ 多写,多问,多查,多总结

还有引用14楼的一句话(点睛之笔):
汇编指令不是重点,不懂就查手册.
流程的理解和功能的分解是关键.
#19
liyanhong2008-09-11 07:41
[bo][un]随心[/un] 在 2008-9-11 01:20 的发言:[/bo]

有一点点感想,和一块学习的人分享
① 兴趣最重要
② 不要被汇编这个名词吓倒,其实不难,无非就是几个指令的组合
③ 不要局限于书本,多找代码看,找自己感兴趣的代码看
④ 多写,多问,多查,多总结

还有引用14楼的 ...

学习了   也正在学汇编
#20
ONEPROBLEM2008-09-11 08:06
汇编论坛人气开始旺了~~~
#21
zklhp2008-09-18 16:26
[bo][un]ONEPROBLEM[/un] 在 2008-9-11 08:06 的发言:[/bo]

汇编论坛人气开始旺了~~~


ONEPROBLEM功不可没

呵呵 过两天 等汇编通讯十二期出来 转一个偶写的程序 就是不算bccn原创了
#22
ONEPROBLEM2008-09-18 16:47
[bo][un]zklhp[/un] 在 2008-9-18 16:26 的发言:[/bo]



ONEPROBLEM功不可没

呵呵 过两天 等汇编通讯十二期出来 转一个偶写的程序 就是不算bccn原创了

到时一定拜读~~~
#23
随心2008-09-18 17:05
第六个程序:好几天没写了,熟练一下
程序代码:

.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib

.data
MsgBoxCaption  db "我的Win32汇编",0
MsgBoxText     db "Win32 Assembly is Great!",0

.code
start:
invoke MessageBox, NULL, addr MsgBoxText, addr MsgBoxCaption, MB_OK
invoke ExitProcess, NULL
end start

#24
ONEPROBLEM2008-09-18 17:09
[bo][un]随心[/un] 在 2008-9-18 17:05 的发言:[/bo]


.386
.model flat,stdcall
option casemap:none
include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib

.data
MsgBoxCaption  db "我 ...

太幽默了你,这是练发贴的吧?
#25
随心2008-09-18 17:11
addr操作符与offset操作符的区别:
addr操作符把标号的地址传递给被调用的函数,只能用在invoke语句中
offset可以把标号地址赋给变量或寄存器
===========
addr不可以处理向前引用,offset则能。所谓向前引用是指:标号的定义是在invoke 语句之后,譬如在如下的例子:
invoke MessageBox,NULL, addr MsgBoxText,addr MsgBoxCaption,MB_OK

......

MsgBoxCaption db "我的Win32汇编",0
MsgBoxText db "Win32 Assembly is Great!",0
=========
addr可以处理局部变量而 offset 则不能。局部变量只是在运行时在堆栈中分配内存空间。而 offset 则是在编译时由编译器解释,这显然不能用offset 在运行时来分配内存空间。编译器对 addr 的处理是先检查处理的是全局还是局部变量,若是全局变量则把其地址放到目标文件中,这一点和 offset 相同,若是局部变量,就在执行 invoke 语句前产生如下指令序列:
lea eax, LocalVar
push eax
因为lea指令能够在运行时决定标号的有效地址,所以有了上述指令序列,就可以保证 invoke 的正确执行了。
#26
随心2008-09-18 17:13
回复 24# ONEPROBLEM 的帖子
在小问题中学习,顺便练习一下发贴
#27
随心2008-09-18 17:29
第七个程序:第一个窗口程序
程序代码:

.386 ;使用80386指令集
.model flat,stdcall    
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib

;WinMain函数声明
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

;======================数据段
.data
ClassName db "SimpleWinClass",0
AppName  db "我的汇编窗口",0

.data?
hInstance HINSTANCE ?    ;应用程序句柄
CommandLine LPSTR ?        ;保存命令行传入的参数
;==========================

;==========================代码段开始
.code
start:
    invoke GetModuleHandle, NULL    ;得到应用程序句柄
    mov    hInstance,eax
    
    invoke GetCommandLine            ;得到命令行参数
    mov    CommandLine,eax
    
    ;调用主函数
    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
    ;退出程序
    invoke ExitProcess,eax

;===================主过程=======================
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    ;注册窗口样式
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_WINDOW+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    ;创建窗口
    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
    mov   hwnd,eax
    ;显示窗口
    invoke ShowWindow, hwnd,SW_SHOWNORMAL
    invoke UpdateWindow, hwnd
    ;进入消息循环
    .WHILE TRUE
        invoke GetMessage, ADDR msg,NULL,0,0
        .BREAK .IF (!eax)
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
    .ENDW
    mov     eax,msg.wParam
    ret
WinMain endp

;回调函数
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    .IF uMsg==WM_DESTROY ;关闭消息
        invoke PostQuitMessage,NULL
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam    ;调用系统默认的函数进行处理    
        ret
    .ENDIF
    xor eax,eax
    ret
WndProc endp
end start

#28
随心2008-09-19 03:29
第八个程序:在窗口上输出文字
文字是输出了,只不过狂闪不已,汗一下...
在汇编中,我不会用rc文件
程序代码:

.386 ;使用80386指令集
.model flat,stdcall    
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
include gdi32.inc
includelib gdi32.lib

;WinMain函数声明
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

;======================数据段
.data
ClassName db "SimpleWinClass",0
AppName  db "我的汇编窗口",0
MyString db "我的第二个窗口程序",0

.data?
hInstance HINSTANCE ?    ;应用程序句柄
CommandLine LPSTR ?        ;保存命令行传入的参数
hdc HDC ?
;==========================

;==========================代码段开始
.code
start:
    invoke GetModuleHandle, NULL    ;得到应用程序句柄
    mov    hInstance,eax
    
    invoke GetCommandLine            ;得到命令行参数
    mov    CommandLine,eax
    
    ;调用主函数
    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
    ;退出程序
    invoke ExitProcess,eax

;===================主过程=======================
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    ;注册窗口样式
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_WINDOW+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    ;创建窗口
    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_SYSMENU or WS_MINIMIZEBOX,CW_USEDEFAULT,\
           CW_USEDEFAULT,200,200,NULL,NULL,\
           hInst,NULL
    mov   hwnd,eax
    ;显示窗口
    invoke ShowWindow, hwnd,SW_SHOWNORMAL
    invoke UpdateWindow, hwnd
    invoke GetDC, hwnd
    mov hdc, eax
    ;进入消息循环
    .WHILE TRUE
        invoke GetMessage, ADDR msg,NULL,0,0
        .BREAK .IF (!eax)
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
    .ENDW
    mov     eax,msg.wParam
    ret
WinMain endp

;回调函数
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    .IF uMsg==WM_DESTROY ;关闭消息
        invoke PostQuitMessage,NULL
    .ELSEIF uMsg==WM_PAINT
        invoke TextOut, hdc, 0, 0, addr MyString, SIZEOF MyString
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam    ;调用系统默认的函数进行处理    
        ret
    .ENDIF
    xor eax,eax
    ret
WndProc endp
end start
#29
随心2008-09-19 03:54
第八个程序第二版:解决不闪的问题
解决办法都在注释里了
程序代码:

.386 ;使用80386指令集
.model flat,stdcall   
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
include gdi32.inc
includelib gdi32.lib

;WinMain函数声明
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

;======================数据段
.data
ClassName db "SimpleWinClass",0
AppName  db "我的汇编窗口",0
MyString db "我的第二个窗口程序",0

.data?
hInstance HINSTANCE ?    ;应用程序句柄
CommandLine LPSTR ?        ;保存命令行传入的参数
;hdc HDC ?
;==========================

;==========================代码段开始
.code
start:
    invoke GetModuleHandle, NULL    ;得到应用程序句柄
    mov    hInstance,eax
   
    invoke GetCommandLine            ;得到命令行参数
    mov    CommandLine,eax
   
    ;调用主函数
    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
    ;退出程序
    invoke ExitProcess,eax

;===================主过程=======================
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    ;注册窗口样式
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_WINDOW+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    ;创建窗口
    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_SYSMENU or WS_MINIMIZEBOX,CW_USEDEFAULT,\
           CW_USEDEFAULT,200,200,NULL,NULL,\
           hInst,NULL
    mov   hwnd,eax
    ;显示窗口
    invoke ShowWindow, hwnd,SW_SHOWNORMAL
    invoke UpdateWindow, hwnd
   
    ;狂闪的原因:在这里得到了DC
   ; invoke GetDC, hwnd
    ;mov hdc, eax
    ;进入消息循环
    .WHILE TRUE
        invoke GetMessage, ADDR msg,NULL,0,0
        .BREAK .IF (!eax)
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
    .ENDW
    mov     eax,msg.wParam
    ret
WinMain endp

;回调函数
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
      LOCAL hdc:HDC
    LOCAL ps:PAINTSTRUCT
    .IF uMsg==WM_DESTROY ;关闭消息
        invoke PostQuitMessage,NULL
    .ELSEIF uMsg==WM_PAINT
        invoke BeginPaint,hWnd, addr ps ;在这里得到DC就不闪了
        mov    hdc,eax
        invoke TextOut, hdc, 0, 0, addr MyString, SIZEOF MyString
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam    ;调用系统默认的函数进行处理   
        ret
    .ENDIF
    xor eax,eax
    ret
WndProc endp
end start
#30
随心2008-09-19 04:07
第九个程序:得到当前系统日期
程序代码:

.386 ;使用80386指令集
.model flat,stdcall   
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
include gdi32.inc
includelib gdi32.lib

;WinMain函数声明
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

;======================数据段
.data
ClassName db "SimpleWinClass",0
AppName  db "我的汇编窗口",0
MyString db "我的第二个窗口程序",0
Date_Format   db   "yyyy年MM月dd日",0     ;日期格式_1  

.data?
hInstance HINSTANCE ?    ;应用程序句柄
CommandLine LPSTR ?        ;保存命令行传入的参数
;hdc HDC ?
;==========================

;==========================代码段开始
.code
start:
    invoke GetModuleHandle, NULL    ;得到应用程序句柄
    mov    hInstance,eax
   
    invoke GetCommandLine            ;得到命令行参数
    mov    CommandLine,eax
   
    ;调用主函数
    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
    ;退出程序
    invoke ExitProcess,eax

;===================主过程=======================
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    ;注册窗口样式
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_WINDOW+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    ;创建窗口
    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_SYSMENU or WS_MINIMIZEBOX,CW_USEDEFAULT,\
           CW_USEDEFAULT,200,200,NULL,NULL,\
           hInst,NULL
    mov   hwnd,eax
    ;显示窗口
    invoke ShowWindow, hwnd,SW_SHOWNORMAL
    invoke UpdateWindow, hwnd
   
    ;狂闪的原因:在这里得到了DC
   ; invoke GetDC, hwnd
    ;mov hdc, eax
    ;进入消息循环
    .WHILE TRUE
        invoke GetMessage, ADDR msg,NULL,0,0
        .BREAK .IF (!eax)
        invoke TranslateMessage, ADDR msg
        invoke DispatchMessage, ADDR msg
    .ENDW
    mov     eax,msg.wParam
    ret
WinMain endp

;回调函数
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
      LOCAL hdc:HDC
    LOCAL ps:PAINTSTRUCT
    local   TimeStruct:SYSTEMTIME         ;时间结构   
    local   ShowDateStr[128]:byte         ;显示日期缓冲区
   
    .IF uMsg==WM_DESTROY ;关闭消息
        invoke PostQuitMessage,NULL
    .ELSEIF uMsg==WM_PAINT
        invoke BeginPaint,hWnd, addr ps ;在这里得到DC就不闪了
        mov    hdc,eax

          invoke   GetSystemTime,addr   TimeStruct   

         invoke   GetDateFormat,NULL,0,addr TimeStruct, addr Date_Format, addr ShowDateStr,sizeof ShowDateStr      
        invoke TextOut, hdc, 40, 50, addr ShowDateStr, 14
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam    ;调用系统默认的函数进行处理   
        ret
    .ENDIF
    xor eax,eax
    ret
WndProc endp
end start
#31
随心2008-09-19 04:15
终于温习了一下汇编,估计又得好几天没时间学习了
#32
ONEPROBLEM2008-09-19 07:11
[bo][un]随心[/un] 在 2008-9-19 04:15 的发言:[/bo]


把一些漂亮的代码打印成纸张,带在身上,有空就看一下,想一下,就可以天天学汇编了~~
#33
duduchang2008-09-20 12:55
知音
我们也刚学了汇编,可到现在还不知怎么上机运行!
这学期还开了c++!忙啊!
#34
arsionbc2008-09-21 20:18
多看看罗云彬的书,随心的程序不太合编程规范,比如GetDC函数没有相应的release函数,二是响应WM_PAINT消息一般是用BeginPaint和EndPaint函数的相应使用,这两个函数只对无效区刷新,否则很容易闪烁.
#35
随心2008-09-30 22:18
回复 34# arsionbc 的帖子
先谢谢楼上的.
又好几天没来论坛了.由工作上的原因,汇编的学习停了一段时间.我本身是做C/C++的,加上手上的项目还没完.估计一时是看不成了.不过我会尽量抽时间来看看的.
我是刚开始学习的汇编,从0开始学习的,希望和大家一块进步.
还有就是大家有问题就提上来,发帖子,我们一块解决,这样大家都可以学到东西了.
ONEPROBLEM版主以及好多人都是高手,以后要多向你们请教学习.
谢谢zklhp版主以及大家对我的支持,我会努力去做的.

[[it] 本帖最后由 随心 于 2008-9-30 22:29 编辑 [/it]]
#36
你们都要疼我哦2008-10-01 21:18
  我开始学C++
#37
cooge2008-11-02 16:30
HI  大家好~我也开始学汇编啦~
#38
oliverypf2009-07-17 16:54
很认真呢,适合初学者看看
1