`
yiyeqinghuasoon
  • 浏览: 639032 次
文章分类
社区版块
存档分类
最新评论

菜鸟学反汇编10—call

 
阅读更多

#include<iostream>

#include<iostream>

using namespace std;

using namespace std;

void swap(int i,int j)

void myswap(int &i,int &j)

{

{

int a=i;

int a=i;

i=j;

i=j;

j=a;

j=a;

}

}

int main()

int main()

{

{

int i=0,j=1;

int i=0,j=1;

swap(i,j);

myswap(i,j);

cout<<i<<" "<<j;

cout<<i<<" "<<j;

system("pause");

system("pause");

return 0;

return 0;

}

}

var_8= dword ptr -8

var_8= dword ptr -8

var_4= dword ptr -4

var_4= dword ptr -4

argc= dword ptr 8

argc= dword ptr 8

argv= dword ptr 0Ch

argv= dword ptr 0Ch

envp= dword ptr 10h

envp= dword ptr 10h

push ebp

push ebp

mov ebp, esp

mov ebp, esp

sub esp, 8

sub esp, 8

mov [ebp+var_4], 0

mov [ebp+var_4], 0

mov [ebp+var_8], 1

mov [ebp+var_8], 1

mov eax, [ebp+var_8]

lea eax, [ebp+var_8]

push eax

push eax

mov ecx, [ebp+var_4]

lea ecx, [ebp+var_4]

push ecx

push ecx

call sub_401000

call sub_401000

add esp, 8

add esp, 8

mov edx, [ebp+var_8]

mov edx, [ebp+var_8]

前面都是一样的

push edx

push edx

push offset asc_41C1D8 ; " "

push offset asc_41C1D8 ; " "

mov eax, [ebp+var_4]

mov eax, [ebp+var_4]

push eax

push eax

mov ecx, offset unk_422858

mov ecx, offset unk_422858

call sub_401080

call sub_401090

push eax ; int

push eax ; int

call sub_402410

call sub_402420

add esp, 8

add esp, 8

mov ecx, eax

mov ecx, eax

call sub_401080

call sub_401090

push offset aPause ; "pause"

push offset aPause ; "pause"

call unknown_libname_33 ; Microsoft VisualC 2-8/net runtime

call unknown_libname_33 ; Microsoft VisualC 2-8/net runtime

add esp, 4

add esp, 4

xor eax, eax

xor eax, eax

mov esp, ebp

mov esp, ebp

pop ebp

pop ebp

retn

retn

sub_401000 proc near

sub_401000 proc near

var_4= dword ptr -4

var_4= dword ptr -4

arg_0= dword ptr 8

arg_0= dword ptr 8

arg_4= dword ptr 0Ch

arg_4= dword ptr 0Ch

push ebp

push ebp

mov ebp, esp

mov ebp, esp

push ecx

push ecx

mov eax, [ebp+arg_0]

mov eax, [ebp+arg_0]

这儿就是值传递和引用传递的区别

mov [ebp+var_4], eax

mov ecx, [eax]

mov [ebp+var_4], ecx

mov ecx, [ebp+arg_4]

mov edx, [ebp+arg_0]

mov [ebp+arg_0], ecx

mov eax, [ebp+arg_4]

mov ecx, [eax]

mov [edx], ecx

mov edx, [ebp+var_4]

mov edx, [ebp+arg_4]

mov [ebp+arg_4], edx

mov eax, [ebp+var_4]

mov [edx], eax

mov esp, ebp

mov esp, ebp

pop ebp

pop ebp

retn

retn

sub_401000 endp

sub_401000 endp

#include<iostream>

#include<iostream>

using namespace std;

using namespace std;

int add(int i)

inline int add(int i)

{

{

return (i+1);

return (i+1);

}

}

int main()

int main()

{

{

int i=0;

int i=0;

i=add(i);

i=add(i);

cout<<i;

cout<<i;

system("pause");

system("pause");

return 0;

return 0;

}

}

var_4= dword ptr -4

var_4= dword ptr -4

argc= dword ptr 8

argc= dword ptr 8

argv= dword ptr 0Ch

argv= dword ptr 0Ch

envp= dword ptr 10h

envp= dword ptr 10h

最奇怪的应该是这儿,就是在调用内联函数时没有发生插入,而只是直接调用。我猜可能是出于使用这个函数的次数太少的原因,以致插入的代价要远远大于调用的代价。我就设计了另外一个程序,其中有双层for循环调用了10000*10000次内联函数,很奇怪的是仍然是直接调用而不是插入。我只能猜测在for循环连续调用一个函数时,系统作了优化,使得插入的效率没有直接调用高。于是我就只能猜测在每次调用内联函数程序处于不同的环境下,才直接插入,否则就直接调用。

push ebp

push ebp

mov ebp, esp

mov ebp, esp

push ecx

push ecx

mov [ebp+var_4], 0

mov [ebp+var_4], 0

mov eax, [ebp+var_4]

mov eax, [ebp+var_4]

push eax

push eax

call sub_401000

call sub_401040

add esp, 4

add esp, 4

mov [ebp+var_4], eax

mov [ebp+var_4], eax

mov ecx, [ebp+var_4]

mov ecx, [ebp+var_4]

push ecx

push ecx

mov ecx, offset unk_422858

mov ecx, offset unk_422858

call sub_401050

call sub_401050

push offset aPause ; "pause"

push offset aPause ; "pause"

call unknown_libname_33 ; Microsoft VisualC 2-8/net runtime

call unknown_libname_33 ; Microsoft VisualC 2-8/net runtime

add esp, 4

add esp, 4

xor eax, eax

xor eax, eax

mov esp, ebp

mov esp, ebp

pop ebp

pop ebp

retn

retn

sub_401000 proc near

sub_401040 proc near

arg_0= dword ptr 8

arg_0= dword ptr 8

push ebp

push ebp

mov ebp, esp

mov ebp, esp

mov eax, [ebp+arg_0]

mov eax, [ebp+arg_0]

add eax, 1

add eax, 1

pop ebp

pop ebp

retn

retn

sub_401000 endp

sub_401040 endp

反思:

内联函数这块海需要好好考证。

下步:

作文件的读取等操作。

在网上搜索到一篇callret有关的文章,转来看看

1)段内直接调用

指令格式: CALL 过程名

能: SPSP-2[SP+1][SP]IPIPIP+displ6

操作说明: 被调用过程是一个近过程,在本代码段内。CALL指令将IP(返回地址)压入堆栈,然后将CALL的下一条指令与被调用过程入口地址之间的16位相对位移量displ6加到IP上,使控制转到被调用的过程。

2)段内间接调用

指令格式: CALL 字地址指针

能: SPSP-2[SP+1][SP] IPIPEA

操作说明: 指令中的操作数是一个16位的寄存器或字存储单元,其中的内容是一个近过程的入口地址。CALL指令将返回地址IP压入堆栈,然后将寄存器或字存储单元的内容作为有效地址装入IP

3)段间直接调用

指令格式: CALL FAR PTR过程名

能: SPSP-2[SP+1][SP] CSCSSEG FAR-PROC

SPSP-2[SP+1][IP] IPIPOFFSET FAR-PROC

操作说明: 被调用过程是一个远过程,该过程不在现行代码段内。段间直接调用指令首先将CS(断点的段基址)压入堆栈,并将远过程所在的段基址SEG FARPROCCS;再将IP(断点的偏移地址)压入堆栈,然后将远过程的偏移地址OFFSETFAR-PROCIP

4)段间间接调用

指令格式: CALL 双字地址指针

能: SPSP-2[SP+1][SP] CSCS[EA+2]

SPSP-2[SP+1][SP] IPIP[EA]

操作说明: 指令操作数是一个32位的双字存储单元,指令将CS寄存器的内容压入堆栈,并将操作数指向的存储器的后两个字节送CS;再将IP寄存器的内容压入堆栈,然后将存储器的前两个字节送IP

【例2.53 CALL SUB-PROCA ;段内直接调用

CALL AX ;段内间接调用

CALL WORD PTR[BX] ;段内间接调用

CALL FAR PTR SUB-PROCX ;段间直接调用

CALL DWORD PTR[BP][SI] ;段间间接调用

2)过程返回指令

子过程执行最后一条指令必须是返回指令,返回到调用该子程序断点处。

1)返回指令

指令格式: RET

能: 从近过程返回时:IP[SP+1][SP]SPSP+2

从远过程返回时:IP[SP+1][SP]SPSP+2

CS[SP+1][SP]SPSP+2

2)带弹出值的返回指令

指令格式: RET POP_VALUE

能: 先执行与RET相同的操作,再修改SP SPSP+POP_VALUE

操作说明: 弹出值应为一个16位立即数,通常是偶数。弹出值表示返回时从堆栈中舍弃的字节数。例如:RET 4,返回时舍弃堆栈中的4个字节。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics