随笔-341  评论-2670  文章-0  trackbacks-0
    这个汇编程序读入一个字符串,并计算结果。支持加减乘除括号,不支持浮点数,不支持查错。以下是汇编以及注释。汇编程序使用这篇文章的程序编译并执行。

    这个程序可以覆盖除了浮点以外的几乎所有参数格式,用于测试汇编器是否正确。

  1 CONSTANT
  2   INPUT stra:(11+22)*(33+44)
  3 VARIABLE
  4   RESULT int32
  5 CODE
  6 
  7   MOV EDI, int32 INPUT        //将输入的字符串指针放入EDI
  8   CALL @GETEXP            //EAX=GETEXP
  9   MOV int32 [RESULT], EAX    //输出结果
 10   MOV EAX, int32 RESULT
 11   RET
 12 
 13 @GETEXP:            //从EDI读取一个表达式,结果放入EAX,偏移
 14   PUSH EDX
 15   CALL @GETTERM
 16 @GETEXP_LOOP_BEGIN:
 17   CMP int8 [EDI], int8 $+    //检查操作符是否'+'
 18   JE @GETEXP_ADD        //是则跳往GETEXP_ADD
 19   CMP int8 [EDI], int8 $-    //检查操作符是否'-'
 20   JE @GETEXP_SUB        //是则跳往GETEXP_SUB
 21 @GETEXP_FINISHED:        //否则直接退出
 22   POP EDX
 23   RET
 24 @GETEXP_ADD:
 25   INC EDI            //跳过加号
 26   MOV EDX, EAX            //EDX=EAX
 27   CALL @GETTERM            //EAX=GETTERM
 28   ADD EAX, EDX            //EAX=EAX+EDX
 29   JMP @GETEXP_LOOP_BEGIN    //继续循环
 30 @GETEXP_SUB:
 31   INC EDI            //跳过减号
 32   MOV EDX, EAX            //EDX=EAX
 33   CALL @GETTERM            //EAX=GETTERM
 34   SUB EDX, EAX            //EDX=EDX-EAX
 35   MOV EAX, EDX            //EAX=EDX
 36   JMP @GETEXP_LOOP_BEGIN    //继续循环
 37 
 38 @GETTERM:            //从EDI读取一个只含有乘除法的字符串,结果放入EAX,偏移
 39   PUSH EDX
 40   PUSH EBX
 41   CALL @GETFACTOR        //读取一个factor
 42 @GETTERM_LOOP_BEGIN:
 43   CMP int8 [EDI], int8 $*    //检查操作符是否'*'
 44   JE @GETTERM_MULTIPLE        //是则跳往GETTERM_MULTIPLE
 45   CMP int8 [EDI], int8 $/    //检查操作符是否'/'
 46   JE @GETTERM_DIVID        //是则跳往GETTERM_DIVID
 47 @GETTERM_FINISHED:        //否则直接退出
 48   POP EBX
 49   POP EDX
 50   RET
 51 @GETTERM_MULTIPLE:
 52   INC EDI            //跳过乘号
 53   MOV EDX, EAX            //EDX=EAX
 54   CALL @GETFACTOR        //EAX=GETFACTOR
 55   IMUL EAX, EDX            //EDX:EAX=EAX*EDX
 56   JMP @GETTERM_LOOP_BEGIN    //继续循环
 57 @GETTERM_DIVID:
 58   INC EDI            //跳过除号
 59   MOV EBX, EAX            //EBX=EAX
 60   CALL @GETFACTOR        //EAX=GETFACTOR
 61   XCHG EAX, EBX            //交换EAX和EBX,EAX是被除数,EBX是除数
 62   XOR EDX, EDX            //EDX=0
 63   IDIV EBX            //EAX=EDX:EAX/EBX
 64   JMP @GETTERM_LOOP_BEGIN    //继续循环
 65 
 66 @GETFACTOR:            //从EDI读取一个数字或被括号包围的字符串,结果放入EAX,偏移EDI
 67   CMP int8 [EDI], int8 $(    //检查第一个字符是否'('
 68   JE @GETFACTOR_BRACKED        //是则跳往GETFACTOR_BRACKED
 69   JMP @CONVERT            //否则直接使用CONVERT代替
 70 @GETFACTOR_BRACKED:
 71   INC EDI            //跳过括号
 72   CALL @GETEXP            //调用GETEXP计算一个表达式
 73   INC EDI            //跳过右括号
 74   RET                //退出
 75 
 76 @CONVERT:            //同UNSIGNED_CONVERT,支持负号
 77   CMP int8 [EDI], int8 $-    //检查第一个符号是不是负号
 78   JE @CONVERT_NEGATIVE        //是则跳往CONVERT_NEGATIVE处理负号
 79   CALL @UNSIGNED_CONVERT    //否则调用UNSIGNED_CONVERT
 80   RET                //退出
 81 @CONVERT_NEGATIVE:
 82   INC EDI            //略过负号
 83   CALL @UNSIGNED_CONVERT    //调用UNSIGNED_CONVERT
 84   NEG EAX            //将EAX变负
 85   RET                //退出
 86 
 87 @UNSIGNED_CONVERT:            //将EDI指向的字符串转成整数,放入EAX,并偏移EDI至末尾
 88   XOR EAX, EAX
 89   PUSH EDX
 90 @UNSIGNED_CONVERT_LOOP_BEGIN:
 91     CMP int8 [EDI], int8 $0        //检查字符是否大于等于'0'
 92     JB @UNSIGNED_CONVERT_LOOP_END    //失败则退出
 93     CMP int8 [EDI], int8 $9        //检查字符是否小于等于'9'
 94     JA @UNSIGNED_CONVERT_LOOP_END    //失败则退出
 95     MOV EDX, int32 10            //EDX=10
 96     MUL EDX                //EDX:EAX = EAX*EDX
 97     XOR EDX, EDX            //EDX=0
 98     MOV DL, int8 [EDI]            //DL=*EDI
 99     SUB EDX, int32 $0            //EDX-='0'
100     ADD EAX, EDX            //EAX=EAX+EDX
101     INC EDI                //EDI++
102     JMP @UNSIGNED_CONVERT_LOOP_BEGIN    //再次执行循环
103 @UNSIGNED_CONVERT_LOOP_END:
104   POP EDX
105   RET
posted on 2009-02-26 09:05 陈梓瀚(vczh) 阅读(2203) 评论(0)  编辑 收藏 引用 所属分类: JIT

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理