首页
社区
课程
招聘
[求助]shl edx, 4 为什么是 左移了一位而不是4位。等 3个汇编问题
发表于: 2008-10-7 23:20 11387

[求助]shl edx, 4 为什么是 左移了一位而不是4位。等 3个汇编问题

2008-10-7 23:20
11387
( 1 ) 第二题中,有许多 shl edx,4 操作,跟踪发现 edx 中的值只左移了一位。为什么呢?
按 intel文档中的说法:
    Shifts the destination left by "count" bits with zeroes shifted in on right.
      左移 count 位目标数,右边填充0。

我理解 count是几就移动几位,有什么不对?

( 2 ) lea的第二个操作数必须是个地址值吗?
如下语句:
lea     eax, dword ptr [ebp+edx-100]

可不可以有如下形式的语句?
lea   eax, ecx

lea 可不可以理解为c语言中的“取地址”操作?

( 3 ) 在 od中,调用系统函数的汇编代码形式如下:
FF15 00203D00 call    dword ptr [<&KERNEL32.GetProcessHeap>
但是,当我想像这样修改某行代码,以调用系统函数时,照着这种格式写却提示语法错误。而必须写为 call    dword ptr [3D2000] 的形式。请问怎样能以函数名的方法来写?

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

收藏
免费 0
支持
分享
最新回复 (16)
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
2
我想是楼主对位的理解差异吧

例如0x01<<4之后应该是0x10
你把这个数值转为二进制数就好理解了
0x01=00000001
0x10=00010000
正好是4位
这个位移是用于定位数组中的指定单元的位置
2008-10-7 23:30
0
雪    币: 419
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
edx== 2的4次方吧
2008-10-7 23:30
0
雪    币: 440
活跃值: (61)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4


是左移4位啊....没有错...
左移4位等于乘2^4(16).........

比如edx=2,shl edx,4后 edx=2*16=32(hex(32)=20)

也就是楼主看到的1位......

混淆了吧....十六进制和二进制了..........
2008-10-7 23:33
0
雪    币: 666
活跃值: (201)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
5
噢 ,哈哈,二楼正解。谢谢!
继续等待后面两个问题的答案。
2008-10-7 23:34
0
雪    币: 503
活跃值: (80)
能力值: (RANK:280 )
在线值:
发帖
回帖
粉丝
6
第二个问题 lea ecx, ecx这条指令不存在
8D /r LEA r32,m Store effective address for m in register r32
第二个字节是ModR/M,所以可以有lea ecx, [ecx]

第三个问题
FF15表示Call+绝对地址
FF /2 CALL r/m32 Call near, absolute indirect, address given in r/m32

你要在其他地方修改代码只需要先输入FF 15并且把接下来的4个字节改成需要调用的函数的地址就好了
2008-10-7 23:42
0
雪    币: 666
活跃值: (201)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
7
楼上,不太明白。
第二个字节是ModR/M,所以可以有lea ecx, [ecx]
这意味着什么? 什么情况下会用到你说的这种情况?
我举个例子: ecx中是一个 数字,比如  0x03。
那 lea ecx, [ecx] 会发生什么?

第三个问题:

你描述的是怎样直接修改代码,必须知道函数的地址。那如果只知道函数名呢?在od的修改代码的功能中,能不能写入形如 call    dword ptr [<&KERNEL32.GetProcessHeap>] 这样的代码,然后  od将其编译为 FF1500404544 这样的机器码?
2008-10-7 23:54
0
雪    币: 222
活跃值: (488)
能力值: ( LV11,RANK:188 )
在线值:
发帖
回帖
粉丝
8
1.第一个问题注意是bits

2.lea eax,[eax];会经常看到的

[reg/mem]可错位的理解为*
lea reg,reg/mem/[reg/mem]可错位理解为&???

也可这样理解
[]运算符操作后返回值为一个地址
lea第二个操作符为一个指针
而其他的指令操作符绝多数为即时数

3.试试call dword ptr [kernel32.GetProcessHeap]
2008-10-8 00:07
0
雪    币: 111
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
[QUOTE=kusky;518361]
我举个例子: ecx中是一个 数字,比如  0x03。
那 lea ecx, [ecx] 会发生什么?

[/QUOTE]

会发生 eax = 0x03
lea Reg, [exp]   ===> reg = exp
如,lea eax , [ eax * 4 + ecx  * 3 + 1]
则, eax = eax * 4 + ecx * 3 + 1
呵呵,是不省了些事?
2008-10-8 00:07
0
雪    币: 82
活跃值: (10)
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
10
lea reg32, [exp]
计算的时候不会影响到EFLAGS,另外简化了表达式计算
2008-10-8 01:14
0
雪    币: 666
活跃值: (201)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
11
原来大家都有早起的习惯~~~~
( 1 ) lea 怎样简化了操作呢?我看 mov也可以解决问题啊。
如,mov eax , [ eax * 4 + ecx  * 3 + 1]
则, eax = eax * 4 + ecx * 3 + 1

不也是一样吗?
( 2  )
[ecx] 和  ecx 有什么不同?
按 intel的说法:
LEA - Load Effective Address
        Transfers offset address of "src" to the destination register.
所以  lea  eax , [ebp -100]  我能理解,这里 "[]"相当于c中的“&”
但    lea eax, [ecx]    为什么是取了ecx的内容呢?我理解应该是取ecx的地址,因为ecx没有地址,所以不能这样用。但试了却可以。
2008-10-8 07:39
0
雪    币: 245
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
如,mov eax , [ eax * 4 + ecx  * 3 + 1]
则, eax = eax * 4 + ecx * 3 + 1

你在搞笑吗? 上面的相等吗?

所以  lea  eax , [ebp -100]  我能理解,这里 "[]"相当于c中的“&”
但    lea eax, [ecx]    为什么是取了ecx的内容呢?我理解应该是取ecx的地址,因为ecx没有地址,所以不能这样用。但试了却可以。

上面的相当于 eax=ebp-100
另外一个就是 eax=ecx 了

强烈建议此帖发到新手区,太弱智的问题了
2008-10-8 07:51
0
雪    币: 221
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
[QUOTE=kusky;518414]原来大家都有早起的习惯~~~~
( 1 ) lea 怎样简化了操作呢?我看 mov也可以解决问题啊。
如,mov eax , [ eax * 4 + ecx  * 3 + 1]
则, eax = eax * 4 + ecx * 3 + 1

不也是一样吗?
( 2  )
[ecx...[/QUOTE]

mov eax , [ eax * 4 + ecx  * 3 + 1]
则, eax = eax * 4 + ecx * 3 + 1
这显然是错的

lea eax, ecx是非法的
2008-10-8 08:46
0
雪    币: 141
活跃值: (1135)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
14
如果从纯数字意义上看shl edx,4相当于edx=edx*16
但这里是对32int类型的指针操作,也就是汇编语言中1个DWORD类型的指针操作。
sizeof(int32) = sizeof(DWORD) = 4*sizeof(BYTE)。

C语言的(32位的intlong int):
   int *i;
    i += 4;

对应于汇编语言的(假设edx指向*i):
shl edx, 4  ; edx=edx*16

因为汇编语言指令的基本单位是字节(BYTE)。

这样理解是否正确?
2008-10-8 08:48
0
雪    币: 101
活跃值: (12)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
15
简单来说
shl edx,4 就是edx=edx*16, 是值的语义
你那里不是 i+=4; 因为你的i是一个指针, +=4的是个下标, 应该是
i = i + 4   --->  
不是
{
  mov eax, i
  shl eax, 4
  mov i, eax
}
而是
{
  mov eax, i
  mov edx, 1
  shl edx, 4
  lea eax, [eax+edx]
  mov i, eax
}

int pi[3][4];
想要读pi[2][3];
可以
pi[2][3]
也可以
pi+2*4+3;
还可以
(int *) ( (char *)pi + 2*4*4 + 3*4 );

汇编地址都是char*的所以代码是下面这样
mov edx, 2;
shl edx, 4        // sizeof(int)*4 == 16, edx<<4 等价 edx = edx*16;
mov ecx, 3;
lea eax, [pi+edx+ecx*4];   eax = pi + 2*16 + 3*4;
mov eax, [eax]
2008-10-8 09:14
0
雪    币: 141
活跃值: (1135)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
16
在Windows系统中大量的系统函数都是放在系统的动态连接库里,即以.dll为扩展名的文件中,如kernel32.dll、user32.dll、shell32.dll等等。

在汇编语言中要想用函数名的方式调用某个函数,一般要用LoadLibrary、GetProceAddress及FreeLibrary这三个Win32SDK函数。
以WinExec为例说明如下:

这4个函数都是kernel32.dll中的库函数,其调用信息分别为:

HINSTANCE LoadLibrary(
    LPCTSTR lpLibFileName        // 动态连接库文件名地址
   );

FARPROC GetProcAddress(
    HMODULE hModule,        // 动态连接库句柄  
    LPCSTR lpProcName        // 库函数名指针
   );       

BOOL FreeLibrary(
    HMODULE hLibModule        // 一调入内存的动态连接库句柄  
   );       

UINT WinExec(

    LPCSTR lpCmdLine,        // 应用程序命令行地址
    UINT uCmdShow                // 启动应用程序的窗口显示式样
   );       

汇编代码(不考虑任何异常情况):

DllLib  db 'kernel32.dll',0
LoadLib db 'LoadLibrary',0
GetAddr db 'GetProcAddress',0
FreeLib db 'FreeLibrary',0
ExecCmd db 'WinExec',0
Notepad db 'Notepad.exe',0

mov eax, offset DllLib
push eax
call LoadLibraryA                        ; load kernel32.dll

mov ecx, eax                                ; save hModule
mov edx, offset ExecCmd     
push edx                                        ; lpProcName
push eax                                        ; hModule
call GetProcAddress                ; get address of WinExec

mov edx, 1                                ; nCmdShow=1
push edx
mov edx, offset Notepad
push edx                                        ; lpCmdLine
call eax                                        ; call WinExec
mov eax, ecx                                ; get hModule
push eax
call FreeLibrary                        ; free kernel32.dll
2008-10-8 09:55
0
雪    币: 666
活跃值: (201)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
17
感谢诸位的热心回复。特别是 mstwugui ,jjnet,解决了我的问题。感谢 mavermaver 给我补充的知识~~
好像增加威望的功能不能用了?不知道如何感谢各位了~~~
2008-10-8 19:54
0
游客
登录 | 注册 方可回帖
返回
//