首页
社区
课程
招聘
[旧帖] [求助]关于直接寻址方式疑惑![已解决] 0.00雪花
发表于: 2012-8-3 20:43 1453

[旧帖] [求助]关于直接寻址方式疑惑![已解决] 0.00雪花

2012-8-3 20:43
1453
这几天在用汇编二次开发notepad,遇到一个直接寻址方式的疑惑,百思不得其解,如果哪位了解,请告之一下怎么回事,万分谢谢!

问题是这样的:
从教科书中可以得知:mov eax, [10000000h]
如果不考虑段,简单理解就是把地址10000000h处4个字节的内容赋值给eax
接下来我在ollydbg中直接汇编“mov eax, [10000000h]”,显示汇编后的代码就是“MOV EAX, DWORD PTR DS:[10000000]”,这符合我的认知;

但是我在VS中内嵌这么一句汇编码的时候,再用Ollydbg打开查看,发现编译后的代码却是“mov eax, 10000000h”,很古怪,接下来直接写win32汇编测试用例,并用ML.exe直接编译,不过最终效果也是“mov eax, 10000000h”,这简直有点颠覆我的世界观呀;

同时“push [10000000h]”会被ML.exe直接编译成“push 10000000h”
而"mov [10000000h], eax"或"mov DWORD PTR[10000000h], eax"则直接编译报错

这些指令我原先的理解应该都寻址10000000h地址指向的4字节数据,并且不会报错;但是目前我看到只有Ollydbg的汇编功能跟我理解的一样,为什么其他内嵌VC或ML.exe编译后的结果都如此诡异???

-----------------------------------------------------------------------------------------------------------------------------

非常感谢“jianghe”及“天命小三”的回答,你们解开了我心中的疑惑和一个错误的认知(太可怕了),非常感谢!


在此我想把原先一直存在的错误认知的起因经过以及现在的新认知再列举总结下,各位看看是否还有错误;

错误认知最早的起源于沈美明汇编教材第三章讲述直接寻址方式时,有这么几句:


在汇编语言指令中,可以用符号地址代替数值地址,如:
mov ax, VALUE
此时VALUE为存放操作数单元的符号地址。如写成:
mov ax, [VALUE]
也是可以的,二者是等效的。


data1 dd ?        ;定义一个DWORD数据
Func1 proc        ;定义一个函数
label1:        ;定义一个函数内标号
Func1 endp
上述表示中我认为data1,Func1,label1都是符号地址;

但是不知怎么搞的把“VALUE为存放操作数单元的符号地址”中的“存放操作数单元”在进入大脑后给自动过滤了,
导致在我脑海中一直有这么一个错误的认知,就是只要是符号地址,那么[VALUE]==VALUE;

因为平时还真没用过mov eax, [0x10000000]写法这种方式,所以这个错误认知一直被遗留下来;
直到最近二次开发Notepad的时候,发现call [0x10000000]或call NEAR DWORD DS:[0x10000000]在VC以及ML.exe中始终编译不过去;

上网google后,在百度知道中发现这么一个说法:call [0x10000000] 跟 call DWORD PTR [0x10000000]的效果不一样,具体见下面地址:
http://zhidao.baidu.com/question/439046121.html(现在我想他的回答应该是错误的)

在自己平时写win32汇编时,用的都是call Func1这种形式,这时看到百度知道的说法后当时就突然想到了[value]==value
然后测试如问题中描述的mov eax, [0x10000000]等写法形式,发现跟我认知的都出了问题;
因为编译后结果不是把0x10000000处存放的数据赋值给eax,而是直接把0x10000000赋值给eax,导致歧路越走越远,悲催!

现在经几位大哥指点,我想这个疑惑我明白了,同时下面仔做了一些测试验证;

以下是再次测试的结果,编译命令如下:
ML.EXE /c /coff /Cp /Fl /Fm /nologo /I"D:\RadASM\Masm32\Include" "twin1.asm"

