首页
社区
课程
招聘
[讨论]这是如何编译来的?(已解决)
发表于: 2008-8-10 17:27 6724

[讨论]这是如何编译来的?(已解决)

2008-8-10 17:27
6724
一个小过程,用于检测字符串是否为空,dwOffset为字符串首地址
IsEmpty proc dwOffset:DWORD
    xor ecx,ecx
    cmp byte ptr [dwOffset],0
    je @f
    inc ecx
    @@:
    ret
IsEmpty endp

编译之后没达到预期效果,因为编译出来的代码有问题
如下
0040101A  /$  55            push    ebp
0040101B  |.  8BEC          mov     ebp, esp
0040101D  |.  33C9          xor     ecx, ecx
0040101F  |.  807D 08 00    cmp     byte ptr [ebp+8], 0
00401023  |.  74 01         je      short 00401026
00401025  |.  41            inc     ecx
00401026  |>  C9            leave
00401027  \.  C2 0400       retn    4

在此程序中
[ebp+8] = dwOffset
因此[dwOffset] = [[ebp+8]]
但编译出来的代码明显把[dwOffset]=[ebp+8]了

对这个过程做一下改进
IsEmpty proc dwOffset:DWORD
    xor ecx,ecx
    mov eax,dwOffset
    mov al,[eax]
    cmp al,0
    je @f
    inc ecx
    @@:
    ret
IsEmpty endp

效果达到了
再来看看编译出的代码
0040101A  /$  55            push    ebp
0040101B  |.  8BEC          mov     ebp, esp
0040101D  |.  33C9          xor     ecx, ecx
0040101F  |.  8B45 08       mov     eax, dword ptr [ebp+8]
00401022  |?  8A00          mov     al, byte ptr [eax]
00401024  |?  3C 00         cmp     al, 0
00401026  |>  74 01         je      short 00401029
00401028   ?  41            inc     ecx
00401029   ?  C9            leave
0040102A   $  C2 0400       retn    4

第一次编译器为什么会把[dwOffset]编译为[ebp+8]呢?

编译工具为MASM32 Version 9.00 Release

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

收藏
免费 0
支持
分享
最新回复 (15)
雪    币: 215
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
dwoffset被看做一个标号了,[dwoffset]就看做取这个标号的地址而非
取标号指向的地址
2008-8-10 18:59
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
3

完全不明白你在说什么,也许是因为你完全不明白我在说什么
2008-8-10 19:49
0
雪    币: 399
活跃值: (38)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
老外给出的答案

Intel x86-based processors are only capable of accessing memory one step (indirection) at a time.
2008-8-10 20:34
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
5
有炶类似这个 mov eax, [12345678h]

不会报错, 结果出来是 mov        eax, 12345678h

你的例子应该本来就该这么写吧
    mov eax,dwOffset
    mov al,[eax]

原先的 cmp byte ptr [dwOffset],0
不会报错, 但是会让人误解
不要加 [] 比较好
2008-8-10 20:36
0
雪    币: 7309
活跃值: (3788)
能力值: (RANK:1130 )
在线值:
发帖
回帖
粉丝
6
不懂ASM,换C吧
2008-8-11 00:07
0
雪    币: 249
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
mov eax,[dwNum] - mov eax,dwNum
mov eax,dwNum - mov eax, offset dwNum
2008-8-11 00:10
0
雪    币: 63
活跃值: (17)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
8
总算看明白了
2008-8-11 00:12
0
雪    币: 107
活跃值: (1683)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
9
楼主不时去老外那学新技术 佩服!
2008-8-11 01:35
0
雪    币: 2559
活跃值: (176)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
在此程序中
[ebp+8] = dwOffset
因此[dwOffset] = [[ebp+8]]
但编译出来的代码明显把[dwOffset]=[ebp+8]了
     不对吧,应该是 ebp+8 = dwOffset,你的dwOffset是形参,不是你原来的那个字符窜的首地址了!!!
2008-8-11 10:30
0
雪    币: 101
活跃值: (12)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
11
dwOffset是个符号, 编译的程序没任何问题,
很奇怪你有问题..

cmp byte ptr [dwOffset],0

cmp byte ptr dwOffset,0

在MS的编译器里面是一样的效果, 因为他是符号..
2008-8-11 10:42
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
12
这是符号吗?
mov eax, [401000h]
2008-8-11 10:46
0
雪    币: 101
活跃值: (12)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
13
dwOffset不管加不加括号都是取值, 因为他是符号
4010000不管加不加括号都是他本身的值, 因为他的常数

为了阅读的人存在误区, 所以建议
cmp byte ptr [dwOffset],0 和
mov eax, 401000h 这样的版本
2008-8-11 10:51
0
雪    币: 335
活跃值: (140)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
好好再回去看看寻址方式吧。
2008-8-11 11:23
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
15

欲将常数当指标, 需指定一个区段, 所以应写成:
        mov        eax, ds:[40100h]
就会真的是
        0040389F >    A1 00010400   mov     eax, [40100]

平常写惯了不加段,
若省略段记号, 常数会被直接使用, 而不是当成一个指标, 如下:
        mov        eax, [40100h]
变成
        0040389F >    B8 00010400   mov     eax, 40100
2008-8-11 11:46
0
雪    币: 2067
活跃值: (82)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
16
看的应该是MASM手册
2008-8-11 11:59
0
游客
登录 | 注册 方可回帖
返回
//