在完成了
这里和
这里的工作之后,就可以写程序生成机器码了。在生成机器码的时候有如下注意事项:
1:可执行代码所在的空间必须使用VirtualAlloc与PAGE_EXECUTE_READWRITE标记分配。
2:程序需要的常量空间、全局变量空间和指令空间需要分开在三个不同的地方。
下面的例子使用一个struct保存指令的每一个部分,并且结合之前产生的指令译码表生成二进制码。
1 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
2 #include "..\..\..\..\VL++\Library\Script\JIT\Assembler\VL_JIT_X86Generator.h"
3 #include <windows.h>
4
5 using namespace vl;
6 using namespace vl::platform;
7 using namespace vl::jit::x86;
8 using namespace vl::jit::assembly;
9
10 extern void Main_Generator();
11
12 #define GET_LABEL(NAME,VARIABLE) \
13 { \
14 VARIABLE=Program.LabelNames.IndexOf(L#NAME); \
15 if(VARIABLE==-1) \
16 { \
17 VARIABLE=Program.LabelNames.GetCount(); \
18 Program.LabelNames.Add(L#NAME); \
19 Program.Labels.Add(-1); \
20 } \
21 }
22
23 #define INSTRUCTION(NAME) \
24 { \
25 VL_AsmIns Ins; \
26 Ins.Name=L#NAME; \
27 Ins.ParameterCount=0; \
28 Program.Instructions.Add(Ins); \
29 }
30 #define LABEL(NAME) \
31 { \
32 VInt LabelIndex=0; \
33 GET_LABEL(NAME,LabelIndex); \
34 VInt InsIndex=Program.Instructions.GetCount(); \
35 Program.Labels[LabelIndex]=InsIndex; \
36 }
37 #define PARAM_IMM_32(IMMEDIATE) \
38 { \
39 VInt Index=Program.Instructions.GetCount()-1; \
40 VL_AsmIns& Ins=Program.Instructions[Index]; \
41 VInt PRMIDX=Ins.ParameterCount++; \
42 Ins.Parameters[PRMIDX].ParameterKind=vapkSigned; \
43 Ins.Parameters[PRMIDX].ParameterType=vaptInt32; \
44 Ins.Parameters[PRMIDX].Signed=IMMEDIATE; \
45 }
46 #define PARAM_REG_32(REGISTER) \
47 { \
48 VInt Index=Program.Instructions.GetCount()-1; \
49 VL_AsmIns& Ins=Program.Instructions[Index]; \
50 VInt PRMIDX=Ins.ParameterCount++; \
51 Ins.Parameters[PRMIDX].ParameterKind=vapkRegister; \
52 Ins.Parameters[PRMIDX].ParameterType=vaptInt32; \
53 Ins.Parameters[PRMIDX].Register=var##REGISTER; \
54 }
55 #define PARAM_MI_32(INDEX,SCALE,BASE,OFFSET) \
56 { \
57 VInt Index=Program.Instructions.GetCount()-1; \
58 VL_AsmIns& Ins=Program.Instructions[Index]; \
59 VInt PRMIDX=Ins.ParameterCount++; \
60 Ins.Parameters[PRMIDX].ParameterKind=vapkPointer; \
61 Ins.Parameters[PRMIDX].ParameterType=vaptInt32; \
62 Ins.Parameters[PRMIDX].Base=var##BASE; \
63 Ins.Parameters[PRMIDX].Index=var##INDEX; \
64 Ins.Parameters[PRMIDX].Scale=vas##SCALE; \
65 Ins.Parameters[PRMIDX].Offset=OFFSET; \
66 }
67 #define PARAM_LABEL(NAME) \
68 { \
69 VInt Index=Program.Instructions.GetCount()-1; \
70 VInt Label=0; \
71 GET_LABEL(NAME,Label); \
72 VL_AsmIns& Ins=Program.Instructions[Index]; \
73 VInt PRMIDX=Ins.ParameterCount++; \
74 Ins.Parameters[PRMIDX].ParameterKind=vapkLabel; \
75 Ins.Parameters[PRMIDX].ParameterType=vaptInt32; \
76 Ins.Parameters[PRMIDX].Label=Label; \
77 }
78
79 VL_AsmCompiled* Compile()
80 {
81 VL_AsmProgram Program;
82 {
83 // XOR EAX, EAX
84 INSTRUCTION(XOR)
85 PARAM_REG_32(EAX)
86 PARAM_REG_32(EAX)
87 // MOV ECX, [EDI]
88 INSTRUCTION(MOV)
89 PARAM_REG_32(ECX)
90 PARAM_MI_32(NONE,1,EDI,0)
91 // @BEGIN:
92 LABEL(BEGIN)
93 // CMP ECX, 0
94 INSTRUCTION(CMP)
95 PARAM_REG_32(ECX)
96 PARAM_IMM_32(0)
97 // JE @END
98 INSTRUCTION(JE)
99 PARAM_LABEL(END)
100 // ADD EAX, [ECX * 4 + EDI]
101 INSTRUCTION(ADD)
102 PARAM_REG_32(EAX)
103 PARAM_MI_32(ECX,4,EDI,0)
104 // SUB ECX, 1
105 INSTRUCTION(SUB)
106 PARAM_REG_32(ECX)
107 PARAM_IMM_32(1)
108 // JMP @BEGIN
109 INSTRUCTION(JMP)
110 PARAM_LABEL(BEGIN)
111 // @END:
112 LABEL(END)
113 // RET
114 INSTRUCTION(RET)
115 }
116 VL_AsmCompiled* Compiled=Compile(&Program);
117 if(Compiled->Errors.GetCount())
118 {
119 for(VInt i=0;i<Compiled->Errors.GetCount();i++)
120 {
121 VL_AsmError& Error=Compiled->Errors[i];
122 GetConsole()->Write(L"["+VUnicodeString(Error.Index)+L"]"+Error.Message+L"\r\n");
123 }
124 delete Compiled;
125 return 0;
126 }
127 else
128 {
129 return Compiled;
130 }
131 }
132
133 void vlmain()
134 {
135 GetConsole()->SetTitle(L"Vczh Library++ 2.0 Assembler");
136 GetConsole()->SetTestMemoryLeaks(true);
137 GetConsole()->SetPauseOnExit(true);
138
139 VL_AsmCompiled* Compiled=Compile();
140 if(Compiled)
141 {
142 VInt Size=(VInt)Compiled->InstructionBuffer.Size();
143 void* Buffer=VirtualAlloc(0,Size,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
144 Compiled->InstructionBuffer.SeekFromBegin(0);
145 Compiled->InstructionBuffer.Read(Buffer,Size);
146
147 VInt Params[]={10,1,2,3,4,5,6,7,8,9,10};
148 VInt* Input=Params;
149 VInt Output=0;
150 __asm
151 {
152 PUSH EAX
153 PUSH EBX
154 PUSH ECX
155 PUSH EDX
156 PUSH ESI
157 PUSH EDI
158 MOV EAX, dword ptr[Buffer]
159 MOV EDI, dword ptr[Input]
160 INT 3
161 CALL EAX
162 MOV dword ptr[Output], EAX
163 POP EDI
164 POP ESI
165 POP EDX
166 POP ECX
167 POP EBX
168 POP EAX
169 }
170 VirtualFree(Buffer,Size,MEM_RELEASE);
171 GetConsole()->Write(L"结果:EAX="+VUnicodeString(Output)+L"\r\n");
172 delete Compiled;
173 }
174 }
注意,VL_AsmCompiled* Compile()函数使用的宏用于简化汇编的编码(以后将写一个分析器将字符串的汇编转换成这些struct)。EDI指向11个32位整数(见下文对vlmain函数的说明)。程序首先将EDI[0]存放在ECX,此时ECX是10。然后执行一个循环让EAX=EDI[10]+EDI[9]+...+EDI[2]+EDI[1],然后ECX变成0,退出。
vlmain函数中的汇编首先将存放着指令的Buffer放入EAX,然后将Params数组的指针放入EDI,然后执行函数(INT 3用于在Visual Studio中产生断点)。汇编将结果保存在了EAX中,因此将EAX的结果村放入Output变量。最后输出。
下面是两张调试的贴图。使用Visual Studio的反汇编功能可以检查汇编器是否正确:
首先,程序运行到INT 3的时候会产生调试中断,这个时候使用Visual Studio捕获:
按CTRL+ALT+D进入汇编窗口以便跟踪(代码窗口不能单步进CALL):
执行到CALL EAX的时候按F11进入我们写程序生成的代码:
这里我们可以看到,程序产生的结果是正确的。于是CPU将顺利执行这段代码,最后将EAX变为55:
到这里就结束了。以下是汇编器的源代码的核心部分。首先是结构的声明:
1 /*******************************************************************************
2 Vczh Library++ 2.0
3 JIT::x86汇编数据结构
4 开发者:陈梓瀚
5
6 接口:
7 类:
8 函数:
9 *******************************************************************************/
10 #ifndef VL_JIT_ASSEMBLY
11 #define VL_JIT_ASSEMBLY
12
13 #include "..\..\..\Data\Data\VL_Data_Basic.h"
14 #include "..\..\..\Data\Data\VL_Data_String.h"
15 #include "..\..\..\Data\Data\VL_Data_List.h"
16 #include "..\..\..\Data\Data\VL_Data_Map.h"
17 #include "..\..\..\Data\VL_Stream.h"
18
19 namespace vl
20 {
21 namespace jit
22 {
23 namespace assembly
24 {
25 using namespace collection;
26 using namespace stream;
27
28 enum VLE_AsmParameterKind
29 {
30 vapkRegister, /*寄存器*/
31 vapkPointer, /*指针*/
32 vapkSigned, /*有符号数字*/
33 vapkUnsigned, /*无符号数字*/
34 vapkRelative, /*相对指针*/
35 vapkLabel /*Label指定的Relative指针常数*/
36 };
37
38 enum VLE_AsmParameterType
39 {
40 vaptInt8,
41 vaptInt16,
42 vaptInt32,
43 vaptFp32,
44 vaptFp64,
45 vaptFpReg
46 };
47
48 /*分段保持顺序*/
49 enum VLE_AsmRegister
50 {
51 varAL,
52 varAH,
53 varBL,
54 varBH,
55 varCL,
56 varCH,
57 varDL,
58 varDH,
59
60 varAX,
61 varBX,
62 varCX,
63 varDX,
64 varSP,
65 varBP,
66 varSI,
67 varDI,
68
69 varEAX,
70 varEBX,
71 varECX,
72 varEDX,
73 varESP,
74 varEBP,
75 varESI,
76 varEDI,
77
78 varST0,
79 varST1,
80 varST2,
81 varST3,
82 varST4,
83 varST5,
84 varST6,
85 varST7,
86
87 varNONE
88 };
89
90 /*保持顺序*/
91 enum VLE_AsmScale
92 {
93 vas1,
94 vas2,
95 vas4,
96 vas8
97 };
98
99 enum VLE_AsmErrorCode
100 {
101 vaecUnrecognizedName, /*不能识别的指令名称*/
102 vaecWrongParameterCount, /*错误的参数数量*/
103 vaecUnrecognizedKind, /*不能识别的参数样式*/
104 vaecUnrecognizedType, /*不能识别的参数类型*/
105
106 vaecLostRegister, /*寄存器为NONE*/
107 vaecWrongRegisterType, /*寄存器与参数值类型不匹配*/
108 vaecUnrecognizedRegister, /*无法识别的寄存器值*/
109
110 vaecLabelMustBeInt32, /*Label的类型必须是32位整数*/
111 vaecUnrecognizedLabel, /*无法识别的Label值*/
112
113 vaecIndexRegisterMustBe32Bits, /*Index寄存器必须是32位*/
114 vaecBaseRegisterMustBe32Bits, /*Base寄存器必须是32位*/
115 vaecUnrecognizedScale, /*无法识别的Scale值*/
116
117 vaecSignedMustBeInteger, /*有符号整数的类型必须是整数*/
118 vaecUnsignedMustBeInteger, /*无符号整数的类型必须是整数*/
119 vaecRelativeMustBeInteger, /*相对地址必须是整数类型*/
120 vaecSignedOutOfRange, /*有符号整数超过类型描述的范围*/
121 vaecUnsignedOutOfRange, /*无符号整数超过类型描述的范围*/
122
123 vaecUnrecognizedLinkingID, /*【】无法识别的链接ID*/
124 vaecParameterNotMatched, /*参数无法匹配指令的要求*/
125 vaecDoNotKnowHowToCompile /*不知道如何编译*/
126 };
127
128 struct VL_AsmError
129 {
130 VLE_AsmErrorCode ErrorCode;
131 VInt Index;
132 VUnicodeString Message;
133 };
134
135 struct VL_AsmParameter
136 {
137 VLE_AsmParameterKind ParameterKind; /*参数样式,决定Union哪些可用*/
138 VLE_AsmParameterType ParameterType; /*参数数值类型*/
139 struct
140 {
141 VInt LinkingID; /*链接数值ID*/
142 VInt LinkingOffset; /*链接数值偏移*/
143 VBool Enabled; /*是否允许链接,参数类型不接受链接则忽略*/
144 } Linking;
145 union
146 {
147 VInt32s Signed; /*vapkSigned、vapkRelative有效,Linking.Enable为true则使用Linking*/
148 VInt32u Unsigned; /*vapkUnsigned有效,Linking.Enable为true则使用Linking*/
149 VInt Label; /*vapkLabel有效*/
150 VLE_AsmRegister Register; /*寄存器*/
151 struct
152 {
153 VLE_AsmRegister Index; /*底数寄存器,为varNONE则忽略Index*Scale*/
154 VLE_AsmScale Scale; /*指数*/
155 VLE_AsmRegister Base; /*偏移寄存器,为varNONE则忽略Base*/
156 VInt Offset; /*常数偏移,Linking.Enable为true则使用Linking*/
157 };
158 };
159
160 VL_AsmParameter();
161 };
162
163 struct VL_AsmIns
164 {
165 VUnicodeString Name; /*指令名字*/
166 VInt ParameterCount; /*有效参数数量*/
167 VL_AsmParameter Parameters[4]; /*参数*/
168 };
169
170 struct VL_AsmProgram
171 {
172 typedef VL_List<VInt , true> _LabelMap;
173 typedef VL_List<VL_AsmIns , false> _InsList;
174 typedef VL_List<VUnicodeString , false> _LabelList;
175
176 static const VInt CONSTANT_BUFFER_POINTER=0; /*LinkingID:常数缓冲区指针*/
177
178 VL_MemoryStream ConstantBuffer; /*常数缓冲区*/
179 _LabelMap Labels; /*ID -> Instruction*/
180 _InsList Instructions; /*指令表*/
181 _LabelList LabelNames; /*ID -> Name*/
182
183 VL_AsmProgram();
184 };
185
186 struct VL_AsmCompiled
187 {
188 typedef VL_List<VL_AsmError , false> _ErrorList;
189
190 _ErrorList Errors;
191 VL_MemoryStream ConstantBuffer;
192 VL_MemoryStream InstructionBuffer;
193 VL_MemoryStream LinkingBuffer;
194
195 VL_AsmCompiled();
196 };
197 }
198 }
199 }
200
201 #endif
其次是产生二进制码的程序:
1 #include "VL_JIT_X86Generator.h"
2 #include "VL_JIT_X86.h"
3
4 namespace vl
5 {
6 namespace jit
7 {
8 namespace x86
9 {
10 void CopyStream(IVL_Stream* In , IVL_Stream* Out)
11 {
12 VByte Buffer[65536];
13 VInt Count=0;
14 In->SeekFromBegin(0);
15 Out->SeekFromBegin(0);
16 while(Count=In->Read(Buffer,sizeof(Buffer)))
17 {
18 Out->Write(Buffer,Count);
19 }
20 In->SeekFromBegin(0);
21 Out->SeekFromBegin(0);
22 }
23
24 VBool CheckParameter(VLE_InsParam Template , VL_AsmParameter& Assembly)
25 {
26 switch(Template)
27 {
28 case vipREL_8: return Assembly.ParameterKind==vapkRelative && Assembly.ParameterType==vaptInt8;
29 case vipREL_16: return Assembly.ParameterKind==vapkRelative && Assembly.ParameterType==vaptInt16;
30 case vipREL_32: return (Assembly.ParameterKind==vapkRelative && Assembly.ParameterType==vaptInt32) || Assembly.ParameterKind==vapkLabel;
31 case vipPTR_16_16: return Assembly.ParameterKind==vapkUnsigned && Assembly.ParameterType==vaptInt32;
32 case vipPTR_16_32: return false;
33 case vipREG_8: return Assembly.ParameterKind==vapkRegister && Assembly.ParameterType==vaptInt8;
34 case vipREG_16: return Assembly.ParameterKind==vapkRegister && Assembly.ParameterType==vaptInt16;
35 case vipREG_32: return Assembly.ParameterKind==vapkRegister && Assembly.ParameterType==vaptInt32;
36 case vipIMM_8: return (Assembly.ParameterKind==vapkSigned || Assembly.ParameterKind==vapkUnsigned) && Assembly.ParameterType==vaptInt8;
37 case vipIMM_16: return (Assembly.ParameterKind==vapkSigned || Assembly.ParameterKind==vapkUnsigned) && Assembly.ParameterType==vaptInt16;
38 case vipIMM_32: return (Assembly.ParameterKind==vapkSigned || Assembly.ParameterKind==vapkUnsigned) && Assembly.ParameterType==vaptInt32;
39 case vipRM_8: return (Assembly.ParameterKind==vapkRegister || Assembly.ParameterKind==vapkPointer) && Assembly.ParameterType==vaptInt8;
40 case vipRM_16: return (Assembly.ParameterKind==vapkRegister || Assembly.ParameterKind==vapkPointer) && Assembly.ParameterType==vaptInt16;
41 case vipRM_32: return (Assembly.ParameterKind==vapkRegister || Assembly.ParameterKind==vapkPointer) && Assembly.ParameterType==vaptInt32;
42 case vipM_16_16: return false;
43 case vipM_16_32: return false;
44 case vipM_16_AND_16: return false;
45 case vipM_16_AND_32: return false;
46 case vipM_32_AND_32: return false;
47 case vipMI_16: return Assembly.ParameterKind==vapkPointer && Assembly.ParameterType==vaptInt16;
48 case vipMI_32: return Assembly.ParameterKind==vapkPointer && Assembly.ParameterType==vaptInt32;
49 case vipMI_64: return false;
50 case vipMF_32: return Assembly.ParameterKind==vapkPointer && Assembly.ParameterType==vaptFp32;
51 case vipMF_64: return Assembly.ParameterKind==vapkPointer && Assembly.ParameterType==vaptFp64;
52 case vipMF_80: return false;
53 case vipSREG: return false;
54 case vipST_0: return Assembly.ParameterKind==vapkRegister && Assembly.Register==varST0;
55 case vipST_I: return Assembly.ParameterKind==vapkRegister && (Assembly.Register>=varST0 && Assembly.Register<=varST7);
56 case vipAL: return Assembly.ParameterKind==vapkRegister && Assembly.Register==varAL;
57 case vipAX: return Assembly.ParameterKind==vapkRegister && Assembly.Register==varAX;
58 case vipEAX: return Assembly.ParameterKind==vapkRegister && Assembly.Register==varEAX;
59 case vipCL: return Assembly.ParameterKind==vapkRegister && Assembly.Register==varCL;
60 case vipCX: return Assembly.ParameterKind==vapkRegister && Assembly.Register==varCX;
61 case vipECX: return Assembly.ParameterKind==vapkRegister && Assembly.Register==varECX;
62 case vipCS: return false;
63 case vipDS: return false;
64 case vipES: return false;
65 case vipFS: return false;
66 case vipGS: return false;
67 case vipSS: return false;
68 case vipCONST_1: return Assembly.ParameterKind==vapkUnsigned && Assembly.Linking.Enabled==false && Assembly.Unsigned==1;
69 case vipCONST_3: return Assembly.ParameterKind==vapkUnsigned && Assembly.Linking.Enabled==false && Assembly.Unsigned==3;
70 default: return false;
71 }
72 }
73 /*
74 VInt Selected=-1;
75 for(VInt i=0;i<4;i++)
76 {
77 switch(Format.Params[i])
78 {
79 case vipREL_8:
80 case vipREL_16:
81 case vipREL_32:
82 case vipPTR_16_16:
83 case vipPTR_16_32:
84 case vipREG_8:
85 case vipREG_16:
86 case vipREG_32:
87 case vipIMM_8:
88 case vipIMM_16:
89 case vipIMM_32:
90 case vipRM_8:
91 case vipRM_16:
92 case vipRM_32:
93 case vipM_16_16:
94 case vipM_16_32:
95 case vipM_16_AND_16:
96 case vipM_16_AND_32:
97 case vipM_32_AND_32:
98 case vipMI_16:
99 case vipMI_32:
100 case vipMI_64:
101 case vipMF_32:
102 case vipMF_64:
103 case vipMF_80:
104 case vipSREG:
105 case vipST_0:
106 case vipST_I:
107 case vipAL:
108 case vipAX:
109 case vipEAX:
110 case vipCL:
111 case vipCX:
112 case vipECX:
113 case vipCS:
114 case vipDS:
115 case vipES:
116 case vipFS:
117 case vipGS:
118 case vipSS:
119 case vipCONST_1:
120 case vipCONST_3:
121 if(!Used[i])
122 {
123 Selected=i;
124 Used[i]=true;
125 }
126 }
127 }
128 return Selected;
129 */
130
131 VInt FindRI(VLS_InsFormat& Format , VBool* Used)
132 {
133 VInt Selected=-1;
134 for(VInt i=0;i<4;i++)
135 {
136 switch(Format.Params[i])
137 {
138 case vipREG_8:
139 case vipREG_16:
140 case vipREG_32:
141 case vipAL:
142 case vipAX:
143 case vipEAX:
144 case vipCL:
145 case vipCX:
146 case vipECX:
147 if(!Used[i])
148 {
149 Selected=i;
150 Used[i]=true;
151 }
152 }
153 }
154 return Selected;
155 }
156
157 VInt FindRM(VLS_InsFormat& Format , VBool* Used)
158 {
159 VInt Selected=-1;
160 for(VInt i=0;i<4;i++)
161 {
162 switch(Format.Params[i])
163 {
164 case vipPTR_16_16:
165 case vipPTR_16_32:
166 case vipRM_8:
167 case vipRM_16:
168 case vipRM_32:
169 case vipM_16_16:
170 case vipM_16_32:
171 case vipM_16_AND_16:
172 case vipM_16_AND_32:
173 case vipM_32_AND_32:
174 case vipMI_16:
175 case vipMI_32:
176 case vipMI_64:
177 case vipMF_32:
178 case vipMF_64:
179 case vipMF_80:
180 if(!Used[i])
181 {
182 Selected=i;
183 Used[i]=true;
184 }
185 }
186 }
187 return Selected;
188 }
189
190 VInt FindRF(VLS_InsFormat& Format , VBool* Used)
191 {
192 VInt Selected=-1;
193 for(VInt i=0;i<4;i++)
194 {
195 switch(Format.Params[i])
196 {
197 case vipST_I:
198 if(!Used[i])
199 {
200 Selected=i;
201 Used[i]=true;
202 }
203 }
204 }
205 return Selected;
206 }
207
208 VInt FindIMM(VLS_InsFormat& Format , VBool* Used)
209 {
210 VInt Selected=-1;
211 for(VInt i=0;i<4;i++)
212 {
213 switch(Format.Params[i])
214 {
215 case vipREL_8:
216 case vipREL_16:
217 case vipREL_32:
218 case vipPTR_16_16:
219 case vipPTR_16_32:
220 case vipIMM_8:
221 case vipIMM_16:
222 case vipIMM_32:
223 if(!Used[i])
224 {
225 Selected=i;
226 Used[i]=true;
227 }
228 }
229 }
230 return Selected;
231 }
232
233 VInt RegisterToExt(VLE_AsmRegister Register)
234 {
235 switch(Register)
236 {
237 case varAL:case varAX:case varEAX:case varST0:
238 return 0;
239 case varCL:case varCX:case varECX:case varST1:
240 return 1;
241 case varDL:case varDX:case varEDX:case varST2:
242 return 2;
243 case varBL:case varBX:case varEBX:case varST3:
244 return 3;
245 case varAH:case varSP:case varESP:case varST4:
246 return 4;
247 case varCH:case varBP:case varEBP:case varST5:
248 return 5;
249 case varDH:case varSI:case varESI:case varST6:
250 return 6;
251 case varBH:case varDI:case varEDI:case varST7:
252 return 7;
253 default:
254 return -1;
255 }
256 }
257
258 VByte RegisterToID(VLE_AsmRegister Register)
259 {
260 return (VByte)RegisterToExt(Register);
261 }
262
263 const VByte SIB_Scales[]={0,1,2,3};
264 VByte ScaleToSIB(VLE_AsmScale Scale)
265 {
266 return SIB_Scales[Scale]<<6;
267 }
268
269 VByte IndexToSIB(VLE_AsmRegister Register)
270 {
271 return (VByte)RegisterToExt(Register)<<3;
272 }
273
274 VByte BaseToSIB(VLE_AsmRegister Register)
275 {
276 return (VByte)RegisterToExt(Register);
277 }
278
279 //[Mod][Ext][R/M] [Scale][Index][Base]
280 VBool MakeModRMWithoutExt(VL_AsmParameter& Parameter , VByte& ModRM , VByte& SIB , VBool& EnableSIB , VBool& Displayment)
281 {
282 if(Parameter.ParameterKind==vapkRegister)
283 {
284 ModRM=0xC0 | RegisterToID(Parameter.Register);//11000XXX
285 SIB=0;
286 EnableSIB=false;
287 Displayment=false;
288 return true;
289 }
290 else
291 {
292 VBool DispZero=Parameter.Offset==0 && !Parameter.Linking.Enabled;
293 VLE_AsmRegister Index=Parameter.Index;
294 VLE_AsmRegister Base=Parameter.Base;
295 VLE_AsmScale Scale=Parameter.Scale;
296 if(Base==varNONE && Scale==vas1)
297 {
298 Base=Index;
299 Index=varNONE;
300 }
301
302 if(Base==varNONE && Index==varNONE)//disp32
303 {
304 ModRM=0x05;//00000101
305 SIB=0;
306 EnableSIB=false;
307 Displayment=false;
308 return true;
309 }
310 if(Base!=varNONE && Index==varNONE && DispZero)//[REG]
311 {
312 VByte ID=RegisterToID(Base);
313 if(ID==4)//[ESP]
314 {
315 ModRM=0x04;//00000100
316 SIB=0x24;//00100100
317 EnableSIB=true;
318 Displayment=true;
319 return true;
320 }
321 else if(ID==5)//[EBP]
322 {
323 ModRM=0x85;//10000101
324 SIB=0;
325 EnableSIB=false;
326 Displayment=true;
327 return true;
328 }
329 else
330 {
331 ModRM=0x00 | ID;//00000XXX
332 SIB=0;
333 EnableSIB=false;
334 Displayment=false;
335 return true;
336 }
337 }
338 if(Base!=varNONE && Index==varNONE && !DispZero)//[REG + disp32]
339 {
340 VByte ID=RegisterToID(Base);
341 if(ID==4)//[ESP + disp32]
342 {
343 ModRM=0x84;//10000100
344 SIB=0x24;//00100100
345 EnableSIB=true;
346 Displayment=true;
347 return true;
348 }
349 else
350 {
351 ModRM=0x80 | ID;//10000XXX
352 SIB=0;
353 EnableSIB=false;
354 Displayment=false;
355 return true;
356 }
357 }
358 if(Base==varNONE && Index!=varNONE && DispZero)//[REG * s]
359 {
360 ModRM=0x04;//00000100
361 SIB=ScaleToSIB(Scale) | IndexToSIB(Index) | BaseToSIB(varEBP);
362 EnableSIB=true;
363 Displayment=true;
364 return true;
365 }
366 if(Base!=varNONE && Index!=varNONE && DispZero)//[REG * s + REG]
367 {
368 if(Index==varESP)
369 return false;
370 if(Base==varEBP)
371 {
372 ModRM=0x84;//10000100
373 SIB=ScaleToSIB(Scale) | IndexToSIB(Index) | BaseToSIB(Base);
374 EnableSIB=true;
375 Displayment=true;
376 return true;
377 }
378 else
379 {
380 ModRM=0x04;//00000100
381 SIB=ScaleToSIB(Scale) | IndexToSIB(Index) | BaseToSIB(Base);
382 EnableSIB=true;
383 Displayment=false;
384 return true;
385 }
386 }
387 if(Base==varNONE && Index!=varNONE && !DispZero)//[REG * s + disp32]
388 {
389 if(Index==varESP)
390 return false;
391 ModRM=0x04;//00000100
392 SIB=ScaleToSIB(Scale) | IndexToSIB(Index) | BaseToSIB(Base);
393 EnableSIB=true;
394 Displayment=true;
395 return true;
396 }
397 if(Base!=varNONE && Index!=varNONE && !DispZero)//[REG * s + REG + disp32]
398 {
399 if(Index==varESP)
400 return false;
401 ModRM=0x84;//10000100
402 SIB=ScaleToSIB(Scale) | IndexToSIB(Index) | BaseToSIB(Base);
403 EnableSIB=true;
404 Displayment=true;
405 return true;
406 }
407 return false;
408 }
409 }
410
411 #define APPEND_ERROR(ERRORCODE,MESSAGE) \
412 { \
413 VL_AsmError Error; \
414 Error.ErrorCode=ERRORCODE; \
415 Error.Index=i; \
416 Error.Message=MESSAGE; \
417 Compiled->Errors.Add(Error); \
418 /*throw Error;*/ \
419 CompileToBinaryCode=false; \
420 goto EXIT_SINGLE_INSTRUCTION_COMPILATION; \
421 }
422
423 struct LabelRef
424 {
425 VSize Position; //填补的位置
426 VSize InsBegin; //包含该位置的指令的起始地址
427 VSize InsEnd; //包含该位置的指令的结束地址
428 VInt LabelID; //标号
429 };
430
431 struct LinkingRef
432 {
433 VInt ID;
434 VInt Offset;
435 VSize Position;
436 VByte Bits; //0->8, 1->16, 2->32
437 };
438
439 VL_AsmCompiled* Compile(VL_AsmProgram* Program)
440 {
441 VL_AsmCompiled* Compiled=new VL_AsmCompiled; // 保存二进制代码的Compiled对象
442 VL_ListedMap<VInt , VSize> LabelOffsets; // LabelID -> InstructionAddress
443 VL_List<LabelRef , true> LabelReferences; // 空缺的需要填补的Label相对地址
444 VL_MultiMap<VInt , VInt , true> LabelLookups; // InstructionIndex -> LabelID
445 VBool CompileToBinaryCode=true; // 是否将二进制代码写进Compiled对象
446
447 CopyStream(&Program->ConstantBuffer,&Compiled->ConstantBuffer);
448 for(VInt i=0;i<Program->Labels.GetCount();i++)
449 {
450 LabelLookups.Add(Program->Labels[i],i);
451 }
452
453 for(VInt i=0;i<Program->Instructions.GetCount();i++)
454 {
455 VL_AsmIns& Instruction=Program->Instructions[i];
456 VL_List<VInt , true>* AssociatedLabels=0;
457 {
458 VInt Index=LabelLookups.IndexOfKey(i);
459 if(Index>-1)
460 {
461 AssociatedLabels=&LabelLookups.ValueOfIndex(Index);
462 }
463 }
464
465 VLE_InsName Name=NameToIns(Instruction.Name.Buffer());
466 if(Name==vinUNKNOWN)
467 APPEND_ERROR(vaecUnrecognizedName,L"指令名\""+Instruction.Name+L"\"无法识别。");
468 if(Instruction.ParameterCount<0||Instruction.ParameterCount>4)
469 APPEND_ERROR(vaecWrongParameterCount,L"指令的参数数量只能是0、1、2、3、4。");
470 for(VInt j=0;j<Instruction.ParameterCount;j++)
471 {
472 VL_AsmParameter& Parameter=Instruction.Parameters[j];
473 switch(Parameter.ParameterKind)
474 {
475 case vapkRegister:
476 if(Parameter.Register==varNONE)
477 {
478 APPEND_ERROR(vaecLostRegister,L"类型为寄存器的参数不可为varNONE。");
479 }
480 else if(Parameter.Register>=varAL && Parameter.Register<=varDH)
481 {
482 if(Parameter.ParameterType!=vaptInt8)
483 APPEND_ERROR(vaecWrongRegisterType,L"AL、AH、BL、BH、CL、CH、DL、DH的参数值类型必须是8位整数。");
484 }
485 else if(Parameter.Register>=varAX && Parameter.Register<=varDI)
486 {
487 if(Parameter.ParameterType!=vaptInt16)
488 APPEND_ERROR(vaecWrongRegisterType,L"AX、BX、CX、DS、SP、BP、SI、DI的参数值类型必须是16位整数。");
489 }
490 else if(Parameter.Register>=varEAX && Parameter.Register<=varEDI)
491 {
492 if(Parameter.ParameterType!=vaptInt32)
493 APPEND_ERROR(vaecWrongRegisterType,L"EAX、EBX、ECX、EDS、ESP、EBP、ESI、EDI的参数值类型必须是32位整数。");
494 }
495 else if(Parameter.Register>=varST0 && Parameter.Register<=varST7)
496 {
497 if(Parameter.ParameterType!=vaptFpReg)
498 APPEND_ERROR(vaecWrongRegisterType,L"浮点寄存器ST(i)的参数值类型必须是与位数无关的浮点数。");
499 }
500 else
501 {
502 APPEND_ERROR(vaecUnrecognizedRegister,L"未知寄存器。");
503 }
504 break;
505 case vapkPointer:
506 if(Parameter.Index!=varNONE && (Parameter.Index<varEAX || Parameter.Index>varEDI))
507 APPEND_ERROR(vaecIndexRegisterMustBe32Bits,L"Index寄存器只能是EAX、EBX、ECX、EDS、ESP、EBP、ESI、EDI。");
508 if(Parameter.Base!=varNONE && (Parameter.Base<varEAX || Parameter.Base>varEDI))
509 APPEND_ERROR(vaecBaseRegisterMustBe32Bits,L"Base寄存器只能是EAX、EBX、ECX、EDS、ESP、EBP、ESI、EDI。");
510 if(Parameter.Scale<vas1 || Parameter.Scale>vas4)
511 APPEND_ERROR(vaecUnrecognizedScale,L"Scale只能是1、2、4、8。");
512 switch(Parameter.ParameterType)
513 {
514 case vaptInt8:
515 case vaptInt16:
516 case vaptInt32:
517 case vaptFp32:
518 case vaptFp64:
519 break;
520 default:
521 APPEND_ERROR(vaecUnrecognizedType,L"指针的参数值类型只能是8位、16位、32位整数或32位、64位浮点数。");
522 }
523 break;
524 case vapkSigned:
525 switch(Parameter.ParameterType)
526 {
527 case vaptInt8:
528 if(Parameter.Linking.Enabled==false && (Parameter.Signed<-128 || Parameter.Signed>127))
529 APPEND_ERROR(vaecSignedOutOfRange,L"有符号整数\""+VUnicodeString(Parameter.Signed)+L"\"超出了8位有符号整数的描述范围。");
530 break;
531 case vaptInt16:
532 if(Parameter.Linking.Enabled==false && (Parameter.Signed<-32768 || Parameter.Signed>32767))
533 APPEND_ERROR(vaecSignedOutOfRange,L"有符号整数\""+VUnicodeString(Parameter.Signed)+L"\"超出了16位有符号整数的描述范围。");
534 break;
535 case vaptInt32:
536 break;
537 default:
538 APPEND_ERROR(vaecSignedMustBeInteger,L"有符号整数的参数值类型只能是8位、16位、32位的有符号整数。");
539 }
540 break;
541 case vapkUnsigned:
542 switch(Parameter.ParameterType)
543 {
544 case vaptInt8:
545 if(Parameter.Linking.Enabled==false && Parameter.Unsigned>255)
546 {
547 VWChar Buffer[64]={0};
548 _ui64tow(Parameter.Unsigned,Buffer,10);
549 APPEND_ERROR(vaecUnsignedOutOfRange,L"无符号整数\""+VUnicodeString(Buffer)+L"\"超出了8位无符号整数的描述范围。");
550 }
551 break;
552 case vaptInt16:
553 if(Parameter.Linking.Enabled==false && Parameter.Unsigned>65535)
554 {
555 VWChar Buffer[64]={0};
556 _ui64tow(Parameter.Unsigned,Buffer,10);
557 APPEND_ERROR(vaecUnsignedOutOfRange,L"无符号整数\""+VUnicodeString(Buffer)+L"\"超出了16位无符号整数的描述范围。");
558 }
559 break;
560 case vaptInt32:
561 break;
562 default:
563 APPEND_ERROR(vaecUnsignedMustBeInteger,L"无符号整数的参数值类型只能是8位、16位、32位的无符号整数。");
564 }
565 break;
566 case vapkRelative:
567 switch(Parameter.ParameterType)
568 {
569 case vaptInt8:
570 if(Parameter.Linking.Enabled==false && (Parameter.Signed<-128 || Parameter.Signed>127))
571 APPEND_ERROR(vaecSignedOutOfRange,L"相对地址\""+VUnicodeString(Parameter.Signed)+L"\"超出了8位有符号整数的描述范围。");
572 break;
573 case vaptInt16:
574 if(Parameter.Linking.Enabled==false && (Parameter.Signed<-32768 || Parameter.Signed>32767))
575 APPEND_ERROR(vaecSignedOutOfRange,L"相对地址\""+VUnicodeString(Parameter.Signed)+L"\"超出了16位有符号整数的描述范围。");
576 break;
577 case vaptInt32:
578 break;
579 default:
580 APPEND_ERROR(vaecRelativeMustBeInteger,L"相对地址的参数值类型只能是8位、16位、32位的有符号整数。");
581 }
582 break;
583 case vapkLabel:
584 if(Parameter.ParameterType!=vaptInt32)
585 APPEND_ERROR(vaecLabelMustBeInt32,L"标号的参数值类型必须是32位整数。");
586 if(Parameter.Label<0 || Parameter.Label>=Program->Labels.GetCount())
587 APPEND_ERROR(vaecUnrecognizedLabel,L"标号不存在。");
588 break;
589 default:
590 APPEND_ERROR(vaecUnrecognizedKind,L"参数类型只能是寄存器、指针、有符号整数、无符号整数、相对地址偏移或标号");
591 }
592 }
593
594 VInt InsMin=InsOffset[Name];
595 VInt InsMax=InsMin+InsCount[Name]-1;
596 VInt SelectedIns=-1;
597 for(VInt j=InsMin;j<=InsMax;j++)
598 {
599 VLS_InsFormat& Format=InsFormat[j];
600 VBool Failed=false;
601 for(VInt k=0;k<Instruction.ParameterCount;k++)
602 {
603 if(!CheckParameter(Format.Params[k],Instruction.Parameters[k]))
604 {
605 Failed=true;
606 break;
607 }
608 }
609 for(VInt k=Instruction.ParameterCount;k<4;k++)
610 {
611 if(Format.Params[k]!=vipNoParam)
612 {
613 Failed=true;
614 break;
615 }
616 }
617 if(!Failed)
618 {
619 SelectedIns=j;
620 break;
621 }
622 }
623 if(SelectedIns==-1)
624 APPEND_ERROR(vaecParameterNotMatched,L"没有可以用于此参数类型组合的指令。");
625
626 {
627 VBool UseModRM=false;
628 VInt ModRMIndex=-1;
629 VInt ExtRegIndex=-1;
630 VInt Ext=-1;
631 VInt PlusIndex=-1;
632 VInt ImmIndex=-1;
633 VBool Used[4]={false,false,false,false};
634 VLS_InsFormat& Format=InsFormat[SelectedIns];
635
636 if(Format.Plus==vipRegister)
637 {
638 PlusIndex=FindRI(Format,Used);
639 if(PlusIndex==-1)
640 APPEND_ERROR(vaecDoNotKnowHowToCompile,L"找不到Plus的对应参数。");
641 }
642 else if(Format.Plus==vipFloat)
643 {
644 PlusIndex=FindRF(Format,Used);
645 if(PlusIndex==-1)
646 APPEND_ERROR(vaecDoNotKnowHowToCompile,L"找不到Plus的对应参数。");
647 }
648
649 if(Format.Imm==viiNoImm)
650 {
651 ImmIndex=FindIMM(Format,Used);
652 if(ImmIndex!=-1)
653 {
654 if(Format.Params[ImmIndex]==vipCONST_1 || Format.Params[ImmIndex]==vipCONST_3)
655 {
656 ImmIndex=-1;
657 }
658 }
659 }
660 else
661 {
662 ImmIndex=FindIMM(Format,Used);
663 if(ImmIndex==-1)
664 APPEND_ERROR(vaecDoNotKnowHowToCompile,L"找不到Immediate的对应参数。");
665 }
666
667 if(Format.Ext>=vie0 && Format.Ext<=vie7)
668 {
669 UseModRM=true;
670 Ext=Format.Ext;
671 }
672 else if(Format.Ext==vieRegister)
673 {
674 UseModRM=true;
675 ExtRegIndex=FindRI(Format,Used);
676 if(ExtRegIndex==-1)
677 APPEND_ERROR(vaecDoNotKnowHowToCompile,L"找不到/r的对应参数。");
678 Ext=RegisterToExt(Instruction.Parameters[ExtRegIndex].Register);
679 }
680
681 ModRMIndex=FindRM(Format,Used);
682 if(ModRMIndex!=-1)
683 {
684 if(Format.Params[ModRMIndex]>=vipAL && Format.Params[ModRMIndex]<=vipSS)
685 {
686 ModRMIndex=-1;
687 }
688 else
689 {
690 if(!UseModRM)
691 {
692 UseModRM=true;
693 }
694 if(Ext==-1)
695 {
696 ExtRegIndex=FindRI(Format,Used);
697 if(ExtRegIndex!=-1)
698 {
699 if(Format.Params[ExtRegIndex]>=vipAL && Format.Params[ExtRegIndex]<=vipSS)
700 {
701 ExtRegIndex=-1;
702 }
703 else
704 {
705 Ext=RegisterToExt(Instruction.Parameters[ExtRegIndex].Register);
706 }
707 }
708 }
709 }
710 }
711
712 for(VInt j=0;j<Instruction.ParameterCount;j++)
713 {
714 if(!Used[j])
715 APPEND_ERROR(vaecDoNotKnowHowToCompile,L"找不到第\""+VUnicodeString(j+1)+L"\"个参数的二进制码贡献方法");
716 }
717 if(CompileToBinaryCode)
718 {
719 VSize InstructionBeginPosition=Compiled->InstructionBuffer.Position();
720 if(AssociatedLabels)
721 {
722 for(VInt j=0;j<AssociatedLabels->GetCount();j++)
723 {
724 LabelOffsets.Add((*AssociatedLabels)[j],InstructionBeginPosition);
725 }
726 }
727 if(Format.Prefix16)
728 {
729 VByte Prefix=0x66;
730 Compiled->InstructionBuffer.Write(&Prefix,sizeof(Prefix));
731 }
732 if(PlusIndex==-1)
733 {
734 Compiled->InstructionBuffer.Write((VPointer)Format.Opcode,Format.OpcodeLength);
735 }
736 else
737 {
738 Compiled->InstructionBuffer.Write((VPointer)Format.Opcode,Format.OpcodeLength-1);
739 VByte OpCode=Format.Opcode[Format.OpcodeLength-1];
740 OpCode+=(VByte)RegisterToExt(Instruction.Parameters[PlusIndex].Register);
741 Compiled->InstructionBuffer.Write(&OpCode,sizeof(OpCode));
742 }
743 if(UseModRM)
744 {
745 VByte ModRM=0;
746 VByte SIB=0;
747 VBool EnableSIB=false;
748 VBool Displayment=false;
749 VL_AsmParameter& Parameter=Instruction.Parameters[ModRMIndex];
750
751 if(MakeModRMWithoutExt(Parameter,ModRM,SIB,EnableSIB,Displayment))
752 {
753 ModRM|=(VByte)(Ext<<3);
754 Compiled->InstructionBuffer.Write(&ModRM,sizeof(ModRM));
755 if(EnableSIB)
756 {
757 Compiled->InstructionBuffer.Write(&SIB,sizeof(SIB));
758 }
759 if(Displayment)
760 {
761 VInt32s Disp32=Parameter.Offset;
762 if(Parameter.Linking.Enabled)
763 {
764 LinkingRef Ref;
765 Ref.Position=Compiled->InstructionBuffer.Position();
766 Ref.ID=Parameter.Linking.LinkingID;
767 Ref.Offset=Parameter.Linking.LinkingOffset;
768 Ref.Bits=2;
769 Compiled->LinkingBuffer.Write(&Ref,sizeof(Ref));
770 }
771 Compiled->InstructionBuffer.Write(&Disp32,sizeof(Disp32));
772 }
773 }
774 else
775 {
776 APPEND_ERROR(vaecDoNotKnowHowToCompile,L"无法将参数中的寄存器表达的指针转换成ModR/M+SIB字节。");
777 }
778 }
779 if(ImmIndex!=-1)
780 {
781 VL_AsmParameter& Parameter=Instruction.Parameters[ImmIndex];
782 VLE_AsmParameterKind Kind=Parameter.ParameterKind;
783 if(Parameter.Linking.Enabled)
784 {
785 LinkingRef Ref;
786 Ref.Position=Compiled->InstructionBuffer.Position();
787 Ref.ID=Parameter.Linking.LinkingID;
788 Ref.Offset=Parameter.Linking.LinkingOffset;
789 switch(Parameter.ParameterType)
790 {
791 case vaptInt8:
792 Ref.Bits=0;
793 break;
794 case vaptInt16:
795 Ref.Bits=1;
796 break;
797 case vaptInt32:
798 default:
799 Ref.Bits=2;
800 break;
801 }
802 Compiled->LinkingBuffer.Write(&Ref,sizeof(Ref));
803 }
804 else if(Kind==vapkLabel)
805 {
806 LabelRef Ref;
807 Ref.Position=Compiled->InstructionBuffer.Position();
808 Ref.InsBegin=InstructionBeginPosition;
809 Ref.InsEnd=Compiled->InstructionBuffer.Position()+sizeof(VInt32u);
810 Ref.LabelID=Parameter.Label;
811 LabelReferences.Add(Ref);
812 }
813 switch(Parameter.ParameterType)
814 {
815 case vaptInt8:
816 {
817 VInt8s Data=Kind==vapkSigned?(VInt8s)Parameter.Signed:(VInt8s)Parameter.Unsigned;
818 Compiled->InstructionBuffer.Write(&Data,sizeof(Data));
819 }
820 break;
821 case vaptInt16:
822 {
823 VInt16s Data=Kind==vapkSigned?(VInt16s)Parameter.Signed:(VInt16s)Parameter.Unsigned;
824 Compiled->InstructionBuffer.Write(&Data,sizeof(Data));
825 }
826 break;
827 case vaptInt32:
828 default:
829 {
830 VInt32s Data=Kind==vapkSigned?(VInt32s)Parameter.Signed:(VInt32s)Parameter.Unsigned;
831 Compiled->InstructionBuffer.Write(&Data,sizeof(Data));
832 }
833 break;
834 }
835 }
836 }
837 }
838 EXIT_SINGLE_INSTRUCTION_COMPILATION:
839 ;
840 }
841
842 if(!Compiled->Errors.GetCount())
843 {
844 for(VInt i=0;i<LabelReferences.GetCount();i++)
845 {
846 LabelRef& Ref=LabelReferences[i];
847 VSize Address=LabelOffsets[Ref.LabelID];
848 if(Address<=Ref.InsBegin)
849 {
850 Address=Address-Ref.InsEnd;
851 }
852 else if(Address>=Ref.InsEnd)
853 {
854 Address=Address-Ref.InsEnd;
855 }
856 else
857 {
858 throw "Label地址位于本指令中间,有BUG。";
859 }
860 Compiled->InstructionBuffer.SeekFromBegin(Ref.Position);
861 VInt32s Address32=(VInt32s)Address;
862 Compiled->InstructionBuffer.Write(&Address32,sizeof(Address32));
863 }
864 }
865
866 Compiled->ConstantBuffer.SeekFromBegin(0);
867 Compiled->InstructionBuffer.SeekFromBegin(0);
868 Compiled->LinkingBuffer.SeekFromBegin(0);
869 return Compiled;
870 }
871
872 #undef APPEND_ERROR
873
874 }
875 }
876 }
在if(SelectedIns==-1) APPEND_ERROR(vaecParameterNotMatched,L"没有可以用于此参数类型组合的指令。");这句下面的APPEND_ERROR大部分是为了调试写的,基本上如果促触发了DoNotKnowHowToCompile错误的话,9成都是这个汇编器有BUG。
汇编器的核心部分顺利完成。接下来的工作是写一个汇编语言的编译器,以便手写大量test case进行自动测试。
posted on 2009-02-22 07:08
陈梓瀚(vczh) 阅读(4931)
评论(11) 编辑 收藏 引用 所属分类:
JIT