close
一把刀實用查詢📘

小計算器/譯原理學習日記簡單指令型計算器(2)虛擬機的實現



  首先,我對指令系統進行了完善,主要是添加了很多三角函數指令,尤其是雙曲函數。還有,我修改了運算元和指令的資料類型,通過使用typedef語句,我將運算元類型聲明為double、將指令類型聲明為unsigned char。這主要體現在inst.h的改動中,我在其中添加了如下聲明:


/* type of instructions: */

typedef unsigned char inst_t;


/* type of operands: */

typedef double operand_t;


  這使得我的程式更具伸縮性。當然,這些改動使得我同時改動了彙編編譯器和反彙編編譯器。如果大家真的感興趣,而且需要“新版”的計算器,呵呵,老規矩,給我發郵件,我悄悄地告訴你。


  另外還有一件值得高興的事我要在這裏說,我的大學英語四級(國家)考試居然過了!我還是上上次(非典剛過,9月份那次)考的試,都沒指望了,也沒查過分,而且上次(大概是1月份的吧)都沒報名。前兩天居然接到通知,60.5!哈哈哈Tracy


  好了,這也不是什麼光彩的事,不過覺得很有意思而已。我這種人四級居然能過,中國的教育……

  現在就說說我這個虛擬的計算器的實現吧。程式方面沒什麼新鮮的,主要是一些想法和其中的數學原理。

  首先,以前已經說過,這個計算器是基於堆疊的。不過,我沒有在其中使用任何顯式的堆疊資料結構,也沒有特地為此建立函數庫。原因很簡單——效率。我在程式中聲明了一個全局陣列opStack,類型為operand_t,作為運算棧;以及一個總體變數opSP,類型為unsigned int,作為堆疊指標。堆疊指標的初值為零(因為使用了無符號整型),這可能與一些用陣列實現堆疊的程式不太一樣;這樣,出棧操作類似於:


operand_t operand = opStack[--opSp];


而入棧操作類似於:


opStack[opSp++] = operand;


  也就是說,我的堆疊指標並未指向棧頂元素,而是指向了棧頂元素上面的位置。不過,我在程式中並沒有使用這樣的操作,稍後將作說明。


  由於使用了固定大小的運算棧,對堆疊的空滿狀態的檢查就顯得尤為重要。因為幾乎所有的指令都要涉及到出入棧操作,因此,我為棧狀態的檢查編寫了兩個宏:


/* check the stack status(overflow): */

  1. define check_overflow() \

  if(opSp >= MAX_STACK_SIZE - 1) { \

  fprintf(stderr, "Operate stack overflow!\n"); \

  exit(0); \

  }


/* check the stack statuc(underflow)

  • n means how many operands are required:
  • /
  1. define check_underflow(n) \

  if(opSp <= n - 1) { \

  fprintf(stderr, "Operate stack underflow!\n"); \

  exit(0); \

  }

  其中,check_overflow()用於檢查運算棧是否上溢出,用於所有入棧操作之前;check_underflow()用於檢查運算棧是否下溢出,用於所有出棧操作之前。由於所有的指令最多只會將一個運算元壓入堆疊,check_overflow()巨集是沒有參數的,只要檢查運算棧中是否有一個空位即可;但是,有的指令需要彈出一個運算元,有的需要兩個,所以我為check_underflow()宏添加了一個參數,用來表示需要的檢查的最小空間。下面的示意圖顯示了堆疊的結構和堆疊指標在不同情況下的位置,可以幫助你理解如果獲取棧頂運算元(後面會遇到)以及上、下溢出檢查的依據。

關于“小計算器/譯原理學習日記簡單指令型計算器(2)虛擬機的實現”的用戶留言:

目前暫無留言

新增相關留言✍


返回首頁 | 📱 行動版 | 電腦版 💻
2009-2024 v1.22 a-j-e-3