有关信息ACM/ICPC竞争环境GCC/G++叠插件研究记录的扩展
0、起因
有时。DFS总是比BFS受人喜爱——毕竟DFS简单粗暴,更,而有些东西BFS不要启动,DFS它似乎是一个可行的选择……
但是有一个问题,DFS默认直接写入到系统堆栈。系统堆栈和足够浅,此时OI传统的方法是通过手工叠写,acm究一下旁门左道——开栈外挂。
Uva上的神贴(Set heap size and stack size in C++,http://acm.uva.es/board/viewtopic.php?f=14&t=16685)里面提到了一个拓栈外挂:
#include <stdio.h>
#include <string.h>
#include <stdlib.h> int main2() {
char test[255 << 20];
memset(test, 42, sizeof(test));
printf(":)\n");
return 0;
} int main() {
int size = 256 << 20; // 256Mb
char *p = malloc(size) + size;
asm("movl %0, %%esp\n"
"pushl $exit\n" // if you get a compile error here under mingw/cygwin,
"jmp main2\n" // replace exit with _exit, and main2 with _main2.
:: "r"(p));
}
可惜这个外挂有点老了(kuangbin神牡丹江被虐哭)。我们须要依据如今的实际环境与时俱进,学习新姿势。学会灵活运用拓栈挂了
事先声明:我汇编是为了研究这个问题现学现卖的,有什么地方讲的不正确还望各位指正。谢谢!
1、理解原版的含义。以及原版如今碰到的问题
原版关键的思路是,从堆上申请一大块内存,然后把esp(一个指向系统栈的寄存器)所指向的空间改为刚刚手工申请的地盘。之后把退出函数先推入,再直接跳转到main2的函数调用里去。
这个整体思路是没错,但是在语法上,在如今的编译器下,那是要磕磕碰碰老半天了——毕竟当年是2007年4月。如今是2014年10月了,gcc3.*都变成gcc4.7.2了,当年32位还非常流行,如今比赛环境、评測环境都是烂大街的64位。不少细节须要改动了。
为了具体说明情况,接下去将採用3个不同的測试环境
1、Win下的MinGW4.7.2
2、Linux(CentOS 6.5)下的gcc4.8.1
3、ZOJ评測
2、从攻坚Win 32位出发!
把上述代码按凝视中的提示改动。放到MinGW去编译,结果得到编译错误:
Undefined reference to 'main2';
找不到main2?这也是醉了?。
于是轮到利用网络资源的时刻了
我也不知道为什么,我在一个讲ARM-GCC内联汇编的文章(http://www.ethernut.de/en/documents/arm-inline-asm.html)里偶然看到了一句话:
extern long Calc(void) asm ("CALCULATE");
好吧,我们现学现卖,我们加上一句:
extern int main2(void) asm ("_main2");
然后编译,没问题了!
等一会就有个笑脸:)了!
好了,Win 32位环境下没事了。
3、转移到Linux 64位下的漫漫长征
接下去,开了虚拟机,扔到Linux的GCC手上编译一下,挂了……
提示是:
invalid instruction suffix for `mov'
invalid instruction suffix for `push'
继续研究……
中间折腾来折腾去的过程不用多说,
可是发现pushl改成push就少了个错误,那是个好消息
后来查资料。知道push和mov最后的字母表示操作的单位是b(1字节)。w(2字节一个word),l(4字节一个longword)
呃,等等,64位环境。8字节呢?
Pascal选手都知道qword吧……
那我们猜猜看最后一个字母可不能够是q(quadword)
于是pushl改成pushq,这里还是没问题!
好的,那以下对mov动刀
首先想到栈地址应该是个qword,于是应该试试看movq,但是编译失败……
然后。64位汇编应该和32位的不一样吧……继续搜64位汇编资料。发现esp在64位下被rsp替代了
于是语句改动成:
"movq %0, %%rsp\n"
"pushq $exit\n"
"jmp main2\n"
编译。pass了。执行起来得到了笑脸。yes!
4、实战环境检測——zoj为例
于是。直接把之前的2014牡丹江H题代码套上拓栈语句试试看(注意拓栈的大小。毕竟有内存限制的)
结果无情的返回CE……并且CE的错误提示挺无厘头的:
(第二节新加的那一句)error: expected initializer before 'asm'
左搞搞右搞搞,怎么都搞不正确。
这个时候,想起来,应该去看看编译命令的
C++: g++ foo.c -o foo -ansi -fno-asm -O2 -Wall -lm --static -DONLINE_JUDGE
-fno-asm?!
我也是醉了……
于是,把asm换成__asm__继续
然后接下来迎来了Non-zero Exit Code
这个太无解了(毕竟汇编全然不熟),然后灵机一动想到一个好办法:
在实际做事情的main2()函数里面。把之前我们经常使用的return 0;所有换成exit(0);
这下oj评測环境你总没办法了吧?最终迎来了AC……
(与这个的奋斗未完待续)
未完毕測试的项目:
1、之前用了VC++拓栈外挂过的可不能够用这个拓栈挂过了呢?
2、这样的拓栈挂安全性和普适性怎样?
5、总结
不得不承认,作为一个课外自发研究项目,这个折腾来折腾去挺好玩的
神犇们肯定不屑一顾
或许不少小菜急急忙忙就收走了。然后“着火”时刻立即拉出来用了
说老实话啊,这样的对水平提升帮助太小。这里贴出来仅仅是作为个人总结,也供大家娱乐。
祝各位接下来水平能有实质性的突破!
最后感谢一下队友。感谢ACDream群里的各位神犇,特别感谢kuangbin、[CUGB]fz、[bupt]leo、[NENU]Lee_vincent等人的关心和和支持和指导。
附赠:完整改动版的G++可用拓栈外挂模板
1、Win 32位MinGW 4.7.2环境
#include <stdio.h>
#include <string.h>
#include <stdlib.h> extern int main2(void) __asm__ ("_main2"); int main2() {
char test[255 << 20];
memset(test, 42, sizeof(test));
printf(":)\n");
exit(0);
} int main() {
int size = 256 << 20; // 256Mb
char *p = (char *)malloc(size) + size;
__asm__ __volatile__(
"movl %0, %%esp\n"
"pushl $_exit\n"
"jmp _main2\n"
:: "r"(p));
}
2、Linux 64位gcc 4.8.1环境
#include <stdio.h>
#include <string.h>
#include <stdlib.h> extern int main2(void) __asm__ ("main2"); int main2() {
char test[255 << 20];
memset(test, 42, sizeof(test));
printf(":)\n");
exit(0);
} int main() {
int size = 256 << 20; // 256Mb
char *p = (char *)malloc(size) + size;
__asm__ __volatile__(
"movq %0, %%rsp\n"
"pushq $exit\n"
"jmp main2\n"
:: "r"(p));
}
3、整体改动规律:
1)extern那个伪main函数这一步不可缺少!
不然编译器找不到的!
2)32位下请用longword和32位寄存器,64位下请用quadword和对应的64位寄存器
3)习惯性地return 0;或更换exit(0);大多数被保险人
版权声明:本文博主原创文章,博客,未经同意不得转载。
有关信息ACM/ICPC竞争环境GCC/G++叠插件研究记录的扩展的更多相关文章
- 2019 ACM/ICPC North America Qualifier G.Research Productivity Index(概率期望dp)
https://open.kattis.com/problems/researchproductivityindex 这道题是考场上没写出来的一道题,今年看看感觉简单到不像话,当时自己对于dp没有什么 ...
- 2014嘉杰信息杯ACM/ICPC湖南程序设计邀请赛暨第六届湘潭市程序设计竞赛
比赛链接: http://202.197.224.59/OnlineJudge2/index.php/Contest/problems/contest_id/36 题目来源: 2014嘉杰信息杯ACM ...
- ACM ICPC 2015 Moscow Subregional Russia, Moscow, Dolgoprudny, October, 18, 2015 G. Garden Gathering
Problem G. Garden Gathering Input file: standard input Output file: standard output Time limit: 3 se ...
- gcc/g++/make 编译信息带颜色输出
假设编译一个项目错误警告太多.很不好找,所以很希望输出信息能够带有颜色. 但是 gcc 4.9.0 之前的版本号并不支持,非常多情况下是不能替换编译器的,比方使用交叉编译器, 也能够使用 colorg ...
- Windows Sublime Text 配置Linux子系统(WSL)下的 gcc/g++ 编译环境
0. 简介(若已了解背景可以跳过此部分) Windows 10 Build 14316以上版本中加入了"Windows系统的Linux子系统"(Windows Subsystem ...
- MinGW下载并配置gcc/g++编译环境
本文将讲解如何下载MinGW并配置gcc\g++编译环境 一.下载MinGW 在MinGW官网中下载“mingw-get-setup.exe” 官网传送门:http://www.mingw.org/ ...
- ACM ICPC China final G Pandaria
目录 ACM ICPC China final G Pandaria ACM ICPC China final G Pandaria 题意:给一张\(n\)个点\(m\)条边的无向图,\(c[i]\) ...
- Linux环境下GNU, GCC, G++编译器
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012823258/article/details/36890125 一.GNU GNU是" ...
- Linux环境下GNU, GCC, G++编译器(转)
一,GNU GNU是“GNU 's Not Unix”的递归缩写, Stallman宣布GNU应当发音为Guh-NOO(革奴)以避免与new这个单词混淆(注:Gnu在英文中原意为非洲牛羚,发音与new ...
随机推荐
- 微凉大大,教你一步一步在linux中正确的安装Xcache加速php。
首先,强烈吐槽,百度上的教程,都左复制右复制的,乱七八糟,缺东缺西的.借此微凉大大我提供我苦心整理好的教程.以便各位小菜能顺利的使用Xcache加速php,假设看完了,也操作了,还是失败了的话,请联系 ...
- C++ - Operator Precedence
The following table lists the precedence and associativity of C++ operators. Operators are listed to ...
- Qt之生成Window资源文件(.rc 文件)
简述 qmake 可以随意地自动生成一个适当填充的 Windows 资源文件.本节主要讲解如何用 qmake 处理一个 Windows 资源文件,并将其链接到一个可执行应用程序(EXE)或动态链接库( ...
- Delphi的TService的輸入桌面切換(服务程序)(windows登录界面如何截图)(使用了OpenDesktop和GetThreadDesktop等API)
dfm: object CopyDeskService: TCopyDeskService OldCreateOrder = False OnCreate = ServiceCreate OnD ...
- 【Demo 0005】视图控制器
本章学习要点: 1. 熟悉MVC模型及模型中(Modal, View, Control)用途: 2. 了解iOS中常见的几种视图控制器及使用场景: 3. 掌握 ...
- Cocos2d-x CCProgressTimer
CCProgressTimer,创建使用这个节点可以大致实现两个作用的效果: 其一:在游戏中几乎大部分的游戏启动界面都是游戏加载画面,那么用到的一般是进度条提示加载进度,其使用的就是CCProgres ...
- 函数指针玩得不熟,就不要自称为C语言高手(函数指针是解耦对象关系的最佳利器,还有signal)
记得刚开始工作时,一位高手告诉我说,longjmp和setjmp玩得不熟,就不要自称为C语言高手.当时我半信半疑,为了让自己向高手方向迈进,还是花了一点时间去学习longjmp和setjmp的用法.后 ...
- Html中隐藏a标签
<div><a href="#"><span style="visibility:hidden">我的</span&g ...
- SilkTest Q&A 6
Q51.GMO在线的问题? 该问题是一个特例,不具有代表性,故不翻译了. Q52.如何为一个testplan的属性定义值? A52:你必须在使用前为一个testplan定义值: 1.确保你的test ...
- 腾讯測试project师笔试面试记录
从3月29日參加腾讯笔试開始,開始了为期1周的腾讯之旅,尽管最后还是跪在了二面上,可是感觉收获非常多,至少明确了自己与向往的BAT公司的差距,明确了自己还是路漫漫其修远兮. 腾讯非常注 ...