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