这个汇编程序读入一个字符串,并计算结果。支持加减乘除括号,不支持浮点数,不支持查错。以下是汇编以及注释。汇编程序使用
这篇文章的程序编译并执行。
这个程序可以覆盖除了浮点以外的几乎所有参数格式,用于测试汇编器是否正确。
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