📄 x86.md
字号:
stmt: ARGF8(reg) "sub esp,8\nfstp qword ptr [esp]\n"stmt: ARGF4(reg) "sub esp,4\nfstp dword ptr [esp]\n"reg: NEGF8(reg) "fchs\n"reg: NEGF4(reg) "fchs\n"flt: memf " %0"flt: reg "p st(1),st"reg: ADDF8(reg,flt) "fadd%1\n"reg: ADDF4(reg,flt) "fadd%1\n"reg: DIVF8(reg,flt) "fdiv%1\n"reg: DIVF4(reg,flt) "fdiv%1\n"reg: MULF8(reg,flt) "fmul%1\n"reg: MULF4(reg,flt) "fmul%1\n"reg: SUBF8(reg,flt) "fsub%1\n"reg: SUBF4(reg,flt) "fsub%1\n"reg: CVFF8(reg) "# CVFF8\n"reg: CVFF4(reg) "sub esp,4\nfstp dword ptr 0[esp]\nfld dword ptr 0[esp]\nadd esp,4\n" 12reg: CVFI4(reg) "call __ftol\n" 31reg: CVIF8(INDIRI4(addr)) "fild dword ptr %0\n" 10reg: CVIF4(reg) "push %0\nfild dword ptr 0[esp]\nadd esp,4\n" 12reg: CVIF8(reg) "push %0\nfild dword ptr 0[esp]\nadd esp,4\n" 12addrj: ADDRGP4 "%a"addrj: reg "%0" 2addrj: mem "%0" 2stmt: JUMPV(addrj) "jmp %0\n" 3stmt: LABELV "%a:\n"stmt: EQI4(mem,rc) "cmp %0,%1\nje %a\n" 5stmt: GEI4(mem,rc) "cmp %0,%1\njge %a\n" 5stmt: GTI4(mem,rc) "cmp %0,%1\njg %a\n" 5stmt: LEI4(mem,rc) "cmp %0,%1\njle %a\n" 5stmt: LTI4(mem,rc) "cmp %0,%1\njl %a\n" 5stmt: NEI4(mem,rc) "cmp %0,%1\njne %a\n" 5stmt: GEU4(mem,rc) "cmp %0,%1\njae %a\n" 5stmt: GTU4(mem,rc) "cmp %0,%1\nja %a\n" 5stmt: LEU4(mem,rc) "cmp %0,%1\njbe %a\n" 5stmt: LTU4(mem,rc) "cmp %0,%1\njb %a\n" 5stmt: EQI4(reg,mrc1) "cmp %0,%1\nje %a\n" 4stmt: GEI4(reg,mrc1) "cmp %0,%1\njge %a\n" 4stmt: GTI4(reg,mrc1) "cmp %0,%1\njg %a\n" 4stmt: LEI4(reg,mrc1) "cmp %0,%1\njle %a\n" 4stmt: LTI4(reg,mrc1) "cmp %0,%1\njl %a\n" 4stmt: NEI4(reg,mrc1) "cmp %0,%1\njne %a\n" 4stmt: EQU4(reg,mrc1) "cmp %0,%1\nje %a\n" 4stmt: GEU4(reg,mrc1) "cmp %0,%1\njae %a\n" 4stmt: GTU4(reg,mrc1) "cmp %0,%1\nja %a\n" 4stmt: LEU4(reg,mrc1) "cmp %0,%1\njbe %a\n" 4stmt: LTU4(reg,mrc1) "cmp %0,%1\njb %a\n" 4stmt: NEU4(reg,mrc1) "cmp %0,%1\njne %a\n" 4cmpf: memf " %0"cmpf: reg "p"stmt: EQF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %b\nje %a\n%b:\n"stmt: GEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\njbe %a\n"stmt: GTF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\njb %a\n"stmt: LEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\njae %a\n"stmt: LTF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\nja %a\n"stmt: NEF8(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\njne %a\n"stmt: EQF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %b\nje %a\n%b:\n"stmt: GEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\njbe %a\n\n"stmt: GTF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\njb %a\n"stmt: LEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\njae %a\n\n"stmt: LTF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\nja %a\n"stmt: NEF4(cmpf,reg) "fcomp%0\nfstsw ax\nsahf\njp %a\njne %a\n"reg: CALLI4(addrj) "call %0\nadd esp,%a\n"reg: CALLU4(addrj) "call %0\nadd esp,%a\n"reg: CALLP4(addrj) "call %0\nadd esp,%a\n"stmt: CALLV(addrj) "call %0\nadd esp,%a\n"reg: CALLF4(addrj) "call %0\nadd esp,%a\n"reg: CALLF8(addrj) "call %0\nadd esp,%a\n"stmt: CALLF4(addrj) "call %0\nadd esp,%a\nfstp\n"stmt: CALLF8(addrj) "call %0\nadd esp,%a\nfstp\n"stmt: RETI4(reg) "# ret\n"stmt: RETU4(reg) "# ret\n"stmt: RETP4(reg) "# ret\n"stmt: RETF4(reg) "# ret\n"stmt: RETF8(reg) "# ret\n"%%static void progbeg(int argc, char *argv[]) { int i; { union { char c; int i; } u; u.i = 0; u.c = 1; swap = ((int)(u.i == 1)) != IR->little_endian; } parseflags(argc, argv); intreg[EAX] = mkreg("eax", EAX, 1, IREG); intreg[EDX] = mkreg("edx", EDX, 1, IREG); intreg[ECX] = mkreg("ecx", ECX, 1, IREG); intreg[EBX] = mkreg("ebx", EBX, 1, IREG); intreg[ESI] = mkreg("esi", ESI, 1, IREG); intreg[EDI] = mkreg("edi", EDI, 1, IREG); shortreg[EAX] = mkreg("ax", EAX, 1, IREG); shortreg[ECX] = mkreg("cx", ECX, 1, IREG); shortreg[EDX] = mkreg("dx", EDX, 1, IREG); shortreg[EBX] = mkreg("bx", EBX, 1, IREG); shortreg[ESI] = mkreg("si", ESI, 1, IREG); shortreg[EDI] = mkreg("di", EDI, 1, IREG); charreg[EAX] = mkreg("al", EAX, 1, IREG); charreg[ECX] = mkreg("cl", ECX, 1, IREG); charreg[EDX] = mkreg("dl", EDX, 1, IREG); charreg[EBX] = mkreg("bl", EBX, 1, IREG); for (i = 0; i < 8; i++) fltreg[i] = mkreg("%d", i, 0, FREG); charregw = mkwildcard(charreg); shortregw = mkwildcard(shortreg); intregw = mkwildcard(intreg); fltregw = mkwildcard(fltreg); tmask[IREG] = (1<<EDI) | (1<<ESI) | (1<<EBX) | (1<<EDX) | (1<<ECX) | (1<<EAX); vmask[IREG] = 0; tmask[FREG] = 0xff; vmask[FREG] = 0; print(".486\n"); print(".model flat\n"); print("extrn __fltused:near\n"); print("extrn __ftol:near\n"); cseg = 0; quo = mkreg("eax", EAX, 1, IREG); quo->x.regnode->mask |= 1<<EDX; rem = mkreg("edx", EDX, 1, IREG); rem->x.regnode->mask |= 1<<EAX;}static Symbol rmap(int opk) { switch (optype(opk)) { case B: case P: return intregw; case I: case U: if (opsize(opk) == 1) return charregw; else if (opsize(opk) == 2) return shortregw; else return intregw; case F: return fltregw; default: return 0; }}static void segment(int n) { if (n == cseg) return; if (cseg == CODE || cseg == LIT) print("_TEXT ends\n"); else if (cseg == DATA || cseg == BSS) print("_DATA ends\n"); cseg = n; if (cseg == CODE || cseg == LIT) print("_TEXT segment\n"); else if (cseg == DATA || cseg == BSS) print("_DATA segment\n");}static void progend(void) { segment(0); print("end\n");}static void target(Node p) { assert(p); switch (specific(p->op)) { case MUL+U: setreg(p, quo); rtarget(p, 0, intreg[EAX]); break; case DIV+I: case DIV+U: setreg(p, quo); rtarget(p, 0, quo); break; case MOD+I: case MOD+U: setreg(p, rem); rtarget(p, 0, quo); break; case ASGN+B: rtarget(p, 0, intreg[EDI]); rtarget(p->kids[1], 0, intreg[ESI]); break; case ARG+B: rtarget(p->kids[0], 0, intreg[ESI]); break; case CVF+I: setreg(p, intreg[EAX]); break; case CALL+I: case CALL+U: case CALL+P: case CALL+V: setreg(p, intreg[EAX]); break; case RET+I: case RET+U: case RET+P: rtarget(p, 0, intreg[EAX]); break; }}static void clobber(Node p) { static int nstack = 0; assert(p); nstack = ckstack(p, nstack); switch (specific(p->op)) { case RSH+I: case RSH+U: case LSH+I: case LSH+U: if (generic(p->kids[1]->op) != CNST && !( generic(p->kids[1]->op) == INDIR && specific(p->kids[1]->kids[0]->op) == VREG+P && p->kids[1]->syms[RX]->u.t.cse && generic(p->kids[1]->syms[RX]->u.t.cse->op) == CNST)) { spill(1<<ECX, 1, p); } break; case ASGN+B: case ARG+B: spill(1<<ECX | 1<<ESI | 1<<EDI, IREG, p); break; case EQ+F: case LE+F: case GE+F: case LT+F: case GT+F: case NE+F: spill(1<<EAX, IREG, p); if (specific(p->op) == EQ+F) p->syms[1] = findlabel(genlabel(1)); break; case CALL+F: spill(1<<EDX | 1<<EAX | 1<<ECX, IREG, p); break; case CALL+I: case CALL+U: case CALL+P: case CALL+V: spill(1<<EDX | 1<<ECX, IREG, p); break; }}#define isfp(p) (optype((p)->op)==F)int ckstack(Node p, int n) { int i; for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) if (isfp(p->x.kids[i])) n--; if (isfp(p) && p->count > 0) n++; if (n > 8) error("expression too complicated\n"); debug(fprint(stderr, "(ckstack(%x)=%d)\n", p, n)); assert(n >= 0); return n;}int memop(Node p) { assert(p); assert(generic(p->op) == ASGN); assert(p->kids[0]); assert(p->kids[1]); if (generic(p->kids[1]->kids[0]->op) == INDIR && sametree(p->kids[0], p->kids[1]->kids[0]->kids[0])) return 3; else return LBURG_MAX;}int sametree(Node p, Node q) { return p == NULL && q == NULL || p && q && p->op == q->op && p->syms[0] == q->syms[0] && sametree(p->kids[0], q->kids[0]) && sametree(p->kids[1], q->kids[1]);}static void emit2(Node p) { int op = specific(p->op);#define preg(f) ((f)[getregnum(p->x.kids[0])]->x.name) if (op == CVI+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) print("movsx %s,%s\n", p->syms[RX]->x.name, preg(charreg)); else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) print("movsx %s,%s\n", p->syms[RX]->x.name, preg(charreg)); else if (op == CVI+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) print("movsx %s,%s\n", p->syms[RX]->x.name, preg(shortreg)); else if (op == CVI+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) print("movsx %s,%s\n", p->syms[RX]->x.name, preg(shortreg)); else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) print("movzx %s,%s\n", p->syms[RX]->x.name, preg(charreg)); else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 1) print("movzx %s,%s\n", p->syms[RX]->x.name, preg(charreg)); else if (op == CVU+I && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) print("movzx %s,%s\n", p->syms[RX]->x.name, preg(shortreg)); else if (op == CVU+U && opsize(p->op) == 4 && opsize(p->x.kids[0]->op) == 2) print("movzx %s,%s\n", p->syms[RX]->x.name, preg(shortreg)); else if (generic(op) == CVI || generic(op) == CVU || generic(op) == LOAD) { char *dst = intreg[getregnum(p)]->x.name; char *src = preg(intreg); assert(opsize(p->op) <= opsize(p->x.kids[0]->op)); if (dst != src) print("mov %s,%s\n", dst, src); } else if (op == ARG+B) print("sub esp,%d\nmov edi,esp\nmov ecx,%d\nrep movsb\n", roundup(p->syms[0]->u.c.v.i, 4), p->syms[0]->u.c.v.i);}static void doarg(Node p) { assert(p && p->syms[0]); mkactual(4, p->syms[0]->u.c.v.i);}static void blkfetch(int k, int off, int reg, int tmp) {}static void blkstore(int k, int off, int reg, int tmp) {}static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) {}static void local(Symbol p) { if (isfloat(p->type)) p->sclass = AUTO; if (askregvar(p, (*IR->x.rmap)(ttob(p->type))) == 0) { assert(p->sclass == AUTO); offset = roundup(offset + p->type->size, p->type->align < 4 ? 4 : p->type->align); p->x.offset = -offset; p->x.name = stringd(-offset); }}static void function(Symbol f, Symbol caller[], Symbol callee[], int n) { int i; print("%s:\n", f->x.name); print("push ebx\n"); print("push esi\n"); print("push edi\n"); print("push ebp\n"); print("mov ebp,esp\n"); usedmask[0] = usedmask[1] = 0; freemask[0] = freemask[1] = ~(unsigned)0; offset = 16 + 4; for (i = 0; callee[i]; i++) { Symbol p = callee[i]; Symbol q = caller[i]; assert(q); p->x.offset = q->x.offset = offset; p->x.name = q->x.name = stringf("%d", p->x.offset); p->sclass = q->sclass = AUTO; offset += roundup(q->type->size, 4); } assert(caller[i] == 0); offset = maxoffset = 0; gencode(caller, callee); framesize = roundup(maxoffset, 4); if (framesize >= 4096) print("mov eax,%d\ncall __chkstk\n", framesize); else if (framesize > 0) print("sub esp,%d\n", framesize); emitcode(); print("mov esp,ebp\n"); print("pop ebp\n"); print("pop edi\n"); print("pop esi\n"); print("pop ebx\n"); print("ret\n"); if (framesize >= 4096) { int oldseg = cseg; segment(0); print("extrn __chkstk:near\n"); segment(oldseg); }}static void defsymbol(Symbol p) { if (p->scope >= LOCAL && p->sclass == STATIC) p->x.name = stringf("L%d", genlabel(1)); else if (p->generated) p->x.name = stringf("L%s", p->name); else if (p->scope == GLOBAL || p->sclass == EXTERN) p->x.name = stringf("_%s", p->name); else if (p->scope == CONSTANTS && (isint(p->type) || isptr(p->type)) && p->name[0] == '0' && p->name[1] == 'x') p->x.name = stringf("0%sH", &p->name[2]); else p->x.name = p->name;}static void address(Symbol q, Symbol p, long n) { if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) q->x.name = stringf("%s%s%D", p->x.name, n >= 0 ? "+" : "", n); else { assert(n <= INT_MAX && n >= INT_MIN); q->x.offset = p->x.offset + n; q->x.name = stringd(q->x.offset); }}static void defconst(int suffix, int size, Value v) { if (suffix == I && size == 1) print("db %d\n", v.u); else if (suffix == I && size == 2) print("dw %d\n", v.i); else if (suffix == I && size == 4) print("dd %d\n", v.i); else if (suffix == U && size == 1) print("db 0%xH\n", (unsigned)((unsigned char)v.u)); else if (suffix == U && size == 2) print("dw 0%xH\n", (unsigned)((unsigned short)v.u)); else if (suffix == U && size == 4) print("dd 0%xH\n", (unsigned)v.u); else if (suffix == P && size == 4) print("dd 0%xH\n", (unsigned)v.p); else if (suffix == F && size == 4) { float f = v.d; print("dd 0%xH\n", *(unsigned *)&f); } else if (suffix == F && size == 8) { double d = v.d; unsigned *p = (unsigned *)&d; print("dd 0%xH\ndd 0%xH\n", p[swap], p[!swap]); } else assert(0);}static void defaddress(Symbol p) { print("dd %s\n", p->x.name);}static void defstring(int n, char *str) { char *s; for (s = str; s < str + n; s++) print("db %d\n", (*s)&0377);}static void export(Symbol p) { print("public %s\n", p->x.name);}static void import(Symbol p) { int oldseg = cseg; if (p->ref > 0) { segment(0); print("extrn %s:near\n", p->x.name); segment(oldseg); }}static void global(Symbol p) { print("align %d\n", p->type->align > 4 ? 4 : p->type->align); print("%s label byte\n", p->x.name);}static void space(int n) { print("db %d dup (0)\n", n);}Interface x86IR = { 1, 1, 0, /* char */ 2, 2, 0, /* short */ 4, 4, 0, /* int */ 4, 4, 0, /* long */ 4, 4, 0, /* long long */ 4, 4, 1, /* float */ 8, 4, 1, /* double */ 8, 4, 1, /* long double */ 4, 4, 0, /* T * */ 0, 1, 0, /* struct */ 1, /* little_endian */ 0, /* mulops_calls */ 0, /* wants_callb */ 1, /* wants_argb */ 0, /* left_to_right */ 0, /* wants_dag */ 0, /* unsigned_char */ address, blockbeg, blockend, defaddress, defconst, defstring, defsymbol, emit, export, function, gen, global, import, local, progbeg, progend, segment, space, 0, 0, 0, 0, 0, 0, 0, {1, rmap, blkfetch, blkstore, blkloop, _label, _rule, _nts, _kids, _string, _templates, _isinstruction, _ntname, emit2, doarg, target, clobber,}};static char rcsid[] = "$Id: x86.md,v 1.1 2002/08/28 23:12:48 drh Exp $";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -