首页
社区
课程
招聘
[讨论]关于在控制台程序中WriteFile的两种调用格式引起的问题
发表于: 2005-12-10 11:12 5480

[讨论]关于在控制台程序中WriteFile的两种调用格式引起的问题

HSQ 活跃值
8
2005-12-10 11:12
5480
一般情况下要想控制台程序具有输出到文件或管道,就不能再用WriteConsole,必须用WriteFile。但我在用WriteFile时,用两种调用格式书写,却出现了两种结果:
1.在命令行下可以用">"有输出到文件;
2.在命令行下用">"有输出到文件,虽然成功,但也弹出内存不能为"Written"的错误提示
    源文件:
.386
      .model flat,stdcall
option casemap:none

include windows.inc
include kernel32.inc
includelib kernel32.lib

.data
msg DB "Hello, world."
written DD ?
hStdOut DD ?

.CODE
start:
        push        STD_OUTPUT_HANDLE
        call        GetStdHandle
        mov        hStdOut, eax

        push        0
        push        written
        push        LENGTHOF msg
        push        OFFSET msg
        push        hStdOut
        call        WriteFile        
;这种书写格式用">"有输出到文件,虽然成功,但也弹出内存不能为"Written"

        invoke  WriteFile,hStdOut,offset msg,LENGTHOF msg,written,0                       
;这种书写格式用">"有输出到文件,一切正常

        push        hStdOut
        call        CloseHandle

        push        0
        call        ExitProcess

END start
   随后,我用OD将其反编译如下:
00401010     6A F5            push -0B                              ;DevType=STD_OUTPUT_HANDLE
00401012     E8 6B000000      call <jmp.&kernel32.GetStdHandle>     ;GetStdHandle
00401017     A3 11404000      mov dword ptr ds:[404011],eax

0040101C     6A 00            push 0                                ;pOverlapped = NULL
0040101E     FF35 0D404000    push dword ptr ds:[40400D]            ;pBytesWritten = NULL
00401024     6A 0D            push 0D
00401026     68 00404000      push pp.00404000                      ;ASCII "Hello, world."
0040102B     FF35 11404000    push dword ptr ds:[404011]
00401031     E8 52000000      call <jmp.&kernel32.WriteFile>

00401036     6A 00            push 0                                ;pOverlapped = NULL
00401038     FF35 0D404000    push dword ptr ds:[40400D]            ;pBytesWritten = NULL
0040103E     6A 0D            push 0D
00401040     68 00404000      push pp.00404000                      ;ASCII "Hello, world."
00401045     FF35 11404000    push dword ptr ds:[404011]
0040104B     E8 38000000      call <jmp.&kernel32.WriteFile>

00401050     FF35 11404000    push dword ptr ds:[404011]
00401056     E8 1B000000      call <jmp.&kernel32.CloseHandle>
0040105B     6A 00            push 0
0040105D     E8 1A000000      call <jmp.&kernel32.ExitProcess>
00401062     CC               int3
... ....
00401075     CC               int3
00401076     FF25 70504000    jmp dword ptr ds:[<&kernel32.CloseHandle>]  ;kernel32.CloseHandle
0040107C     FF25 64504000    jmp dword ptr ds:[<&kernel32.ExitProcess>]  ;kernel32.ExitProcess
00401082     FF25 68504000    jmp dword ptr ds:[<&kernel32.GetStdHandle>] ;kernel32.GetStdHandle
00401088     FF25 6C504000    jmp dword ptr ds:[<&kernel32.WriteFile>]    ;kernel32.WriteFile

表明两种调用格式书写,实质上是完全一样的,为什么用前者出错,而后者却正常????

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 291
活跃值: (213)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
2
WriteFile的第四个参数是指针,而你却写成了普通的变量
应当把push  written
改为
push OFFSET written
2005-12-10 14:02
0
雪    币: 381
活跃值: (140)
能力值: ( LV13,RANK:330 )
在线值:
发帖
回帖
粉丝
3
改动后一切正常,可是标号不也是一个地址指针吗?
2005-12-10 14:46
0
雪    币: 291
活跃值: (213)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
4
汇编里的标号相当于C/C++里的标识符,回想一下在C/C++里,所有的标识符都是地址指针吗?
MASM的标号分为数据标号(如a dd 5 中的a.和代码标号(如函数名以及程序中的地址标号等),对于程序中引用的数据标号,MASM默认转换为标号所在地址的内容,如
a dd 5
mov eax,a
会在eax中装入5,和
mov eax,[a]
的作用相同
另外,
mov eax,a+1
等价于
mov eax,[a+1]
而对于程序中的代码标号,MASM则默认将其转换为地址

_Test:
mov eax,_Test
会将_Test的地址传给eax
注意mov eax,[_Test]和
mov eax,_Test作用相同
实际上,所有的标号确实是地址,但是编译器在处理标号时针对不同类型的标号作了不同的处理
2005-12-11 00:02
0
雪    币: 381
活跃值: (140)
能力值: ( LV13,RANK:330 )
在线值:
发帖
回帖
粉丝
5
谢谢thebutterfly,收获不浅啊
2005-12-12 22:27
0
游客
登录 | 注册 方可回帖
返回
//