原始测试代码:
        mov eax, [10000000h]
        push [10000000h]
        mov eax, ds:[10000000h]
        push ds:[10000000h]
        mov ds:[10000000h], eax
label1:
        call DWORD PTR ds:[10000000h]
        call label1
        mov eax, offset label1
        mov eax, offset _WinMain
        mov eax, offset hInstance
        mov eax, label1
        mov eax, _WinMain
        mov eax, hInstance
        mov eax, ds:[10000000h]
        lea eax, label1
        lea eax, _WinMain
        lea eax, hInstance
        lea eax, ds:[10000000h]

编译后在Ollydbg中反编译的代码:
0040132B B8 00000010              MOV     EAX, 10000000
00401330 68 00000010              PUSH    10000000
00401335 A1 00000010              MOV     EAX, DWORD PTR DS:[10000000]
0040133A FF35 00000010            PUSH    DWORD PTR DS:[10000000]
00401340 A3 00000010              MOV     DWORD PTR DS:[10000000], EAX
00401345 FF15 00000010            CALL    NEAR DWORD PTR DS:[10000000]
0040134B E8 F5FFFFFF              CALL    twin1.00401345
00401350 B8 45134000              MOV     EAX, twin1.00401345
00401355 B8 F6114000              MOV     EAX, twin1.004011F6
0040135A B8 00304000              MOV     EAX, twin1.00403000
0040135F B8 45134000              MOV     EAX, twin1.00401345
00401364 B8 F6114000              MOV     EAX, twin1.004011F6
00401369 A1 00304000              MOV     EAX, DWORD PTR DS:[403000]
0040136E A1 00000010              MOV     EAX, DWORD PTR DS:[10000000]
00401373 8D05 45134000            LEA     EAX, DWORD PTR DS:[401345]
00401379 8D05 F6114000            LEA     EAX, DWORD PTR DS:[4011F6]
0040137F 8D05 00304000            LEA     EAX, DWORD PTR DS:[403000]
00401385 8D05 00000010            LEA     EAX, DWORD PTR DS:[10000000]

从中我得出的结论是:
只有变量的符号地址才会使[value]==value这种等效发生,操作结果是符号地址所指向的数据,
其他的符号地址,在call|push|mov时,操作结果都是符号地址本身,并非其指向的数据;

但是对于lea指令而言,所有符号地址,对应的操作结果都是符号地址本身,即赋值给eax的值是符号地址;
call [0x10000000] 及 call NEAR DWORD PTR [0x10000000]效果是一致的,只不过写时需要加上段前缀;

补充:在网上搜到一篇关于“在masm中,直接寻址需要加段,否则会被当成立即数寻址”的文章,
http://jpkc.zzu.edu.cn/hbyycai/courses/slist.asp?id=385

[课程]Android-CTF解题方法汇总!

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 107
活跃值: (73)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
2
没有人帮忙解惑下嘛,或者大家的测试结果跟我表述不一致吗?
2012-8-3 22:02
0
雪    币: 54
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
我试了一下,跟你说的结果是一样的。但是除了直接寻址以外,寄存器间接寻址或相对寻址都是正确的。但是以前没注意过这种情况,不过我用asm编辑过,不会出现跟VC中的一样。具体原因待查,我再找找
2012-8-4 09:56
0
雪    币: 54
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
哥们,我找到原因了,你只要将mov eax, [10000000h]改为mov eax, dword ptr ds:[00401245],或者mov eax, ds:[00401245]就可以。原因是因为没有加段前缀ds:的话,编译器会默认为这是个立即数,不会当做地址进行处理的....
2012-8-4 10:14
0
雪    币: 2993
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
这个是由于编译器和反汇编器的版本不同造成的。
在masm中,直接寻址需要加段,否则会被当成立即数寻址,这个建议参看一下x86汇编的入门书籍。
在一般的反汇编器中(如debug)输入那条指令则不会变为立即数寻址。

所以只要加上段址ds:就可以了
2012-8-4 10:46
0
游客
登录 | 注册 方可回帖
返回
//