📄 operand.c
字号:
/* * **/#include "a64-2.h"#include "operand.h"#include "error.h"#include "label.h"#include <stdio.h>int is_variable(char *s){ return 0;}/********************************************************* example: parameter: s = "(dword)es:[eax+ecx*8+0xc]" (one operand) o_key = get a operand's key word return value: error if errno is set successed if errno is 0last change: 02-17-2006 21:24 by miklast change: 02-19-2006 21:05 by mik**********************************************************/errno_t get_o_key(o_key_t *o_key, char *s) { if (!s || !s[0]) return 0; errno_t errno = 0; /* return value */ char *p = s; char str[80]; int i = 0; unsigned char c = 0; if (!o_key) return ERR_OPERAND; /* the operand is a memory operand */ if (get_c(s, '[') == 1) o_key->mem = (mem_t *)a64_malloc(sizeof(mem_t)); /* parse operand * * for example: (dword)es:[ecx*8+eax+0xc] */ char tmp_msg[120]; char *msg = get_err_msg_addr(); while (*p) { if (is_c(*p) || is_n(*p)) { str[i++] = *p; } else switch (*p) { case '(': if (p != s) { /* it's not head */ sprintf(tmp_msg, "at %d: %s\n", line, "parse error at before '('"); if (str_len(msg) + str_len(tmp_msg) < ERR_MSG_SIZE) { str_cat(msg, tmp_msg); } } if (get_c(s,')') != 1) errno |= ERR_SLBRACKET; i = 0; break; case ')': /* get operand size cast value */ if (get_c(s, '(') != 1) errno |= ERR_SRBRACKET; str[i] = 0; unsigned char cast = get_castid(str); if (!check_cast(cast)) errno |= ERR_CAST; if (o_key->mem) { if (cast == NEAR_ID || cast == FAR_ID) o_key->mem->transfer_cast = cast; else /* it's a memory cast */ o_key->mem->cast = cast; } else { /* it's a immediate cast */ o_key->imme = (imme_t *)a64_malloc(sizeof(mem_t)); o_key->imme->cast = cast; } i = 0; break; case ':': /* segment override */ /* get segment override size byte */ str[i] = 0; o_key->mem->oseg = get_osegid(str); if (!check_oseg(o_key->mem->oseg)) { if (current_bits == 64) { sprintf(tmp_msg, "error at %d: %s\n", line, "in 64-bit mode: the " "prefix illegal! "); mount_err_link(0, 0, tmp_msg); errno |= ERR_ERROR; } else errno |= ERR_PREFIX; } i = 0; break; case '[': /* memory operand */ /******************************* TO DO: this is reserved for var .... example: var1[eax] this is same as [eax + var1] *****************************/ #ifdef RESERVED_VAR str[i] = 0; /* check var at var table */ if (!check_var(str)) errno |= ERR_OPERAND; p++; /* skip '[' */ #else /* xxx[...] is error */ if (i) errno |= ERR_OPERAND; #endif if (get_c(s, ']') != 1) errno |= ERR_MRBRACKET; i = 0; break; case '+': case ']': if (*p == ']') { if (get_c(s, '[') != 1) errno |= ERR_MLBRACKET; if ((*(p+1) != 0) && (*(p+1) != '!')) { /* not tail and not comment */ /* errno |= ERR_OPERAND; */ sprintf(tmp_msg, "at %d: %s\n", line, "parse error at after ']'"); if (str_len(msg) + str_len(tmp_msg) < ERR_MSG_SIZE) { str_cat(msg, tmp_msg); } } } str[i] = 0; c = get_regid(str); if (check_mreg(c)) { /* it's valid register */ if (!o_key->mem->base) o_key->mem->base = c; else if (!o_key->mem->index) o_key->mem->index = c; else errno |= ERR_BASE; /* check base register and index register */ if (o_key->mem->base && o_key->mem->index) if ((o_key->mem->base & 0xf0) != (o_key->mem->index & 0xf0)) errno |= ERR_BASE; /* this is a disp value or scale value */ } else if (is_numeric(str)) { if (is_n(*(p-1)) && (*(p-2) == '*')) { /* scale value */ o_key->mem->scale = get_scaleid(str); if (!o_key->mem->scale) errno |= ERR_SCALE; } else if (!o_key->mem->disp) { /* displacement value */ o_key->mem->disp = str_to_n(str); } else errno |= ERR_DISP; } else { /* illegal operand */ /* errno |= ERR_OPERAND; */ sprintf(tmp_msg, "at %d: parse error at %s\n", line, str); if (str_len(msg) + str_len(tmp_msg) < ERR_MSG_SIZE) { str_cat(msg, tmp_msg); } } i = 0; break; case '-': str[i] = 0; c = get_regid(str); if (check_mreg(c)) { /* valid regiser */ if (!o_key->mem->base) o_key->mem->base = c; else if (!o_key->mem->index) o_key->mem->index = c; else errno |= ERR_BASE; if (o_key->mem->base && o_key->mem->index) if ((o_key->mem->base & 0xf0) != (o_key->mem->index & 0xf0)) errno != ERR_BASE; /*********************************** * TODO: reserved for disp or scale value ***********************************/ } else { /* errno |= ERR_OPERAND; */ sprintf(tmp_msg, "at %d: parse error at %s\n", line, str); if (str_len(msg) + str_len(tmp_msg) < ERR_MSG_SIZE) str_cat(msg, tmp_msg); } /***************************************/ char *tp = p + 1; i = 0; while (*tp && *tp != ']') str[i++] = *tp++; str[i] = 0; if (is_numeric(str) && (!o_key->mem->disp)) o_key->mem->disp = -str_to_n(str); else return errno | ERR_OPERAND; p = tp; i = 0; break; case '*': /* it's a index register */ str[i] = 0; c = get_regid(str); if (check_mreg(c) && !o_key->mem->index) { /* it's index register */ o_key->mem->index = c; if (o_key->mem->base && ((o_key->mem->base & 0xf0) != (o_key->mem->index & 0xf0))) errno |= ERR_BASE; } else errno |= ERR_INDEX; i = 0; break; case '@': /* it's a label string */ if (i) errno |= ERR_OPERAND;/* while (*p != ' ') str[i++] = *p++; str[i] = 0;*/ /**************** * mount_hole_link() ***************/ i = 0; break; case 0x09: /* it's a tab */ i = 0; break; case '!': while (*p) p++; continue; default: errno |= ERR_CHARACTER; } p++; } if (errno || str_len(msg)) { if (str_len(msg) == 0) { sprintf(msg, "at %d: ", line); } mount_err_link(errno, ops_errmsg, msg); goto do_error; } str[i] = 0; if (o_key->mem) { /* memory operand */ mem_t *mem = o_key->mem; /* check base register invalid */ /* example: [esp*4+ecx] is invalid */ if (((mem->index == ESP) || (mem->index == RSP)) && mem->scale) { sprintf(msg, "at %d: %s\n", line, "When index register is \"sp\"" "the scale value error"); mount_err_link(0, 0, msg); /* errno |= ERR_BASE; */ goto do_error; } /**** check 16-bit address size ****/ /* In 16-bit address size mode: [bx+bp] or [si+di] are error */ if (((mem->base == BX) && (mem->index == BP)) || ((mem->base == SI) && (mem->index == DI))) { errno |= ERR_BASE; mount_err_link(errno, ops_errmsg, 0); goto do_error; } if (mem->disp) { /* the disp example: [eax+0x0808004] */ /* example: disp is 8bytes and size is 32bit */ if (get_sizeof(o_key->mem->disp) > (current_bits >> 3)) { union { long long ll; /* 64-bit */ short word; /* 16-bit */ int dword; /* 32-bit */ } u; u.ll = o_key->mem->disp; switch (current_bits) { case 16: o_key->mem->disp = u.word; break; case 32: o_key->mem->disp = u.dword; break; } } } /* if: disp */ if (o_key->mem->base) o_key->mem->addr = (o_key->mem->base & 0xf0) >> 1; else if (o_key->mem->index) o_key->mem->addr = (o_key->mem->index & 0xf0) >> 1;/* else o_key->mem->addr = current_bits;*/ return errno; } else if (o_key->reg = get_regid(str)) { /* register operand */ /******************** TODO: check_reg() ********************/ } else if (is_numeric(str)) { /* immedeate operand */ /******************* TODO: check_imme() ********************/ if (!o_key->imme) o_key->imme = (imme_t *)a64_malloc(sizeof(imme_t)); o_key->imme->imme_value = (long long)str_to_n(str); /* union{ long l[2]; long long ll; }u; u.ll = o_key->imme->imme_value; printf("--%x%x--\n",u.l[1],u.l[0]);*/ unsigned int imme_size = 0; if (o_key->imme->cast > current_bits) errno |= ERR_CAST; else if (o_key->imme->cast) imme_size = o_key->imme->cast; else o_key->imme->cast = get_sizeof(o_key->imme->imme_value) * 8;#if 0 else if (get_sizeof(o_key->imme->imme_value) > (current_bits >> 3)) { imme_size = current_bits; } if (imme_size) { union { long long ll; int dword; short word; } u; u.ll = o_key->imme->imme_value; switch (current_bits) { case 16: o_key->imme->imme_value = u.word; break; case 32: o_key->imme->imme_value = u.dword; } }#endif } else if (is_label(str)) { /* this is a label for "jmp" or "call" */ } else if (is_variable(str)) { /* is a variable value */ /********************************** * TODO: reserved for is_variable() *********************************/ } else { errno |= ERR_OPERAND; mount_err_link(errno, ops_errmsg, 0); } do_error: /* it's not memory operand, so free o_key->mem */ if (o_key->mem) { a64_free(o_key->mem); o_key->mem = 0; } return errno;}/************************************************************* example: parameter: s = "eax,(dword)es:[eax+ecx*8+0xc]" ops_key = get the ops_key_t value for parameter s; return value: error if errno value is set succssed if errno is 0last change: 02-18-2006 14:20 by mik**************************************************************/errno_t get_ops_key(ops_key_t *ops_key, char *s) { /* have no operands */ if (!s || !*s) return 0; int i = 0; char str[80]; char trims[200]; errno_t errno = 0; /* return value */ if (!trim_space(trims, s) || !ops_key) return ERR_OPERAND; s = trims; char *p = s + str_len(s) - 1; char *q = s; char tmp_msg[80]; char *msg = get_err_msg_addr(); /* find operands and get operand key word */ while (*p) { q = p; while (*p != ',') { /* search last ',' */ if (p <= s) break; p--; } i = 0; if (*p == ',') { while (p+i+1 <= q) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -