1. 程式人生 > 其它 >【原創】【自制程式語言】1.從argv[1]開始

【原創】【自制程式語言】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;
}

未完待續。