【免费】全新海外营销策论分享
CSDN社区4月技术大分享活动火爆开始
专访黄钊吉:SQL Server现已经向云过渡
公告:CSDN新版首页上线 欢迎关注CSDN产品客服微博 CSDN论坛 第4期专家问答——基于openstac的可扩展云平台开发
公告:CSDN新版首页上线 欢迎关注CSDN产品客服微博 CSDN论坛 第4期专家问答——基于openstac的可扩展云平台开发
一:问题
call dword ptr xxx与call xxx
前者为什么比后者就效率了?还有一个问题
#include <iostream>
using namespace std;
int main()
{
cout<<"hello world!"<<endl;
__asm jmp main
return 0;
}
这个函数为啥不是死循环?怎么执行一会就结束?
如果加个计数器
#include <iostream>
using namespace std;
int a;
void Cout()
{
a++;
cout<<"hello world!"<<endl;
__asm jmp main
return 0;
}
int main()
{
__asm jmp Cout
return 0;
}
#include <iostream>
using namespace std;
int a;
void Cout()
{
a++;
cout<<"hello world!"<<endl;
__asm call main
return 0;
}
int main()
{
__asm call Cout
return 0;
}
第一个程序的a的值要大一些,也就是说jmp是效率的?输入表的调用为什么还要用call ?
上面这几个问题是看加密解密3 P278 关于输入表函数调用部分的思考,想不明白,请前辈高人帮忙!
二:解答:
fenchang说的是对的
//使用默认栈的大小0x100000 提交0x1000(一个页面)
#include "head.h"
int a;
int main()
{
a++;
cout<<"hello world!"<<" "<<a<<endl;
__asm jmp main
return 0;
}
a=12308
//增大默认的大小为0x200000提交0x1000
//1.exe
#include "head.h"
#pragma comment(linker,"/stack:0x200000,0x1000")
int a;
int main()
{
a++;
cout<<"hello world!"<<" "<<a<<endl;
__asm jmp main
return 0;
}
a=24791
1:结论:是预订地址的空间不够导致了程序的退出,继续增大,程序将继续运行,而并不是抢占式多任务操作系统的任务调试会强制夺回CPU控制权
2:原因:进程空间会发生空间预订的现象——PEB TEB 和线程栈空间分配!
3:区别死循环
//2.exe
#include "head.h"
int a;
int main(int argc,char **argv)
{
while(1)
{
a++;
cout<<"hello world!"<<" "<<a<<endl;
}
return 0;
}
与前面例子的区别:
//1.exe 反汇编
00401005 /E9 06000000 jmp 1.00401010 ;__asm jmp main的位置
0040100A |CC int3
0040100B |CC int3
0040100C |CC int3
0040100D |CC int3
0040100E |CC int3
0040100F |CC int3
00401010 \55 push ebp ;保存栈帧底
00401011 8BEC mov ebp,esp ;开辟新栈帧
00401013 83EC 44 sub esp,44 ;保存变量
00401016 53 push ebx
00401017 56 push esi
00401018 57 push edi
00401019 8D7D BC lea edi,dword ptr ss:[ebp-44]
0040101C B9 11000000 mov ecx,11
00401021 B8 CCCCCCCC mov eax,CCCCCCCC ;实始化操作
00401026 F3:AB rep stos dword ptr es:[edi]
………………………………………………省略N句……………………………………………………………………
004010A0 ^ E9 60FFFFFF jmp 1.00401005 ;__asm jmp main
………………………………………………………………………………………………………………………………
;这里是收复栈空间
004010A5 33C0 xor eax,eax
004010A7 5F pop edi
004010A8 5E pop esi
004010A9 5B pop ebx
004010AA 83C4 44 add esp,44
显然,程序在不停的支出栈空间,而并没有回收,使用call指令一样进行这样的操作!
//2.exe 反汇编
00401010 55 push ebp
00401011 8BEC mov ebp,esp
00401013 83EC 44 sub esp,44
00401016 53 push ebx
00401017 56 push esi
00401018 57 push edi
00401019 8D7D BC lea edi,dword ptr ss:[ebp-44]
0040101C B9 11000000 mov ecx,11
00401021 B8 CCCCCCCC mov eax,CCCCCCCC
00401026 F3:AB rep stos dword ptr es:[edi]
……………………………………………………上面分配栈空间………………………………………………………………
00401028 B8 01000000 mov eax,1
0040102D 85C0 test eax,eax
0040102F 74 7F je short 2.004010B0 ;whie(1)条件检测位置
00401031 8B0D 34464100 mov ecx,dword ptr ds:[414634]
00401037 83C1 01 add ecx,1 ;计数器增加
0040103A 890D 34464100 mov dword ptr ds:[414634],ecx
………………………………………………省略N句,这里省略的部分没有栈操作…………………………………………………………
004010AB ^ E9 78FFFFFF jmp 2.00401028 ;循环继续
……………………………………………………回收栈空间…………………………………………………………………………
004010B0 33C0 xor eax,eax
004010B2 5F pop edi
004010B3 5E pop esi
004010B4 5B pop ebx
004010B5 83C4 44 add esp,44
显然,循环中没有支出任何栈空间!
4:call dword ptr [xxxx],与call xxxx
这两者的区别就在于一点IAT——IAT在OD中就是一段jmp xxxx,call动态链接库的DLL文件时我们根本不再需要先jmp一下,再jmp到函数当中!这个过程的实现如下
_declspec在编写DLL文件的导出函数时被程序员加上了,编译器的汇编阶断会将它转换成call dword ptr [xxxx],并加上一个__im__的标志,生成obj文件教给链接器处理的时候,链接器看到__im__就会直接修改为__im__xxxx!
5:jmp比call效率为什么要用call而不用jmp
A:如果使用jmp我们要自已回收栈空间,这样是浪费程序员的时候,因为程序中很大部分的功能都需要调用函数,所以这个功能被提取出来以方便操作——call!
B:C/C++也用这种方式,是因为它存在的基础是汇编语言,就像遗传!
call dword ptr xxx与call xxx
前者为什么比后者就效率了?还有一个问题
#include <iostream>
using namespace std;
int main()
{
cout<<"hello world!"<<endl;
__asm jmp main
return 0;
}
这个函数为啥不是死循环?怎么执行一会就结束?
如果加个计数器
#include <iostream>
using namespace std;
int a;
void Cout()
{
a++;
cout<<"hello world!"<<endl;
__asm jmp main
return 0;
}
int main()
{
__asm jmp Cout
return 0;
}
#include <iostream>
using namespace std;
int a;
void Cout()
{
a++;
cout<<"hello world!"<<endl;
__asm call main
return 0;
}
int main()
{
__asm call Cout
return 0;
}
第一个程序的a的值要大一些,也就是说jmp是效率的?输入表的调用为什么还要用call ?
上面这几个问题是看加密解密3 P278 关于输入表函数调用部分的思考,想不明白,请前辈高人帮忙!
二:解答:
fenchang说的是对的
//使用默认栈的大小0x100000 提交0x1000(一个页面)
#include "head.h"
int a;
int main()
{
a++;
cout<<"hello world!"<<" "<<a<<endl;
__asm jmp main
return 0;
}
a=12308
//增大默认的大小为0x200000提交0x1000
//1.exe
#include "head.h"
#pragma comment(linker,"/stack:0x200000,0x1000")
int a;
int main()
{
a++;
cout<<"hello world!"<<" "<<a<<endl;
__asm jmp main
return 0;
}
a=24791
1:结论:是预订地址的空间不够导致了程序的退出,继续增大,程序将继续运行,而并不是抢占式多任务操作系统的任务调试会强制夺回CPU控制权
2:原因:进程空间会发生空间预订的现象——PEB TEB 和线程栈空间分配!
3:区别死循环
//2.exe
#include "head.h"
int a;
int main(int argc,char **argv)
{
while(1)
{
a++;
cout<<"hello world!"<<" "<<a<<endl;
}
return 0;
}
与前面例子的区别:
//1.exe 反汇编
00401005 /E9 06000000 jmp 1.00401010 ;__asm jmp main的位置
0040100A |CC int3
0040100B |CC int3
0040100C |CC int3
0040100D |CC int3
0040100E |CC int3
0040100F |CC int3
00401010 \55 push ebp ;保存栈帧底
00401011 8BEC mov ebp,esp ;开辟新栈帧
00401013 83EC 44 sub esp,44 ;保存变量
00401016 53 push ebx
00401017 56 push esi
00401018 57 push edi
00401019 8D7D BC lea edi,dword ptr ss:[ebp-44]
0040101C B9 11000000 mov ecx,11
00401021 B8 CCCCCCCC mov eax,CCCCCCCC ;实始化操作
00401026 F3:AB rep stos dword ptr es:[edi]
………………………………………………省略N句……………………………………………………………………
004010A0 ^ E9 60FFFFFF jmp 1.00401005 ;__asm jmp main
………………………………………………………………………………………………………………………………
;这里是收复栈空间
004010A5 33C0 xor eax,eax
004010A7 5F pop edi
004010A8 5E pop esi
004010A9 5B pop ebx
004010AA 83C4 44 add esp,44
显然,程序在不停的支出栈空间,而并没有回收,使用call指令一样进行这样的操作!
//2.exe 反汇编
00401010 55 push ebp
00401011 8BEC mov ebp,esp
00401013 83EC 44 sub esp,44
00401016 53 push ebx
00401017 56 push esi
00401018 57 push edi
00401019 8D7D BC lea edi,dword ptr ss:[ebp-44]
0040101C B9 11000000 mov ecx,11
00401021 B8 CCCCCCCC mov eax,CCCCCCCC
00401026 F3:AB rep stos dword ptr es:[edi]
……………………………………………………上面分配栈空间………………………………………………………………
00401028 B8 01000000 mov eax,1
0040102D 85C0 test eax,eax
0040102F 74 7F je short 2.004010B0 ;whie(1)条件检测位置
00401031 8B0D 34464100 mov ecx,dword ptr ds:[414634]
00401037 83C1 01 add ecx,1 ;计数器增加
0040103A 890D 34464100 mov dword ptr ds:[414634],ecx
………………………………………………省略N句,这里省略的部分没有栈操作…………………………………………………………
004010AB ^ E9 78FFFFFF jmp 2.00401028 ;循环继续
……………………………………………………回收栈空间…………………………………………………………………………
004010B0 33C0 xor eax,eax
004010B2 5F pop edi
004010B3 5E pop esi
004010B4 5B pop ebx
004010B5 83C4 44 add esp,44
显然,循环中没有支出任何栈空间!
4:call dword ptr [xxxx],与call xxxx
这两者的区别就在于一点IAT——IAT在OD中就是一段jmp xxxx,call动态链接库的DLL文件时我们根本不再需要先jmp一下,再jmp到函数当中!这个过程的实现如下
_declspec在编写DLL文件的导出函数时被程序员加上了,编译器的汇编阶断会将它转换成call dword ptr [xxxx],并加上一个__im__的标志,生成obj文件教给链接器处理的时候,链接器看到__im__就会直接修改为__im__xxxx!
5:jmp比call效率为什么要用call而不用jmp
A:如果使用jmp我们要自已回收栈空间,这样是浪费程序员的时候,因为程序中很大部分的功能都需要调用函数,所以这个功能被提取出来以方便操作——call!
B:C/C++也用这种方式,是因为它存在的基础是汇编语言,就像遗传!