磁芯/核心大战(core war)—是可自我繁殖的电脑病毒的起源
——百度百科
Corewar是代码间的战争(更不如说作病毒间的生存竞争)
代码按着它们自身运行,进行攻击、繁殖等行为
目的则只有一个,杀死它方,努力存活,得到更多积分,最终成为KOTH(King Of The Hill,山丘之王)
程序使用名为Redcode的汇编语言编写,文件后缀名为.red
其余详细介绍请自行上网搜索,在这不做赘述
.red文件在哪里都可以编写(包括传统记事本到VScode都可以编写)
而运行Corewar与.red文件的软件也很多(甚至可以自己搭建,具体方法不指出,我也不会)
这里使用较简单,功能完善的CoreWin(即使其实早不更新但已有功能也足够我们使用了)
下载(只用于Windows)
若系统非Windows可到此处寻找其他系统适用软件
— 原版
— 作者自己的汉化版
界面(部分)
(英文原版可对照使用)
操作按中文界面便行,不作过多介绍
(ps:此非必须操作,不按规范基本也可编译运行,此规范仅为美观与方便阅读)
;代表注释,在开头或一行代码结束处放入,后可随意编写文字符号等,不会被编译入
开头可写上特殊注释,基本有
特殊注释完后编写程序
规范也会渐渐在后续教程中补充
在了解学习这个堪称Corewar中hello world级别的经典程序前,我们要先更深入了解下Corewar
Corewar在一个core(磁芯?内存?随便你怎么叫)内运行,而现在让我们一起来想象下
有一个长长的纸条,上面画满了8000个格子(一般来说是这样),纸条上的格子写满了所谓代码(更像是字母与数字的奇怪结合,大多是dat 0, 0),纸条以奇怪的形式扭在一起,变成了一张纸片,却依旧首尾相接,上面有着奇怪的红点,它们根据这些格子上的代码,一会儿把代码搬来搬去,又把数字搞的乱七八糟,有时又突然飞到了另一个地方,甚至分成两半…
这大抵就是Corewar运行时的样子了,怪诞又有趣
所谓纸条便是core,它是一个线形内存,头尾相接,没有终点
红点就是你的进程们(在CoreWin中它们也是这么表示的)
它们一般执行完指令就向下跳一行(除了像jmp之类的指令)
现在我们开始IMP吧
它简单到只有一行代码
mov 0, 1
这便是IMP,我们现在来说明它的运行原理
进程会在程序的开头运行,所以程序一开始运行了mov 0, 1这个指令
mov指令的意思是
这里还涉及到一点关于Corewar中相对位置的问题
core是没有尽头的,也意味着没有开始,所以Corewar中所有位置都属于相对位置,这意味的所谓1不是第1行指令,而是下1行指令
因此mov 0, 1的意思是将下数0行(本行)移至下数1行
代码便变为了
mov 0, 1
mov 0, 1 % ;刚复制下来的指令,%表示进程所在位置,实际中不会出现
一个一模一样的指令出现了
接下来进程就会继续移动,下一行,移动,下一行…
最后到了画面的尽头,又回到开端,直到一轮结束
这便是IMP的原理,短小而精悍,打平天下无敌手(IMP没有攻击性手段,导致最后总是大部分程序也变成IMP直到平局)
现在让我们来试试编写一个反向移动的IMP
很自然的,我们会写出这个
mov 0, -1
(如果你无法看懂这段指令,建议回到上一章钻研)
让我们运行一下
mov 0, -1 ;刚复制出的指令
mov 0, -1
dat 0, 0 % ;没有指令的core空间会填满dat 0, 0(一般来说)
进程执行至dat时会直接死亡(因此dat常作为攻击手段)
这是一个经典的误区
因此我们该引出一个新的指令来解决这个问题了
mov 0, -1
jmp -1, 0
因此当进程移至下一行时
mov 0, -1 ;复制出的新指令
mov 0, -1 ;<————————\
jmp -1, 0 % ;—/跳转
进程将跳回上一行,接着便形成一个循环,但由于指令一直只能是mov 0, -1,所以向上复制一行似乎是它的极限,当然你可以为它加上sub(减法指令),但我们接下来介绍的是一种更精短巧妙的方法
我们先引进寻址模式这个概念
Corewar中的每个操作数都是有寻址模式的
我们前面写的操作数都是$模式(直接寻址)
而其他的寻址模式有
#(立即寻址*(A操作数间接@(B操作数间接{(A操作数间接后减}(A操作数间接后增<(B操作数间接后减>(B操作数间接后增(也会在最后附上全部的寻址模式集)
我们先简单介绍下
立即寻址就相当于纯粹的数字,而不是指向一个地址
间接寻址会有些麻烦,我们会在之后详细介绍
最后是后增/后减,它们间接寻址后会将所指地址的相应操作数加1/减1
这正是我们所要的结果
我们要将后减寻址放在一个闲置的操作数上且不会影响到原程序的运行
于是我们想起了jmp的B操作数
Corewar中当你运行jmp时,虽然B操作数对跳转一点用都没有,但它还是会寻址
利用这个特点,我们便可以利用B操作数,像资本家一样压榨jmp所有的价值,让它在跳转的同时为我们修改数值,一个指令当两个用,何乐而不为呢
于是程序变成了这样
mov 0, -1
jmp -1, <-1
自己运行吧!看看这些程序神奇般地运作,这便是Corewar的最大乐趣
(到了最后由于Corewar地址相对性与模地址(地址将会被模以core大小)的缘故,最后PMI还将会变回IMP,试着自己理解吧)
这是一个短小的章节
让我们来了解一个简单的程序
我们知道,jmp可以让进程跳来跳去,当A操作数为0的时候,它就会定在原地,就像一扇门(不过弱得谁都可以打破它)
如标题所见,我们要用这扇门来挡住凶狠的IMP,当然根据你现在所学,你很容易想出要用寻址模式
写出来吧,作为本教程为数不多的作业
让我们来写一个真正具有攻击性的程序,这总是让人感到激动的!
我们来先了解下所用到的指令们
首先我们先理清我们所要做的
将dat移动,更改完mov的操作数,最后跳转回去
程序大抵这样
dat 0, 0
mov -1, 3
add #4, -1 ;运算类指令应用#代表数字而不是地址,运算类指令都是向B执行A(如这个是将地址-1的B操作数加上4)
jmp -2, 0
尝试在自己的CoreWin(或者其他模拟器)运行它们
现在让我们将这个程序做上改版来解释 ##所有的寻址模式与指令修饰符##
首先我们来解释前面说的间接寻址
这是一个改版(效果与原先完全一致)
dat 0, 0
mov -1, @-1
add #4, -2
jmp -2, 0
DAT (储存数据,非法MOV (移动指令ADD (加法指令,注意所以运算都是将B进行操作SUB (减法指令MUL (乘法指令DIV (除法指令,除0时非法MOD (模法指令JMP (跳转指令JMZ (为零跳转JMN (非零跳转DJN (非零前减跳转SPL (分裂指令CMP/SEQ (比等下跳SNE (不等下跳SLT (小于下跳LDP (下载从P空间STP (上载到P空间NOP (占位指令,没有任何操作#(立即寻址$(直接寻址,可省略*(A操作数间接@(B操作数间接{(A操作数间接后减}(A操作数间接后增<(B操作数间接后减>(B操作数间接后增.A - 将源指令的A操作数对目标指令的A操作数进行操作.B - 将源指令的B操作数对目标指令的B操作数进行操作.AB - 将源指令的A操作数对目标指令的B操作数进行操作.BA - 将源指令的B操作数对目标指令的A操作数进行操作.F - 将源指令的两个操作数对目标指令的相同操作数进行操作.X - 将源指令的两个操作数对目标指令的相反操作数进行操作.I - 将整个源指令对目标指令进行操作本教程就应到这了,若有错误或愿意探讨Corewar可以通过邮箱-1239786106@qq.com
希望能够帮助你打开Corewar的大门
如今,没有太多的初学者对Core War感兴趣。当然,这是很自然的事情-并不是很多人都会觉得编写汇编代码是很有趣的-但入门门槛较高的原因之一可能是很难找到有关它的基本教程。的确,周围是有很多不错的文档,但是其中大多数文档要么太技术性,已经过时,太难找到,要么就是不完整。 这就是为什么我决定编写本指南的原因。我的目的是指导新手,从他们第一次接触Core War和Redcode到他们可以编写一个工作的(可能是不成功的)战士,并能够进行更多技术性工作的程度。 —-Ilmari Karonen