PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/olly_dll/assembl.c

https://github.com/davislg/iDBG
C | 1412 lines | 1293 code | 22 blank | 97 comment | 779 complexity | d3ea264204f2b14e2a18c89f1dcfc48d MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. // Free Disassembler and Assembler -- Assembler
  2. //
  3. // Copyright (C) 2001 Oleh Yuschuk
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. // 16.01.2002 - corrected error in processing of immediate constants.
  19. #define STRICT
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. //#include <dir.h>
  25. #include <math.h>
  26. #include <float.h>
  27. #pragma hdrstop
  28. #include "disasm.h"
  29. ////////////////////////////////////////////////////////////////////////////////
  30. ///////////////////////////// ASSEMBLER FUNCTIONS //////////////////////////////
  31. // Scanner modes.
  32. #define SA_NAME 0x0001 // Don't try to decode labels
  33. #define SA_IMPORT 0x0002 // Allow import pseudolabel
  34. // Types of input tokens reported by scanner.
  35. #define SCAN_EOL 0 // End of line
  36. #define SCAN_REG8 1 // 8-bit register
  37. #define SCAN_REG16 2 // 16-bit register
  38. #define SCAN_REG32 3 // 32-bit register
  39. #define SCAN_SEG 4 // Segment register
  40. #define SCAN_FPU 5 // FPU register
  41. #define SCAN_MMX 6 // MMX register
  42. #define SCAN_CR 7 // Control register
  43. #define SCAN_DR 8 // Debug register
  44. #define SCAN_OPSIZE 9 // Operand size modifier
  45. #define SCAN_JMPSIZE 10 // Jump size modifier
  46. #define SCAN_LOCAL 11 // Address on stack in form LOCAL.decimal
  47. #define SCAN_ARG 12 // Address on stack in form ARG.decimal
  48. #define SCAN_PTR 20 // PTR in MASM addressing statements
  49. #define SCAN_REP 21 // REP prefix
  50. #define SCAN_REPE 22 // REPE prefix
  51. #define SCAN_REPNE 23 // REPNE prefix
  52. #define SCAN_LOCK 24 // LOCK prefix
  53. #define SCAN_NAME 25 // Command or label
  54. #define SCAN_ICONST 26 // Hexadecimal constant
  55. #define SCAN_DCONST 27 // Decimal constant
  56. #define SCAN_OFS 28 // Undefined constant
  57. #define SCAN_FCONST 29 // Floating-point constant
  58. #define SCAN_EIP 30 // Register EIP
  59. #define SCAN_SIGNED 31 // Keyword "SIGNED" (in expressions)
  60. #define SCAN_UNSIGNED 32 // Keyword "UNSIGNED" (in expressions)
  61. #define SCAN_CHAR 33 // Keyword "CHAR" (in expressions)
  62. #define SCAN_FLOAT 34 // Keyword "FLOAT" (in expressions)
  63. #define SCAN_DOUBLE 35 // Keyword "DOUBLE" (in expressions)
  64. #define SCAN_FLOAT10 36 // Keyword "FLOAT10" (in expressions)
  65. #define SCAN_STRING 37 // Keyword "STRING" (in expressions)
  66. #define SCAN_UNICODE 38 // Keyword "UNICODE" (in expressions)
  67. #define SCAN_MSG 39 // Pseudovariable MSG (in expressions)
  68. #define SCAN_SYMB 64 // Any other character
  69. #define SCAN_IMPORT 65 // Import pseudolabel
  70. #define SCAN_ERR 255 // Definitely bad item
  71. // Definition used by Assembler to report command matching errors.
  72. #define MA_JMP 0x0001 // Invalid jump size modifier
  73. #define MA_NOP 0x0002 // Wrong number of operands
  74. #define MA_TYP 0x0004 // Bad operand type
  75. #define MA_NOS 0x0008 // Explicit operand size expected
  76. #define MA_SIZ 0x0010 // Bad operand size
  77. #define MA_DIF 0x0020 // Different operand sizes
  78. #define MA_SEG 0x0040 // Invalid segment register
  79. #define MA_RNG 0x0080 // Constant out of expected range
  80. typedef struct t_asmoperand {
  81. int type; // Operand type, see beginning of file
  82. int size; // Operand size or 0 if yet unknown
  83. int index; // Index or other register
  84. int scale; // Scale
  85. int base; // Base register if present
  86. long offset; // Immediate value or offset
  87. int anyoffset; // Offset is present but undefined
  88. int segment; // Segment in address if present
  89. int jmpmode; // Specified jump size
  90. } t_asmoperand;
  91. static char *asmcmd; // Pointer to 0-terminated source line
  92. static int scan; // Type of last scanned element
  93. static int prio; // Priority of operation (0: highest)
  94. static char sdata[TEXTLEN]; // Last scanned name (depends on type)
  95. static long idata; // Last scanned value
  96. static long double fdata; // Floating-point number
  97. static char *asmerror; // Explanation of last error, or NULL
  98. // Simple and slightly recursive scanner shared by Assemble(). The scanner is
  99. // straightforward and ineffective, but high speed is not a must here. As
  100. // input, it uses global pointer to source line asmcmd. On exit, it fills in
  101. // global variables scan, prio, sdata, idata and/or fdata. If some error is
  102. // detected, asmerror points to error message, otherwise asmerror remains
  103. // unchanged.
  104. static void Scanasm(int mode) {
  105. int i,j,base,maxdigit;
  106. long decimal,hex;
  107. long double floating,divisor;
  108. char s[TEXTLEN],*pcmd;
  109. sdata[0]='\0';
  110. idata=0;
  111. if (asmcmd==NULL) {
  112. asmerror="NULL input line"; scan=SCAN_ERR; return; };
  113. while (*asmcmd==' ' || *asmcmd=='\t')
  114. asmcmd++; // Skip leading spaces
  115. if (*asmcmd=='\0' || *asmcmd==';') {
  116. scan=SCAN_EOL; return; }; // Empty line
  117. if (isalpha(*asmcmd) || *asmcmd=='_' || *asmcmd=='@') {
  118. sdata[0]=*asmcmd++; i=1; // Some keyword or identifier
  119. while ((isalnum(*asmcmd) || *asmcmd=='_' || *asmcmd=='@') &&
  120. i<sizeof(sdata))
  121. sdata[i++]=*asmcmd++;
  122. if (i>=sizeof(sdata)) {
  123. asmerror="Too long identifier"; scan=SCAN_ERR; return; };
  124. sdata[i]='\0';
  125. while (*asmcmd==' ' || *asmcmd=='\t')
  126. asmcmd++; // Skip trailing spaces
  127. strcpy(s,sdata); strupr(s);
  128. for (j=0; j<=8; j++) { // j==8 means "any register"
  129. if (strcmp(s,regname[0][j])!=0) continue;
  130. idata=j; scan=SCAN_REG8; // 8-bit register
  131. return; };
  132. for (j=0; j<=8; j++) {
  133. if (strcmp(s,regname[1][j])!=0) continue;
  134. idata=j; scan=SCAN_REG16; // 16-bit register
  135. return; };
  136. for (j=0; j<=8; j++) {
  137. if (strcmp(s,regname[2][j])!=0) continue;
  138. idata=j; scan=SCAN_REG32; // 32-bit register
  139. return; };
  140. for (j=0; j<6; j++) {
  141. if (strcmp(s,segname[j])!=0) continue;
  142. idata=j; scan=SCAN_SEG; // Segment register
  143. while (*asmcmd==' ' || *asmcmd=='\t')
  144. asmcmd++; // Skip trailing spaces
  145. return; };
  146. if (strcmp(s,"ST")==0) {
  147. pcmd=asmcmd; Scanasm(SA_NAME); // FPU register
  148. if (scan!=SCAN_SYMB || idata!='(') {
  149. asmcmd=pcmd; // Undo last scan
  150. idata=0; scan=SCAN_FPU; return; };
  151. Scanasm(SA_NAME); j=idata;
  152. if ((scan!=SCAN_ICONST && scan!=SCAN_DCONST) || idata<0 || idata>7) {
  153. asmerror="FPU registers have indexes 0 to 7";
  154. scan=SCAN_ERR; return; };
  155. Scanasm(SA_NAME);
  156. if (scan!=SCAN_SYMB || idata!=')') {
  157. asmerror="Closing parenthesis expected";
  158. scan=SCAN_ERR; return; };
  159. idata=j; scan=SCAN_FPU; return; };
  160. for (j=0; j<=8; j++) {
  161. if (strcmp(s,fpuname[j])!=0) continue;
  162. idata=j; scan=SCAN_FPU; // FPU register (alternative coding)
  163. return; };
  164. for (j=0; j<=8; j++) {
  165. if (strcmp(s,mmxname[j])!=0) continue;
  166. idata=j; scan=SCAN_MMX; // MMX register
  167. return; };
  168. for (j=0; j<=8; j++) {
  169. if (strcmp(s,crname[j])!=0) continue;
  170. idata=j; scan=SCAN_CR; // Control register
  171. return; };
  172. for (j=0; j<=8; j++) {
  173. if (strcmp(s,drname[j])!=0) continue;
  174. idata=j; scan=SCAN_DR; // Debug register
  175. return; };
  176. for (j=0; j<sizeof(sizename)/sizeof(sizename[0]); j++) {
  177. if (strcmp(s,sizename[j])!=0) continue;
  178. pcmd=asmcmd; Scanasm(SA_NAME);
  179. if (scan!=SCAN_PTR) // Fetch non-functional "PTR"
  180. asmcmd=pcmd;
  181. idata=j; scan=SCAN_OPSIZE; // Operand (data) size in bytes
  182. return; };
  183. if (strcmp(s,"EIP")==0) { // Register EIP
  184. scan=SCAN_EIP; idata=0; return; };
  185. if (strcmp(s,"SHORT")==0) { // Relative jump has 1-byte offset
  186. scan=SCAN_JMPSIZE; idata=1; return; };
  187. if (strcmp(s,"LONG")==0) { // Relative jump has 4-byte offset
  188. scan=SCAN_JMPSIZE; idata=2; return; };
  189. if (strcmp(s,"NEAR")==0) { // Jump within same code segment
  190. scan=SCAN_JMPSIZE; idata=4; return; };
  191. if (strcmp(s,"FAR")==0) { // Jump to different code segment
  192. scan=SCAN_JMPSIZE; idata=8; return; };
  193. if (strcmp(s,"LOCAL")==0 && *asmcmd=='.') {
  194. asmcmd++;
  195. while (*asmcmd==' ' || *asmcmd=='\t')
  196. asmcmd++; // Skip trailing spaces
  197. if (!isdigit(*asmcmd)) {
  198. asmerror="Integer number expected";
  199. scan=SCAN_ERR; return; };
  200. while (isdigit(*asmcmd)) // LOCAL index is decimal number!
  201. idata=idata*10+(*asmcmd++)-'0';
  202. scan=SCAN_LOCAL; return; };
  203. if (strcmp(s,"ARG")==0 && *asmcmd=='.') {
  204. asmcmd++;
  205. while (*asmcmd==' ' || *asmcmd=='\t')
  206. asmcmd++; // Skip trailing spaces
  207. if (!isdigit(*asmcmd)) {
  208. asmerror="Integer number expected";
  209. scan=SCAN_ERR; return; };
  210. while (isdigit(*asmcmd)) // ARG index is decimal number!
  211. idata=idata*10+(*asmcmd++)-'0';
  212. scan=SCAN_ARG; return; };
  213. if (strcmp(s,"REP")==0) {
  214. scan=SCAN_REP; return; }; // REP prefix
  215. if (strcmp(s,"REPE")==0 || strcmp(s,"REPZ")==0) {
  216. scan=SCAN_REPE; return; }; // REPE prefix
  217. if (strcmp(s,"REPNE")==0 || strcmp(s,"REPNZ")==0) {
  218. scan=SCAN_REPNE; return; }; // REPNE prefix
  219. if (strcmp(s,"LOCK")==0) {
  220. scan=SCAN_LOCK; return; }; // LOCK prefix
  221. if (strcmp(s,"PTR")==0) {
  222. scan=SCAN_PTR; return; }; // PTR in MASM addressing statements
  223. if (strcmp(s,"CONST")==0 || strcmp(s,"OFFSET")==0) {
  224. scan=SCAN_OFS; return; }; // Present but undefined offset/constant
  225. if (strcmp(s,"SIGNED")==0) {
  226. scan=SCAN_SIGNED; return; }; // Keyword "SIGNED" (in expressions)
  227. if (strcmp(s,"UNSIGNED")==0) {
  228. scan=SCAN_UNSIGNED; return; }; // Keyword "UNSIGNED" (in expressions)
  229. if (strcmp(s,"CHAR")==0) {
  230. scan=SCAN_CHAR; return; }; // Keyword "CHAR" (in expressions)
  231. if (strcmp(s,"FLOAT")==0) {
  232. scan=SCAN_FLOAT; return; }; // Keyword "FLOAT" (in expressions)
  233. if (strcmp(s,"DOUBLE")==0) {
  234. scan=SCAN_DOUBLE; return; }; // Keyword "DOUBLE" (in expressions)
  235. if (strcmp(s,"FLOAT10")==0) {
  236. scan=SCAN_FLOAT10; return; }; // Keyword "FLOAT10" (in expressions)
  237. if (strcmp(s,"STRING")==0) {
  238. scan=SCAN_STRING; return; }; // Keyword "STRING" (in expressions)
  239. if (strcmp(s,"UNICODE")==0) {
  240. scan=SCAN_UNICODE; return; }; // Keyword "UNICODE" (in expressions)
  241. if (strcmp(s,"MSG")==0) {
  242. scan=SCAN_MSG; return; }; // Pseudovariable MSG (in expressions)
  243. if (mode & SA_NAME) {
  244. idata=i; scan=SCAN_NAME; // Don't try to decode symbolic label
  245. return; }
  246. asmerror="Unknown identifier";
  247. scan=SCAN_ERR; return; }
  248. else if (isdigit(*asmcmd)) { // Constant
  249. base=0; maxdigit=0; decimal=hex=0L; floating=0.0;
  250. if (asmcmd[0]=='0' && toupper(asmcmd[1])=='X') {
  251. base=16; asmcmd+=2; }; // Force hexadecimal number
  252. while (1) {
  253. if (isdigit(*asmcmd)) {
  254. decimal=decimal*10+(*asmcmd)-'0';
  255. floating=floating*10.0+(*asmcmd)-'0';
  256. hex=hex*16+(*asmcmd)-'0';
  257. if (maxdigit==0) maxdigit=9;
  258. asmcmd++; }
  259. else if (isxdigit(*asmcmd)) {
  260. hex=hex*16+toupper(*asmcmd++)-'A'+10;
  261. maxdigit=15; }
  262. else break; };
  263. if (maxdigit==0) {
  264. asmerror="Hexadecimal digits after 0x... expected";
  265. scan=SCAN_ERR; return; };
  266. if (toupper(*asmcmd)=='H') { // Force hexadecimal number
  267. if (base==16) {
  268. asmerror="Please don't mix 0xXXXX and XXXXh forms";
  269. scan=SCAN_ERR; return; };
  270. asmcmd++;
  271. idata=hex; scan=SCAN_ICONST;
  272. while (*asmcmd==' ' || *asmcmd=='\t') asmcmd++;
  273. return; };
  274. if (*asmcmd=='.') { // Force decimal number
  275. if (base==16 || maxdigit>9) {
  276. asmerror="Not a decimal number"; scan=SCAN_ERR; return; };
  277. asmcmd++;
  278. if (isdigit(*asmcmd) || toupper(*asmcmd)=='E') {
  279. divisor=1.0;
  280. while (isdigit(*asmcmd)) { // Floating-point number
  281. divisor/=10.0;
  282. floating+=divisor*(*asmcmd-'0');
  283. asmcmd++; };
  284. if (toupper(*asmcmd)=='E') {
  285. asmcmd++;
  286. if (*asmcmd=='-') { base=-1; asmcmd++; }
  287. else base=1;
  288. if (!isdigit(*asmcmd)) {
  289. asmerror="Invalid exponent"; scan=SCAN_ERR; return; };
  290. decimal=0;
  291. while (isdigit(*asmcmd)) {
  292. if (decimal<65536L) decimal=decimal*10+(*asmcmd++)-'0'; };
  293. floating*=powl(decimal*base,10); };
  294. fdata=floating;
  295. scan=SCAN_FCONST; return; }
  296. else {
  297. idata=decimal; scan=SCAN_DCONST;
  298. while (*asmcmd==' ' || *asmcmd=='\t') asmcmd++;
  299. return;
  300. };
  301. };
  302. idata=hex; scan=SCAN_ICONST; // Default is hexadecimal
  303. while (*asmcmd==' ' || *asmcmd=='\t') asmcmd++;
  304. return; }
  305. else if (*asmcmd=='\'') { // Character constant
  306. asmcmd++;
  307. if (*asmcmd=='\0' || (*asmcmd=='\\' && asmcmd[1]=='\0')) {
  308. asmerror="Unterminated character constant"; scan=SCAN_ERR; return; };
  309. if (*asmcmd=='\'') {
  310. asmerror="Empty character constant"; scan=SCAN_ERR; return; };
  311. if (*asmcmd=='\\') asmcmd++;
  312. idata=*asmcmd++;
  313. if (*asmcmd!='\'') {
  314. asmerror="Unterminated character constant"; scan=SCAN_ERR; return; };
  315. asmcmd++;
  316. while (*asmcmd==' ' || *asmcmd=='\t') asmcmd++;
  317. scan=SCAN_ICONST; return; }
  318. else { // Any other character or combination
  319. idata=sdata[0]=*asmcmd++; sdata[1]=sdata[2]='\0';
  320. if (idata=='|' && *asmcmd=='|') {
  321. idata='||'; prio=10; // '||'
  322. sdata[1]=*asmcmd++; }
  323. else if (idata=='&' && *asmcmd=='&') {
  324. idata='&&'; prio=9; // '&&'
  325. sdata[1]=*asmcmd++; }
  326. else if (idata=='=' && *asmcmd=='=') {
  327. idata='=='; prio=5; // '=='
  328. sdata[1]=*asmcmd++; }
  329. else if (idata=='!' && *asmcmd=='=') {
  330. idata='!='; prio=5; // '!='
  331. sdata[1]=*asmcmd++; }
  332. else if (idata=='<' && *asmcmd=='=') {
  333. idata='<='; prio=4; // '<='
  334. sdata[1]=*asmcmd++; }
  335. else if (idata=='>' && *asmcmd=='=') {
  336. idata='>='; prio=4; // '>='
  337. sdata[1]=*asmcmd++; }
  338. else if (idata=='<' && *asmcmd=='<') {
  339. idata='<<'; prio=3; // '<<'
  340. sdata[1]=*asmcmd++; }
  341. else if (idata=='>' && *asmcmd=='>') {
  342. idata='>>'; prio=3; // '>>'
  343. sdata[1]=*asmcmd++; }
  344. else if (idata=='|') prio=8; // '|'
  345. else if (idata=='^') prio=7; // '^'
  346. else if (idata=='&') prio=6; // '&'
  347. else if (idata=='<') {
  348. if (*asmcmd=='&') { // Import pseudolabel (for internal use)
  349. if ((mode & SA_IMPORT)==0) {
  350. asmerror="Syntax error"; scan=SCAN_ERR; return; };
  351. asmcmd++; i=0;
  352. while (*asmcmd!='\0' && *asmcmd!='>') {
  353. sdata[i++]=*asmcmd++;
  354. if (i>=sizeof(sdata)) {
  355. asmerror="Too long import name"; scan=SCAN_ERR; return;
  356. };
  357. };
  358. if (*asmcmd!='>') {
  359. asmerror="Unterminated import name"; scan=SCAN_ERR; return; };
  360. asmcmd++; sdata[i]='\0';
  361. scan=SCAN_IMPORT; return; }
  362. else prio=4; } // '<'
  363. else if (idata=='>') prio=4; // '>'
  364. else if (idata=='+') prio=2; // '+'
  365. else if (idata=='-') prio=2; // '-'
  366. else if (idata=='*') prio=1; // '*'
  367. else if (idata=='/') prio=1; // '/'
  368. else if (idata=='%') prio=1; // '%'
  369. else if (idata==']') {
  370. pcmd=asmcmd; Scanasm(SA_NAME);
  371. if (scan!=SCAN_SYMB || idata!='[') {
  372. idata=']'; asmcmd=pcmd; prio=0; }
  373. else {
  374. idata='+'; prio=2; // Translate '][' to '+'
  375. };
  376. }
  377. else prio=0; // Any other character
  378. scan=SCAN_SYMB;
  379. return;
  380. };
  381. };
  382. // Fetches one complete operand from the input line and fills in structure op
  383. // with operand's data. Expects that first token of the operand is already
  384. // scanned. Supports operands in generalized form (for example, R32 means any
  385. // of general-purpose 32-bit integer registers).
  386. static void Parseasmoperand(t_asmoperand *op) {
  387. int i,j,bracket,sign,xlataddr;
  388. int reg,r[9];
  389. long offset;
  390. if (scan==SCAN_EOL || scan==SCAN_ERR)
  391. return; // No or bad operand
  392. // Jump or call address may begin with address size modifier(s) SHORT, LONG,
  393. // NEAR and/or FAR. Not all combinations are allowed. After operand is
  394. // completely parsed, this function roughly checks whether modifier is
  395. // allowed. Exact check is done in Assemble().
  396. if (scan==SCAN_JMPSIZE) {
  397. j=0;
  398. while (scan==SCAN_JMPSIZE) {
  399. j|=idata; // Fetch all size modifiers
  400. Scanasm(0); };
  401. if (
  402. ((j & 0x03)==0x03) || // Mixed SHORT and LONG
  403. ((j & 0x0C)==0x0C) || // Mixed NEAR and FAR
  404. ((j & 0x09)==0x09) // Mixed FAR and SHORT
  405. ) {
  406. asmerror="Invalid combination of jump address modifiers";
  407. scan=SCAN_ERR; return; };
  408. if ((j & 0x08)==0) j|=0x04; // Force NEAR if not FAR
  409. op->jmpmode=j; };
  410. // Simple operands are either register or constant, their processing is
  411. // obvious and straightforward.
  412. if (scan==SCAN_REG8 || scan==SCAN_REG16 || scan==SCAN_REG32) {
  413. op->type=REG; op->index=idata; // Integer general-purpose register
  414. if (scan==SCAN_REG8) op->size=1;
  415. else if (scan==SCAN_REG16) op->size=2;
  416. else op->size=4; }
  417. else if (scan==SCAN_FPU) { // FPU register
  418. op->type=RST; op->index=idata; }
  419. else if (scan==SCAN_MMX) { // MMX or 3DNow! register
  420. op->type=RMX; op->index=idata; }
  421. else if (scan==SCAN_CR) { // Control register
  422. op->type=CRX; op->index=idata; }
  423. else if (scan==SCAN_DR) { // Debug register
  424. op->type=DRX; op->index=idata; }
  425. else if (scan==SCAN_SYMB && idata=='-') {
  426. Scanasm(0); // Negative constant
  427. if (scan!=SCAN_ICONST && scan!=SCAN_DCONST && scan!=SCAN_OFS) {
  428. asmerror="Integer number expected";
  429. scan=SCAN_ERR; return; };
  430. op->type=IMM; op->offset=-idata;
  431. if (scan==SCAN_OFS) op->anyoffset=1; }
  432. else if (scan==SCAN_SYMB && idata=='+') {
  433. Scanasm(0); // Positive constant
  434. if (scan!=SCAN_ICONST && scan!=SCAN_DCONST && scan!=SCAN_OFS) {
  435. asmerror="Integer number expected";
  436. scan=SCAN_ERR; return; };
  437. op->type=IMM; op->offset=idata;
  438. if (scan==SCAN_OFS) op->anyoffset=1; }
  439. else if (scan==SCAN_ICONST || scan==SCAN_DCONST || scan==SCAN_OFS) {
  440. j=idata;
  441. if (scan==SCAN_OFS) op->anyoffset=1;
  442. Scanasm(0);
  443. if (scan==SCAN_SYMB && idata==':') {
  444. Scanasm(0); // Absolute long address (seg:offset)
  445. if (scan!=SCAN_ICONST && scan!=SCAN_DCONST && scan!=SCAN_OFS) {
  446. asmerror="Integer address expected";
  447. scan=SCAN_ERR; return; };
  448. op->type=JMF; op->offset=idata; op->segment=j;
  449. if (scan==SCAN_OFS) op->anyoffset=1; }
  450. else {
  451. op->type=IMM; op->offset=j; // Constant without sign
  452. return; // Next token already scanned
  453. }; }
  454. else if (scan==SCAN_FCONST) {
  455. asmerror="Floating-point numbers are not allowed in command";
  456. scan=SCAN_ERR; return; }
  457. // Segment register or address.
  458. else if (scan==SCAN_SEG || scan==SCAN_OPSIZE ||
  459. (scan==SCAN_SYMB && idata=='[')
  460. ) { // Segment register or address
  461. bracket=0;
  462. if (scan==SCAN_SEG) {
  463. j=idata; Scanasm(0);
  464. if (scan!=SCAN_SYMB || idata!=':') {
  465. op->type=SGM; op->index=j; // Segment register as operand
  466. return; }; // Next token already scanned
  467. op->segment=j; Scanasm(0); };
  468. // Scan 32-bit address. This parser does not support 16-bit addresses.
  469. // First of all, get size of operand (optional), segment register (optional)
  470. // and opening bracket (required).
  471. while (1) {
  472. if (scan==SCAN_SYMB && idata=='[') {
  473. if (bracket) { // Bracket
  474. asmerror="Only one opening bracket allowed";
  475. scan=SCAN_ERR; return; };
  476. bracket=1; }
  477. else if (scan==SCAN_OPSIZE) {
  478. if (op->size!=0) { // Size of operand
  479. asmerror="Duplicated size modifier";
  480. scan=SCAN_ERR; return; };
  481. op->size=idata; }
  482. else if (scan==SCAN_SEG) {
  483. if (op->segment!=SEG_UNDEF) { // Segment register
  484. asmerror="Duplicated segment register";
  485. scan=SCAN_ERR; return; };
  486. op->segment=idata; Scanasm(0);
  487. if (scan!=SCAN_SYMB || idata!=':') {
  488. asmerror="Semicolon expected";
  489. scan=SCAN_ERR; return;
  490. }; }
  491. else if (scan==SCAN_ERR)
  492. return;
  493. else break; // None of expected address elements
  494. Scanasm(0); };
  495. if (bracket==0) {
  496. asmerror="Address expression requires brackets";
  497. scan=SCAN_ERR; return; };
  498. // Assembling a 32-bit address may be a kind of nigthmare, due to a large
  499. // number of allowed forms. Parser collects immediate offset in op->offset
  500. // and count for each register in array r[]. Then it decides whether this
  501. // combination is valid and determines scale, index and base. Assemble()
  502. // will use these numbers to select address form (with or without SIB byte,
  503. // 8- or 32-bit offset, use segment prefix or not). As a useful side effect
  504. // of this technique, one may specify, for example, [EAX*5] which will
  505. // correctly assemble to [EAX*4+EAX].
  506. for (i=0; i<=8; i++) r[i]=0;
  507. sign='+'; // Default sign for the first operand
  508. xlataddr=0;
  509. while (1) { // Get SIB and offset
  510. if (scan==SCAN_SYMB && (idata=='+' || idata=='-')) {
  511. sign=idata; Scanasm(0); };
  512. if (scan==SCAN_ERR) return;
  513. if (sign=='?') {
  514. asmerror="Syntax error"; scan=SCAN_ERR; return; };
  515. // Register AL appears as part of operand of (seldom used) command XLAT.
  516. if (scan==SCAN_REG8 && idata==REG_EAX) {
  517. if (sign=='-') {
  518. asmerror="Unable to subtract register"; scan=SCAN_ERR; return; };
  519. if (xlataddr!=0) {
  520. asmerror="Too many registers"; scan=SCAN_ERR; return; };
  521. xlataddr=1;
  522. Scanasm(0); }
  523. else if (scan==SCAN_REG16) {
  524. asmerror="Sorry, 16-bit addressing is not supported";
  525. scan=SCAN_ERR; return; }
  526. else if (scan==SCAN_REG32) {
  527. if (sign=='-') {
  528. asmerror="Unable to subtract register"; scan=SCAN_ERR; return; };
  529. reg=idata; Scanasm(0);
  530. if (scan==SCAN_SYMB && idata=='*') {
  531. Scanasm(0); // Try index*scale
  532. if (scan==SCAN_ERR) return;
  533. if (scan==SCAN_OFS) {
  534. asmerror="Undefined scale is not allowed"; scan=SCAN_ERR; return; };
  535. if (scan!=SCAN_ICONST && scan!=SCAN_DCONST) {
  536. asmerror="Syntax error"; scan=SCAN_ERR; return; };
  537. if (idata==6 || idata==7 || idata>9) {
  538. asmerror="Invalid scale"; scan=SCAN_ERR; return; };
  539. r[reg]+=idata;
  540. Scanasm(0); }
  541. else r[reg]++; } // Simple register
  542. else if (scan==SCAN_LOCAL) {
  543. r[REG_EBP]++;
  544. op->offset-=idata*4;
  545. Scanasm(0); }
  546. else if (scan==SCAN_ARG) {
  547. r[REG_EBP]++;
  548. op->offset+=(idata+1)*4;
  549. Scanasm(0); }
  550. else if (scan==SCAN_ICONST || scan==SCAN_DCONST) {
  551. offset=idata; Scanasm(0);
  552. if (scan==SCAN_SYMB && idata=='*') {
  553. Scanasm(0); // Try scale*index
  554. if (scan==SCAN_ERR) return;
  555. if (sign=='-') {
  556. asmerror="Unable to subtract register"; scan=SCAN_ERR; return; };
  557. if (scan==SCAN_REG16) {
  558. asmerror="Sorry, 16-bit addressing is not supported";
  559. scan=SCAN_ERR; return; };
  560. if (scan!=SCAN_REG32) {
  561. asmerror="Syntax error"; scan=SCAN_ERR; return; };
  562. if (offset==6 || offset==7 || offset>9) {
  563. asmerror="Invalid scale"; scan=SCAN_ERR; return; };
  564. r[idata]+=offset;
  565. Scanasm(0); }
  566. else {
  567. if (sign=='-') op->offset-=offset;
  568. else op->offset+=offset;
  569. }; }
  570. else if (scan==SCAN_OFS) {
  571. Scanasm(0);
  572. if (scan==SCAN_SYMB && idata=='*') {
  573. asmerror="Undefined scale is not allowed"; scan=SCAN_ERR; return; }
  574. else {
  575. op->anyoffset=1;
  576. }; }
  577. else break; // None of expected address elements
  578. if (scan==SCAN_SYMB && idata==']') break;
  579. sign='?';
  580. };
  581. if (scan==SCAN_ERR) return;
  582. if (scan!=SCAN_SYMB || idata!=']') {
  583. asmerror="Syntax error";
  584. scan=SCAN_ERR; return; };
  585. // Process XLAT address separately.
  586. if (xlataddr!=0) { // XLAT address in form [EBX+AX]
  587. for (i=0; i<=8; i++) { // Check which registers used
  588. if (i==REG_EBX) continue;
  589. if (r[i]!=0) break; };
  590. if (i<=8 || r[REG_EBX]!=1 || op->offset!=0 || op->anyoffset!=0) {
  591. asmerror="Invalid address"; scan=SCAN_ERR; return; };
  592. op->type=MXL; }
  593. // Determine scale, index and base.
  594. else {
  595. j=0; // Number of used registers
  596. for (i=0; i<=8; i++) {
  597. if (r[i]==0)
  598. continue; // Unused register
  599. if (r[i]==3 || r[i]==5 || r[i]==9) {
  600. if (op->index>=0 || op->base>=0) {
  601. if (j==0) asmerror="Invalid scale";
  602. else asmerror="Too many registers";
  603. scan=SCAN_ERR; return; };
  604. op->index=op->base=i;
  605. op->scale=r[i]-1; }
  606. else if (r[i]==2 || r[i]==4 || r[i]==8) {
  607. if (op->index>=0) {
  608. if (j<=1) asmerror="Only one register may be scaled";
  609. else asmerror="Too many registers";
  610. scan=SCAN_ERR; return; };
  611. op->index=i; op->scale=r[i]; }
  612. else if (r[i]==1) {
  613. if (op->base<0)
  614. op->base=i;
  615. else if (op->index<0) {
  616. op->index=i; op->scale=1; }
  617. else {
  618. asmerror="Too many registers";
  619. scan=SCAN_ERR; return;
  620. }; }
  621. else {
  622. asmerror="Invalid scale"; scan=SCAN_ERR; return; };
  623. j++;
  624. };
  625. op->type=MRG;
  626. }; }
  627. else {
  628. asmerror="Unrecognized operand"; scan=SCAN_ERR; return; };
  629. // In general, address modifier is allowed only with address expression which
  630. // is a constant, a far address or a memory expression. More precise check
  631. // will be done later in Assemble().
  632. if (op->jmpmode!=0 && op->type!=IMM && op->type!=JMF && op->type!=MRG) {
  633. asmerror="Jump address modifier is not allowed";
  634. scan=SCAN_ERR; return; };
  635. Scanasm(0); // Fetch next token from input line
  636. };
  637. // Function assembles text into 32-bit 80x86 machine code. It supports imprecise
  638. // operands (for example, R32 stays for any general-purpose 32-bit register).
  639. // This allows to search for incomplete commands. Command is precise when all
  640. // significant bytes in model.mask are 0xFF. Some commands have more than one
  641. // decoding. By calling Assemble() with attempt=0,1... and constsize=0,1,2,3 one
  642. // gets also alternative variants (bit 0x1 of constsize is responsible for size
  643. // of address constant and bit 0x2 - for immediate data). However, only one
  644. // address form is generated ([EAX*2], but not [EAX+EAX]; [EBX+EAX] but not
  645. // [EAX+EBX]; [EAX] will not use SIB byte; no DS: prefix and so on). Returns
  646. // number of bytes in assembled code or non-positive number in case of detected
  647. // error. This number is the negation of the offset in the input text where the
  648. // error encountered. Unfortunately, BC 4.52 is unable to compile the switch
  649. // (arg) in this code when any common subexpression optimization is on. The
  650. // next #pragma statement disables all optimizations.
  651. //#pragma option -Od // No optimizations, or BC 4.52 crashes
  652. int __stdcall Assemble(char *cmd,ulong ip,t_asmmodel *model,int attempt, int constsize,char *errtext)
  653. {
  654. int i,j,k,namelen,nameok,arg,match,datasize,addrsize,bytesize,minop,maxop;
  655. int rep,lock,segment,jmpsize,jmpmode,longjump;
  656. int hasrm,hassib,dispsize,immsize;
  657. int anydisp,anyimm,anyjmp;
  658. long l,displacement,immediate,jmpoffset;
  659. char name[32],*nameend;
  660. char tcode[MAXCMDSIZE],tmask[MAXCMDSIZE];
  661. t_asmoperand aop[3],*op; // Up to 3 operands allowed
  662. const t_cmddata *pd;
  663. if (model!=NULL) model->length=0;
  664. if (cmd==NULL || model==NULL || errtext==NULL) {
  665. if (errtext!=NULL) strcpy(errtext,"Internal OLLYDBG error");
  666. return 0; }; // Error in parameters
  667. asmcmd=cmd;
  668. rep=lock=0; errtext[0]='\0';
  669. Scanasm(SA_NAME);
  670. if (scan==SCAN_EOL) // End of line, nothing to assemble
  671. return 0;
  672. while (1) { // Fetch all REPxx and LOCK prefixes
  673. if (scan==SCAN_REP || scan==SCAN_REPE || scan==SCAN_REPNE) {
  674. if (rep!=0) {
  675. strcpy(errtext,"Duplicated REP prefix"); goto error; };
  676. rep=scan; }
  677. else if (scan==SCAN_LOCK) {
  678. if (lock!=0) {
  679. strcpy(errtext,"Duplicated LOCK prefix"); goto error; };
  680. lock=scan; }
  681. else break; // No more prefixes
  682. Scanasm(SA_NAME); };
  683. if (scan!=SCAN_NAME || idata>16) {
  684. strcpy(errtext,"Command mnemonic expected"); goto error; };
  685. nameend=asmcmd;
  686. strupr(sdata);
  687. // Prepare full mnemonic (including repeat prefix, if any).
  688. if (rep==SCAN_REP) sprintf(name,"REP %s",sdata);
  689. else if (rep==SCAN_REPE) sprintf(name,"REPE %s",sdata);
  690. else if (rep==SCAN_REPNE) sprintf(name,"REPNE %s",sdata);
  691. else strcpy(name,sdata);
  692. Scanasm(0);
  693. // Parse command operands (up to 3). Note: jump address is always the first
  694. // (and only) operand in actual command set.
  695. for (i=0; i<3; i++) {
  696. aop[i].type=NNN; // No operand
  697. aop[i].size=0; // Undefined size
  698. aop[i].index=-1; // No index
  699. aop[i].scale=0; // No scale
  700. aop[i].base=-1; // No base
  701. aop[i].offset=0; // No offset
  702. aop[i].anyoffset=0; // No offset
  703. aop[i].segment=SEG_UNDEF; // No segment
  704. aop[i].jmpmode=0; }; // No jump size modifier
  705. Parseasmoperand(aop+0);
  706. jmpmode=aop[0].jmpmode;
  707. if (jmpmode!=0) jmpmode|=0x80;
  708. if (scan==SCAN_SYMB && idata==',') {
  709. Scanasm(0);
  710. Parseasmoperand(aop+1);
  711. if (scan==SCAN_SYMB && idata==',') {
  712. Scanasm(0);
  713. Parseasmoperand(aop+2);
  714. };
  715. };
  716. if (scan==SCAN_ERR) {
  717. strcpy(errtext,asmerror); goto error; };
  718. if (scan!=SCAN_EOL) {
  719. strcpy(errtext,"Extra input after operand"); goto error; };
  720. // If jump size is not specified, function tries to use short jump. If
  721. // attempt fails, it retries with long form.
  722. longjump=0; // Try short jump on the first pass
  723. retrylongjump:
  724. nameok=0;
  725. // Some commands allow different number of operands. Variables minop and
  726. // maxop accumulate their minimal and maximal counts. The numbers are not
  727. // used in assembly process but allow for better error diagnostics.
  728. minop=3; maxop=0;
  729. // Main assembly loop: try to find the command which matches all operands,
  730. // but do not process operands yet.
  731. namelen=strlen(name);
  732. for (pd=cmddata; pd->mask!=0; pd++) {
  733. if (pd->name[0]=='&') { // Mnemonic depends on operand size
  734. j=1;
  735. datasize=2;
  736. addrsize=4;
  737. while (1) { // Try all mnemonics (separated by ':')
  738. for (i=0; pd->name[j]!='\0' && pd->name[j]!=':'; j++) {
  739. if (pd->name[j]=='*') {
  740. if (name[i]=='W') { datasize=2; i++; }
  741. else if (name[i]=='D') { datasize=4; i++; }
  742. else if (sizesens==0) datasize=2;
  743. else datasize=4; }
  744. else if (pd->name[j]==name[i]) i++;
  745. else break;
  746. };
  747. if (name[i]=='\0' && (pd->name[j]=='\0' || pd->name[j]==':'))
  748. break; // Bingo!
  749. while (pd->name[j]!='\0' && pd->name[j]!=':')
  750. j++;
  751. if (pd->name[j]==':') {
  752. j++; datasize=4; } // Retry with 32-bit mnenonic
  753. else {
  754. i=0; break; // Comparison failed
  755. };
  756. };
  757. if (i==0) continue; }
  758. else if (pd->name[0]=='$') { // Mnemonic depends on address size
  759. j=1;
  760. datasize=0;
  761. addrsize=2;
  762. while (1) { // Try all mnemonics (separated by ':')
  763. for (i=0; pd->name[j]!='\0' && pd->name[j]!=':'; j++) {
  764. if (pd->name[j]=='*') {
  765. if (name[i]=='W') { addrsize=2; i++; }
  766. else if (name[i]=='D') { addrsize=4; i++; }
  767. else if (sizesens==0) addrsize=2;
  768. else addrsize=4; }
  769. else if (pd->name[j]==name[i]) i++;
  770. else break;
  771. };
  772. if (name[i]=='\0' && (pd->name[j]=='\0' || pd->name[j]==':'))
  773. break; // Bingo!
  774. while (pd->name[j]!='\0' && pd->name[j]!=':')
  775. j++;
  776. if (pd->name[j]==':') {
  777. j++; addrsize=4; } // Retry with 32-bit mnenonic
  778. else {
  779. i=0; break; // Comparison failed
  780. };
  781. };
  782. if (i==0) continue; }
  783. else { // Compare with all synonimes
  784. j=k=0;
  785. datasize=0; // Default settings
  786. addrsize=4;
  787. while (1) {
  788. while (pd->name[j]!=',' && pd->name[j]!='\0') j++;
  789. if (j-k==namelen && strnicmp(name,pd->name+k,namelen)==0) break;
  790. k=j+1; if (pd->name[j]=='\0') break;
  791. j=k; };
  792. if (k>j) continue;
  793. };
  794. // For error diagnostics it is important to know whether mnemonic exists.
  795. nameok++;
  796. if (pd->arg1==NNN || pd->arg1>=PSEUDOOP)
  797. minop=0;
  798. else if (pd->arg2==NNN || pd->arg2>=PSEUDOOP) {
  799. if (minop>1) minop=1;
  800. if (maxop<1) maxop=1; }
  801. else if (pd->arg3==NNN || pd->arg3>=PSEUDOOP) {
  802. if (minop>2) minop=2;
  803. if (maxop<2) maxop=2; }
  804. else
  805. maxop=3;
  806. // Determine default and allowed operand size(s).
  807. if (pd->bits==FF) datasize=2; // Forced 16-bit size
  808. if (pd->bits==WW || pd->bits==WS || pd->bits==W3 || pd->bits==WP)
  809. bytesize=1; // 1-byte size allowed
  810. else
  811. bytesize=0; // Word/dword size only
  812. // Check whether command operands match specified. If so, variable match
  813. // remains zero, otherwise it contains kind of mismatch. This allows for
  814. // better error diagnostics.
  815. match=0;
  816. for (j=0; j<3; j++) { // Up to 3 operands
  817. op=aop+j;
  818. if (j==0) arg=pd->arg1;
  819. else if (j==1) arg=pd->arg2;
  820. else arg=pd->arg3;
  821. if (arg==NNN || arg>=PSEUDOOP) {
  822. if (op->type!=NNN) // No more arguments
  823. match|=MA_NOP;
  824. break; };
  825. if (op->type==NNN) {
  826. match|=MA_NOP; break; }; // No corresponding operand
  827. switch (arg) {
  828. case REG: // Integer register in Reg field
  829. case RCM: // Integer register in command byte
  830. case RAC: // Accumulator (AL/AX/EAX, implicit)
  831. if (op->type!=REG) match|=MA_TYP;
  832. if (arg==RAC && op->index!=REG_EAX && op->index!=8) match|=MA_TYP;
  833. if (bytesize==0 && op->size==1) match|=MA_SIZ;
  834. if (datasize==0) datasize=op->size;
  835. if (datasize!=op->size) match|=MA_DIF;
  836. break;
  837. case RG4: // Integer 4-byte register in Reg field
  838. if (op->type!=REG) match|=MA_TYP;
  839. if (op->size!=4) match|=MA_SIZ;
  840. if (datasize==0) datasize=op->size;
  841. if (datasize!=op->size) match|=MA_DIF;
  842. break;
  843. case RAX: // AX (2-byte, implicit)
  844. if (op->type!=REG || (op->index!=REG_EAX && op->index!=8))
  845. match|=MA_TYP;
  846. if (op->size!=2) match|=MA_SIZ;
  847. if (datasize==0) datasize=op->size;
  848. if (datasize!=op->size) match|=MA_DIF;
  849. break;
  850. case RDX: // DX (16-bit implicit port address)
  851. if (op->type!=REG || (op->index!=REG_EDX && op->index!=8))
  852. match|=MA_TYP;
  853. if (op->size!=2) match|=MA_SIZ; break;
  854. case RCL: // Implicit CL register (for shifts)
  855. if (op->type!=REG || (op->index!=REG_ECX && op->index!=8))
  856. match|=MA_TYP;
  857. if (op->size!=1) match|=MA_SIZ;
  858. break;
  859. case RS0: // Top of FPU stack (ST(0))
  860. if (op->type!=RST || (op->index!=0 && op->index!=8))
  861. match|=MA_TYP;
  862. break;
  863. case RST: // FPU register (ST(i)) in command byte
  864. if (op->type!=RST) match|=MA_TYP; break;
  865. case RMX: // MMX register MMx
  866. case R3D: // 3DNow! register MMx
  867. if (op->type!=RMX) match|=MA_TYP; break;
  868. case MRG: // Memory/register in ModRM byte
  869. if (op->type!=MRG && op->type!=REG) match|=MA_TYP;
  870. if (bytesize==0 && op->size==1) match|=MA_SIZ;
  871. if (datasize==0) datasize=op->size;
  872. if (op->size!=0 && op->size!=datasize) match|=MA_DIF;
  873. break;
  874. case MR1: // 1-byte memory/register in ModRM byte
  875. if (op->type!=MRG && op->type!=REG) match|=MA_TYP;
  876. if (op->size!=0 && op->size!=1) match|=MA_SIZ;
  877. break;
  878. case MR2: // 2-byte memory/register in ModRM byte
  879. if (op->type!=MRG && op->type!=REG) match|=MA_TYP;
  880. if (op->size!=0 && op->size!=2) match|=MA_SIZ;
  881. break;
  882. case MR4: // 4-byte memory/register in ModRM byte
  883. if (op->type!=MRG && op->type!=REG) match|=MA_TYP;
  884. if (op->size!=0 && op->size!=4) match|=MA_SIZ;
  885. break;
  886. case RR4: // 4-byte memory/register (register only)
  887. if (op->type!=REG) match|=MA_TYP;
  888. if (op->size!=0 && op->size!=4) match|=MA_SIZ;
  889. break;
  890. case MRJ: // Memory/reg in ModRM as JUMP target
  891. if (op->type!=MRG && op->type!=REG) match|=MA_TYP;
  892. if (op->size!=0 && op->size!=4) match|=MA_SIZ;
  893. if ((jmpmode & 0x09)!=0) match|=MA_JMP;
  894. jmpmode&=0x7F; break;
  895. case MR8: // 8-byte memory/MMX register in ModRM
  896. case MRD: // 8-byte memory/3DNow! register in ModRM
  897. if (op->type!=MRG && op->type!=RMX) match|=MA_TYP;
  898. if (op->size!=0 && op->size!=8) match|=MA_SIZ;
  899. break;
  900. case RR8: // 8-byte MMX register only in ModRM
  901. case RRD: // 8-byte memory/3DNow! (register only)
  902. if (op->type!=RMX) match|=MA_TYP;
  903. if (op->size!=0 && op->size!=8) match|=MA_SIZ;
  904. break;
  905. case MMA: // Memory address in ModRM byte for LEA
  906. if (op->type!=MRG) match|=MA_TYP; break;
  907. case MML: // Memory in ModRM byte (for LES)
  908. if (op->type!=MRG) match|=MA_TYP;
  909. if (op->size!=0 && op->size!=6) match|=MA_SIZ;
  910. if (datasize==0) datasize=4; else if (datasize!=4) match|=MA_DIF;
  911. break;
  912. case MMS: // Memory in ModRM byte (as SEG:OFFS)
  913. if (op->type!=MRG) match|=MA_TYP;
  914. if (op->size!=0 && op->size!=6) match|=MA_SIZ;
  915. if ((jmpmode & 0x07)!=0) match|=MA_JMP;
  916. jmpmode&=0x7F; break;
  917. case MM6: // Memory in ModRm (6-byte descriptor)
  918. if (op->type!=MRG) match|=MA_TYP;
  919. if (op->size!=0 && op->size!=6) match|=MA_SIZ;
  920. break;
  921. case MMB: // Two adjacent memory locations (BOUND)
  922. if (op->type!=MRG) match|=MA_TYP;
  923. k=op->size; if (ideal==0 && k>1) k/=2;
  924. if (k!=0 && k!=datasize) match|=MA_DIF;
  925. break;
  926. case MD2: // Memory in ModRM byte (16-bit integer)
  927. case MB2: // Memory in ModRM byte (16-bit binary)
  928. if (op->type!=MRG) match|=MA_TYP;
  929. if (op->size!=0 && op->size!=2) match|=MA_SIZ;
  930. break;
  931. case MD4: // Memory in ModRM byte (32-bit integer)
  932. case MF4: // Memory in ModRM byte (32-bit float)
  933. if (op->type!=MRG) match|=MA_TYP;
  934. if (op->size!=0 && op->size!=4) match|=MA_SIZ;
  935. break;
  936. case MD8: // Memory in ModRM byte (64-bit integer)
  937. case MF8: // Memory in ModRM byte (64-bit float)
  938. if (op->type!=MRG) match|=MA_TYP;
  939. if (op->size!=0 && op->size!=8) match|=MA_SIZ;
  940. break;
  941. case MDA: // Memory in ModRM byte (80-bit BCD)
  942. case MFA: // Memory in ModRM byte (80-bit float)
  943. if (op->type!=MRG) match|=MA_TYP;
  944. if (op->size!=0 && op->size!=10) match|=MA_SIZ;
  945. break;
  946. case MFE: // Memory in ModRM byte (FPU environment)
  947. case MFS: // Memory in ModRM byte (FPU state)
  948. case MFX: // Memory in ModRM byte (ext. FPU state)
  949. if (op->type!=MRG) match|=MA_TYP;
  950. if (op->size!=0) match|=MA_SIZ;
  951. break;
  952. case MSO: // Source in string operands ([ESI])
  953. if (op->type!=MRG || op->base!=REG_ESI ||
  954. op->index!=-1 || op->offset!=0 || op->anyoffset!=0) match|=MA_TYP;
  955. if (datasize==0) datasize=op->size;
  956. if (op->size!=0 && op->size!=datasize) match|=MA_DIF;
  957. break;
  958. case MDE: // Destination in string operands ([EDI])
  959. if (op->type!=MRG || op->base!=REG_EDI ||
  960. op->index!=-1 || op->offset!=0 || op->anyoffset!=0) match|=MA_TYP;
  961. if (op->segment!=SEG_UNDEF && op->segment!=SEG_ES) match|=MA_SEG;
  962. if (datasize==0) datasize=op->size;
  963. if (op->size!=0 && op->size!=datasize) match|=MA_DIF;
  964. break;
  965. case MXL: // XLAT operand ([EBX+AL])
  966. if (op->type!=MXL) match|=MA_TYP; break;
  967. case IMM: // Immediate data (8 or 16/32)
  968. case IMU: // Immediate unsigned data (8 or 16/32)
  969. if (op->type!=IMM) match|=MA_TYP;
  970. break;
  971. case VXD: // VxD service (32-bit only)
  972. if (op->type!=IMM) match|=MA_TYP;
  973. if (datasize==0) datasize=4;
  974. if (datasize!=4) match|=MA_SIZ;
  975. break;
  976. case JMF: // Immediate absolute far jump/call addr
  977. if (op->type!=JMF) match|=MA_TYP;
  978. if ((jmpmode & 0x05)!=0) match|=MA_JMP;
  979. jmpmode&=0x7F; break;
  980. case JOB: // Immediate byte offset (for jumps)
  981. if (op->type!=IMM || longjump) match|=MA_TYP;
  982. if ((jmpmode & 0x0A)!=0) match|=MA_JMP;
  983. jmpmode&=0x7F; break;
  984. case JOW: // Immediate full offset (for jumps)
  985. if (op->type!=IMM) match|=MA_TYP;
  986. if ((jmpmode & 0x09)!=0) match|=MA_JMP;
  987. jmpmode&=0x7F; break;
  988. case IMA: // Immediate absolute near data address
  989. if (op->type!=MRG || op->base>=0 || op->index>=0) match|=MA_TYP;
  990. break;
  991. case IMX: // Immediate sign-extendable byte
  992. if (op->type!=IMM) match|=MA_TYP;
  993. if (op->offset<-128 || op->offset>127) match|=MA_RNG;
  994. break;
  995. case C01: // Implicit constant 1 (for shifts)
  996. if (op->type!=IMM || (op->offset!=1 && op->anyoffset==0))
  997. match|=MA_TYP;
  998. break;
  999. case IMS: // Immediate byte (for shifts)
  1000. case IM1: // Immediate byte
  1001. if (op->type!=IMM) match|=MA_TYP;
  1002. if (op->offset<-128 || op->offset>255) match|=MA_RNG;
  1003. break;
  1004. case IM2: // Immediate word (ENTER/RET)
  1005. if (op->type!=IMM) match|=MA_TYP;
  1006. if (op->offset<0 || op->offset>65535) match|=MA_RNG;
  1007. break;
  1008. case SGM: // Segment register in ModRM byte
  1009. if (op->type!=SGM) match|=MA_TYP;
  1010. if (datasize==0) datasize=2;
  1011. if (datasize!=2) match|=MA_DIF;
  1012. break;
  1013. case SCM: // Segment register in command byte
  1014. if (op->type!=SGM) match|=MA_TYP;
  1015. break;
  1016. case CRX: // Control register CRx
  1017. case DRX: // Debug register DRx
  1018. if (op->type!=arg) match|=MA_TYP;
  1019. if (datasize==0) datasize=4;
  1020. if (datasize!=4) match|=MA_DIF;
  1021. break;
  1022. case PRN: // Near return address (pseudooperand)
  1023. case PRF: // Far return address (pseudooperand)
  1024. case PAC: // Accumulator (AL/AX/EAX, pseudooperand)
  1025. case PAH: // AH (in LAHF/SAHF, pseudooperand)
  1026. case PFL: // Lower byte of flags (pseudooperand)
  1027. case PS0: // Top of FPU stack (pseudooperand)
  1028. case PS1: // ST(1) (pseudooperand)
  1029. case PCX: // CX/ECX (pseudooperand)
  1030. case PDI: // EDI (pseudooperand in MMX extentions)
  1031. break;
  1032. default: // Undefined type of operand
  1033. strcpy(errtext,"Internal Assembler error");
  1034. goto error;
  1035. }; // End of switch (arg)
  1036. if ((jmpmode & 0x80)!=0) match|=MA_JMP;
  1037. if (match!=0) break; // Some of the operands doesn't match
  1038. }; // End of operand matching loop
  1039. if (match==0) { // Exact match found
  1040. if (attempt>0) {
  1041. --attempt; nameok=0; } // Well, try to find yet another match
  1042. else break;
  1043. };
  1044. }; // End of command search loop
  1045. // Check whether some error was detected. If several errors were found
  1046. // similtaneously, report one (roughly in order of significance).
  1047. if (nameok==0) { // Mnemonic unavailable
  1048. strcpy(errtext,"Unrecognized command");
  1049. asmcmd=nameend; goto error; };
  1050. if (match!=0) { // Command not found
  1051. if (minop>0 && aop[minop-1].type==NNN)
  1052. strcpy(errtext,"Too few operands");
  1053. else if (maxop<3 && aop[maxop].type!=NNN)
  1054. strcpy(errtext,"Too many operands");
  1055. else if (nameok>1) // More that 1 command
  1056. strcpy(errtext,"Command does not support given operands");
  1057. else if (match & MA_JMP)
  1058. strcpy(errtext,"Invalid jump size modifier");
  1059. else if (match & MA_NOP)
  1060. strcpy(errtext,"Wrong number of operands");
  1061. else if (match & MA_TYP)
  1062. strcpy(errtext,"Command does not support given operands");
  1063. else if (match & MA_NOS)
  1064. strcpy(errtext,"Please specify operand size");
  1065. else if (match & MA_SIZ)
  1066. strcpy(errtext,"Bad operand size");
  1067. else if (match & MA_DIF)
  1068. strcpy(errtext,"Different size of operands");
  1069. else if (match & MA_SEG)
  1070. strcpy(errtext,"Invalid segment register");
  1071. else if (match & MA_RNG)
  1072. strcpy(errtext,"Constant out of expected range");
  1073. else
  1074. strcpy(errtext,"Erroneous command");
  1075. goto error;
  1076. };
  1077. // Exact match found. Now construct the code.
  1078. hasrm=0; // Whether command has ModR/M byte
  1079. hassib=0; // Whether command has SIB byte
  1080. dispsize=0; // Size of displacement (if any)
  1081. immsize=0;

Large files files are truncated, but you can click here to view the full file