【原创】【自制编程语言】1.从argv[1]开始
第1天:从argv[1]开始
先从命令行参数讲起吧。
现今的人们,尤其是写大型的项目,一般都用IDE。我们没那么高级,只是先从一个编译器做起,不需要IDE。对于编译器的调用,本质就是给一个源代码进去,经过对源代码进行分析,然后出来一个结果。那么对于源代码文件,传送给编译器,一般使用命令行参数。
C:\> gcc test.c -o test
一般我们调用都是直接写一个exe的名称,这里,在名称后面加上的各种东西了例如"test.c","-o",这些就叫做参数。而在调用exe的时候,加上的参数一般称为命令行参数。参数就是告知编译器一些信息的。
如何获取这些参数呢?对于C和C++,获取命令行参数是直接通过main函数获取的:
int main(int argc,char** argv){
}
把main函数声明成这种形式,就能获取命令行参数。其中,argc表示参数的数量,argv是一个指针数组(指针的指针),写法是char** argv
,也有写作char *argv[]
的,两种方式含义相同,其中从argv[0]开始一直到argv[argc-1],都是字符串,保存的就是参数。
一般来说,argv[0]存放这个exe的名称,而argv[1]开始就是第一个参数了,我们可以通过调用argv[1]来获取我们需要编译的代码。
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
using namespace std;
int main(int argc,char** argv){
if(argc!=2){
printf("The syntax of the command is incorrect.\n");
exit(1);
}
FILE *fp=fopen(argv[1],"r");
return 0;
}
代码的主体结构就是这样了。
然后,我们就可以开始正式读入我们的东西了。在此之前,为了方便我们的后续,也是为了仿制汇编语言更加像一些,我决定在里面做一些东西:寄存器。
寄存器其实在汇编语言里面有很多,例如EAX,EBX,ESI,EDI,SS,DS,CS等,毕竟我们只是乱做,寄存器其实也是汇编里面非常接近硬件的东西,(话说C可以内嵌汇编,也就是说这些东西一定程度上我们还是可能实现的)我们就没必要设太多,就设:
eax ebx ecx edx esi edi ebp esp
对了,还有一个eip,用于存放指令的地址,这里我们就不是指令了,而是读入的语句(或者说单词),我们把读入的单词全部放入数组,用eip变量指向这个数组就可以了,eip主要是在后面写跳转的时候用处比较大,现在暂时无法体现出来。
使用一个循环来读入所有的单词,我们这里由于实现的东西比较简单,其实也不需要做词法/句法上的判断,至于词法/句法执行时再做判断,这样也轻松一些。(其实不就是懒
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
using namespace std;
typedef string Word;
int eax,ebx,ecx,edx,esi,edi;
int *ebp,*esp;
Word *eip;
Word wd[32768+10];
int main(int argc,char** argv){
if(argc!=2){
printf("The syntax of the command is incorrect.\n");
exit(1);
}
FILE *fp=fopen(argv[1],"r");
eip=wd;
for(;;){
char s[100];
int i=fscanf(fp,"%s",s);
if(i==EOF)break;
*eip=s;++eip;//*eip就是读取的指令单词 ,存储在wd数组中
}
return 0;
}
我们规定使用"end"字符串来结束代码,经过简单的加工,最终写出来的代码是这样的:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
using namespace std;
typedef string Word;
int eax,ebx,ecx,edx,esi,edi;
int *ebp,*esp;
Word *eip;
Word wd[32768+10];
Word getword(){
return *(eip++);
}
int main(int argc,char** argv){
if(argc!=2){
printf("The syntax of the command is incorrect.\n");
exit(1);
}
FILE *fp=fopen(argv[1],"r");
eip=wd;
for(;;){
char s[100];
int i=fscanf(fp,"%s",s);
if(i==EOF)break;
*eip=s;++eip;//*eip就是读取的指令单词 ,存储在wd数组中
}
eip=wd;
for(;;){
Word s=getword();
if(s=="end"){
exit(0);
}
}
return 0;
}
未完待续。