Make your own free website on Tripod.com
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

x86instr.cpp

Go to the documentation of this file.
00001 /*
00002 PeRdr - PE file disassembler
00003 Copyright (C) 1999-2002 Frediano Ziglio
00004 -----
00005 
00006 This program is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 -----
00020 
00021 INFORMATION
00022   www: http://freddy77.tripod.com/perdr/
00023   e-mail: freddy77@angelfire.com
00024 */
00025 #include "global.h"
00026 #ifdef HAVE_HDRSTOP
00027 #pragma hdrstop
00028 #endif
00029 
00030 #include <cstring>
00031 #include "x86istr.h"
00032 #include "x86instr.h"
00033 
00034 #define REG_INFO(reg) (*RegistryInfo::GetInfo(reg))
00035 #define COMPLETE(reg) (REG_INFO(reg).completeReg)
00036 #define INTERSECT(reg_a,reg_b) ( REG_INFO(reg_a).completeReg == REG_INFO(reg_b).completeReg && (REG_INFO(reg_a).partialMask&REG_INFO(reg_b).partialMask)!=0 )
00037 #define USE_TYPE(u) static_cast<enum Instruction::UseType>(u)
00038 
00039 enum Instruction::UseType Instruction::GetUseType(reg_t reg,Param* param) const
00040 {
00041   unsigned res = useNone;
00042   unsigned overwriteMask = useReadWrite;
00043 
00044   // caso generale
00045   // primo parametro scrive
00046   // altri legge
00047   // se parte di indirizzamento sempre lettura
00048   if (numArg>0)
00049   {
00050     int i = 0;
00051     if (Args[0].type == Param::t_registry)
00052     {
00053       if ( INTERSECT(reg,Args[0].mem_reg1) )
00054       {
00055         if ( (REG_INFO(reg).partialMask&REG_INFO(Args[0].mem_reg1).partialMask) != REG_INFO(reg).partialMask)
00056           overwriteMask = useReadModify;
00057         res |= (useModify|useOverwrite);
00058       }
00059       i = 1;
00060     }
00061     for(;i<numArg;++i)
00062     {
00063       switch(Args[i].type)
00064       {
00065       case Param::t_memory:
00066         if ( Args[i].mem_reg2 != null_reg && INTERSECT(reg,Args[i].mem_reg2) )
00067           res |= useRead;
00068       case Param::t_registry:
00069         if ( Args[i].mem_reg1 != null_reg && INTERSECT(reg,Args[i].mem_reg1) )
00070           res |= useRead;
00071         break;
00072       }
00073     }
00074   }
00075 
00076   // !!! registri flag non gestiti
00077   // !!! per parziale e sovrascrittura ritorna un valore piu' grande !!
00078   switch(instruction)
00079   {
00080   case istr_jb:
00081   case istr_jbe:
00082   case istr_jc:
00083   case istr_jg:
00084   case istr_jl:
00085   case istr_jle:
00086   case istr_jnbe:
00087   case istr_jnb:
00088   case istr_jnc:
00089   case istr_jng:
00090   case istr_jnl:
00091   case istr_jnle:
00092   case istr_jno:
00093   case istr_jnp:
00094   case istr_jns:
00095   case istr_jnz:
00096   case istr_jo:
00097   case istr_jp:
00098   case istr_js:
00099   case istr_jz:
00100   case istr_cld:
00101     break;
00102   case istr_call:
00103     _PRG_ASSERT(numArg==1);
00104     if (res != useNone) // anche se primo operando sempre lettura
00105       return useRead;
00106     break;
00107   case istr_setb:
00108   case istr_setbe:
00109   case istr_setl:
00110   case istr_setle:
00111   case istr_setnb:
00112   case istr_setnbe:
00113   case istr_setnl:
00114   case istr_setnle:
00115   case istr_setno:
00116   case istr_setnp:
00117   case istr_setns:
00118   case istr_setnz:
00119   case istr_seto:
00120   case istr_setp:
00121   case istr_sets:
00122   case istr_setz:
00123     _PRG_ASSERT(numArg == 1);
00124     return USE_TYPE(res&useReadModify); // !!! potrebbe essere Overwrite ma cosa ci scrivo ?
00125 
00126   // istruzioni flag
00127   case istr_bts:
00128   case istr_btr:
00129   case istr_btc:
00130 
00131   // istruzioni shift
00132   case istr_shl:
00133   case istr_shr:
00134   case istr_sar:
00135   case istr_ror:
00136 
00137   case istr_sbb: // sebbene sembri simile a sub non c'e' la condizione di write
00138   case istr_adc:
00139     // !!! manca CF
00140   case istr_add:
00141     _PRG_ASSERT(numArg == 2);
00142     return USE_TYPE(res&useReadModify);
00143   case istr_not:
00144   case istr_neg:
00145   case istr_inc:
00146   case istr_dec:
00147     _PRG_ASSERT(numArg==1);
00148     return USE_TYPE(res&useReadModify);
00149   case istr_or:
00150   case istr_and:
00151     _PRG_ASSERT(numArg==2);
00152     // caso speciale, stesso registro in tutti gli operandi
00153     if ( (res&useReadWrite) == useReadWrite && Args[1].type == Param::t_registry)
00154       return useRead; // !!! non none, cambia flag
00155     return USE_TYPE(res&useReadModify);
00156   case istr_xor:
00157   case istr_sub:
00158     _PRG_ASSERT(numArg == 2);
00159     // caso speciale, stesso registro in tutti gli operandi
00160     if ( (res&useReadWrite) == useReadWrite && Args[1].type == Param::t_registry)
00161     {
00162       if ( (overwriteMask&useOverwrite) && param)
00163         *param = Param(Param::Literal,0);
00164       return USE_TYPE(res&overwriteMask);
00165     }
00166     return USE_TYPE(res&useReadModify);
00167   case istr_movsx: // !!! come viene gestito estensione ??
00168   case istr_movzx:
00169   case istr_mov:
00170     _PRG_ASSERT(numArg == 2);
00171     // caso speciale, stesso registro in tutti gli operandi
00172     if ( (res&useReadWrite) == useReadWrite && Args[1].type == Param::t_registry)
00173       return useNone;
00174     // sovrascrittura
00175     if ( (overwriteMask&useOverwrite) && param)
00176       *param = Args[1]; // !!! per parziale ??
00177     return USE_TYPE(res&overwriteMask);
00178   // !!! in 16 bit mode se modifico cx e chiedo ecx problemi
00179   case istr_repnz:
00180   case istr_repz:
00181     if (COMPLETE(reg) == REG(ecx))
00182       return useModify;
00183     break;
00184   case istr_stosd:
00185   case istr_stosw:
00186     if (reg == REG(ah)) return useRead;
00187   case istr_stosb:
00188     if (reg == REG(eax)) return useRead;
00189     if (reg == REG(ax)) return useRead;
00190     if (reg == REG(al)) return useRead;
00191     if (COMPLETE(reg) == REG(edi))
00192       return useModify;
00193     break;
00194   case istr_movsb:
00195   case istr_movsw:
00196   case istr_movsd:
00197     if (COMPLETE(reg) == REG(esi))
00198       return useModify;
00199     if (COMPLETE(reg) == REG(edi))
00200       return useModify;
00201     break;
00202   case istr_xchg:
00203     _PRG_ASSERT(numArg == 2);
00204     _PRG_ASSERT(Args[0].type == Param::t_registry);
00205     _PRG_ASSERT(Args[1].type == Param::t_registry || Args[1].type == Param::t_memory);
00206     // caso speciale, stesso registro in tutti gli operandi (nop)
00207     if ( (res&useReadWrite) == useReadWrite && Args[1].type == Param::t_registry)
00208       return useNone;
00209     // gestisce caso in cui sia primo parametro
00210     if (res & useOverwrite)
00211     {
00212       if ( (overwriteMask&useOverwrite) && param)
00213         *param = Args[1]; // !!! per parziale ??
00214       return USE_TYPE(res&overwriteMask);
00215     }
00216     // caso 2o parametro
00217     if (res & useRead && Args[1].type == Param::t_registry)
00218     {
00219       // sovrascrive interamente registro richiesto ?
00220       if ( (REG_INFO(reg).partialMask&REG_INFO(Args[1].mem_reg1).partialMask) == REG_INFO(reg).partialMask)
00221       {
00222         if ( param)
00223           *param = Args[0]; // !!! per parziale ??
00224         return useOverwrite;
00225       }
00226     }
00227     break;
00228   case istr_push:
00229     // !!! push [esp+6] ? push esp
00230     _PRG_ASSERT(numArg == 1);
00231     if (REG(esp) == COMPLETE(reg))
00232       return (res!=useNone?useReadModify:useModify);
00233     if (res != useNone)
00234       return useRead;
00235     break;
00236   case istr_popa:
00237   case istr_popf:
00238     if (REG(esp) == COMPLETE(reg))
00239       return useModify;
00240     break;
00241   case istr_pop:
00242     // !!! pop [esp+6] ? pop esp
00243     // !!! speriamo di non incontrare un pop sp in 32bit (Modify e basta)
00244     _PRG_ASSERT(numArg == 1);
00245     if (REG(esp) == COMPLETE(reg))
00246     {
00247       // caso speciale: pop [esp+x]
00248       if (res&useRead)
00249         return useReadModify;
00250       // caso speciale: pop esp
00251       if (res&useOverwrite)
00252         return useReadWrite;
00253       return useModify;
00254     }
00255     if (res != useNone)
00256     {
00257       if ( (overwriteMask&useOverwrite) && param)
00258         // !!! size and reg constant
00259         *param = Param(Param::Memory,REG(esp),0,Param::memInt32);
00260       return USE_TYPE(res&overwriteMask);
00261     }
00262     break;
00263   case istr_cmp:
00264   case istr_test:
00265     _PRG_ASSERT(numArg==2);
00266     if (res & useReadWrite)
00267       return useRead;
00268     break;
00269   case istr_lea:
00270     _PRG_ASSERT(numArg==2 && Args[1].type == Param::t_memory);
00271     if (res & useReadWrite)
00272       return useModify;
00273     if (res & useOverwrite)
00274     {
00275       if ( (overwriteMask&useOverwrite) && param)
00276       {
00277         // !!! in realta' non sovrascrive con la memoria
00278         _PRG_ASSERT(0);
00279         // !!! e per parziale ?
00280         *param = Args[1];
00281       }
00282       return USE_TYPE(res&overwriteMask);
00283     }
00284     break;
00285   case istr_cdq:
00286     _PRG_ASSERT(numArg == 0);
00287     if (COMPLETE(reg) == REG(eax))
00288       return useRead;
00289     if (COMPLETE(reg) == REG(edx))
00290       return useModify; // !!! potrebbe essere Overwrite ma cosa ci scrivo ??
00291     break;
00292   case istr_div:
00293   case istr_idiv:
00294     {
00295     _PRG_ASSERT(numArg == 1);
00296     _PRG_ASSERT(Args[0].type == Param::t_memory || Args[0].type == Param::t_registry);
00297     _PRG_ASSERT(Args[0].type != Param::t_memory || Args[0].GetMemSize() <= 4);
00298     _PRG_ASSERT(Args[0].type != Param::t_memory || ((1<<Args[0].GetMemSize() )&026)!=0 );
00299     if (res != useNone)
00300       res = useRead;
00301     if (COMPLETE(reg) == REG(eax))
00302       return USE_TYPE(res|useModify);
00303 
00304     // se e' memoria ed e' un byte ritorna
00305     if (Args[0].type == Param::t_memory)
00306     {
00307       if (Args[0].GetMemSize() == 1)
00308         return USE_TYPE(res);
00309     }
00310     else if (REG_INFO(Args[0].mem_reg1).size == reg_info::byte)
00311       return USE_TYPE(res);
00312 
00313     if (COMPLETE(reg) == REG(edx))
00314       return USE_TYPE(res|useModify);
00315     }
00316     return USE_TYPE(res);
00317   case istr_out:
00318     _PRG_ASSERT(numArg == 2);
00319     if (res)
00320       return useRead;
00321     break;
00322   case istr_in:
00323     _PRG_ASSERT(numArg == 2);
00324     // in al,dx o in al,Imm8
00325     // !!! dovrebbe essere Overwrite
00326     return USE_TYPE(res&useReadModify);
00327   case istr_nop:
00328     break;
00329   default:
00330     // !!!
00331 #ifdef DEBUG
00332     fprintf(stderr,"Debug: (UseMode) %s\n",x86instructions_names[instruction]);
00333 #else
00334     static bool bUnimplPassed = false;
00335     if (!bUnimplPassed)
00336     {
00337             fprintf(stderr,"Something is yet unimplemented!\n");
00338       bUnimplPassed = true;
00339     }
00340 #endif
00341 //              exit(1);
00342     throw UseTypeUnimplemented(static_cast<enum x86instructions>(instruction));
00343 #ifdef DEBUG
00344     return USE_TYPE(32);
00345 #endif
00346     break;
00347   }
00348   return useNone;
00349 }
00350 
00351 // !!! aggiungere caso speciale per istruzioni stringa
00352 void Instruction::Write(char* buffer) const
00353 {
00354   char* p = buffer;
00355   strcpy(p,x86instructions_names[instruction]);
00356   p += strlen(p);
00357   // parse special function
00358   switch (instruction)
00359   {
00360   case istr_int3:
00361     strcpy(buffer,"int\t3");
00362     return;
00363   case istr_insb:
00364   case istr_insw:
00365   case istr_insd:
00366   case istr_outsb:
00367   case istr_outsw:
00368   case istr_outsd:
00369   case istr_movsb:
00370   case istr_movsw:
00371   case istr_movsd:
00372   case istr_cmpsb:
00373   case istr_cmpsw:
00374   case istr_cmpsd:
00375   case istr_stosb:
00376   case istr_stosw:
00377   case istr_stosd:
00378   case istr_lodsb:
00379   case istr_lodsw:
00380   case istr_lodsd:
00381   case istr_scasb:
00382   case istr_scasw:
00383   case istr_scasd:
00384     if (segOver == -1)
00385       return;
00386     break;
00387   }
00388   if (numArg)
00389   {
00390     *p++ = '\t';
00391     for (int i=0;i<numArg;++i)
00392     {
00393       const Param &param = Args[i];
00394       if (i!=0)
00395         *p++ = ',';
00396       switch(param.type)
00397       {
00398       default:
00399         _PRG_ASSERT(0);
00400         break;
00401       case Param::t_farliteral:
00402         _PRG_ASSERT(param.mem_reg1 >= 0 && param.mem_reg1 < 0x10000l);
00403         sprintf(p,"%04Xh:",param.mem_reg1);
00404         p += strlen(p);
00405         if (param.GetLiteralSize() == 2)
00406           sprintf(p,"%04Xh",param.literal);
00407         else
00408           sprintf(p,"%08Xh",param.literal);
00409         break;
00410       case Param::t_literal:
00411         if (param.GetLiteralSize() == 1)
00412           sprintf(p,"%02Xh",param.literal);
00413         else if (param.GetLiteralSize() == 2)
00414           sprintf(p,"%04Xh",param.literal);
00415         else
00416           sprintf(p,"%08Xh",param.literal);
00417         break;
00418       case Param::t_registry:
00419         strcpy(p,RegistryInfo::GetInfo(param.mem_reg1)->name);
00420         break;
00421       case Param::t_memory:
00422         // print memory size
00423         if (param.MustWriteMemSize())
00424           switch(param.GetMemSize())
00425           {
00426           default:
00427           case 0:  break;
00428           case 1:  strcpy(p,"byte ptr ");  p+=9;  break;
00429           case 2:  strcpy(p,"word ptr ");  p+=9;  break;
00430           case 4:  strcpy(p,"dword ptr "); p+=10; break;
00431           case 6:  strcpy(p,"fword ptr "); p+=10; break;
00432           case 8:  strcpy(p,"qword ptr "); p+=10; break;
00433           case 10: strcpy(p,"tbyte ptr "); p+=10; break;
00434           }
00435         // write seg over
00436         if (segOver != -1)
00437         {
00438           _PRG_ASSERT( segOver>=0 && segOver<6 );
00439           char c;
00440           switch(segOver)
00441           {
00442           case 0: c = 'e'; break;
00443           case 1: c = 'c'; break;
00444           case 2: c = 's'; break;
00445           case 3: c = 'd'; break;
00446           case 4: c = 'f'; break;
00447           default: _PRG_ASSERT(0);
00448           case 5: c = 'g'; break;
00449           }
00450           *p++ = c;
00451           *p++ = 's';
00452           *p++ = ':';
00453         }
00454         *p++ ='[';
00455         bool begin = false;
00456         if (param.mem_reg1 != null_reg)
00457         {
00458           strcpy(p,RegistryInfo::GetInfo(param.mem_reg1)->name);
00459           p += strlen(p);
00460           begin = true;
00461         }
00462         if (param.mem_reg2 != null_reg)
00463         {
00464           if (begin) *p++ = '+';
00465           strcpy(p,RegistryInfo::GetInfo(param.mem_reg2)->name);
00466           p += strlen(p);
00467           if (param.factor > 1)
00468           {
00469             sprintf(p,"*%i",param.factor);
00470             p += strlen(p);
00471           }
00472           begin = true;
00473         }
00474         if (param.literal != 0 || !begin)
00475         {
00476           if ( (param.literal & 0x80000000lu) && begin)
00477             sprintf(p,"-%08Xh",-param.literal);
00478           else
00479           {
00480             if (begin) *p++ = '+';
00481               sprintf(p,"%08Xh",param.literal);
00482           }
00483           p += strlen(p);
00484         }
00485         *p++ = ']';
00486         *p = '\0';
00487         break;
00488       }
00489       p += strlen(p);
00490     }
00491   }
00492   *p = '\0';
00493 }
00494 
00495 enum FlowTypes Instruction::GetFlowType() const
00496 {
00497   switch(instruction)
00498   {
00499   // ritorno
00500   case istr_ret:
00501   case istr_retf:
00502   case istr_iret:
00503     return FLOW_RET;
00504   // chiamata
00505   case istr_call:
00506     return FLOW_CALL;
00507   // jmp incondizionato
00508   case istr_jmp:
00509     return FLOW_JUMP;
00510   default:
00511         // jmp condizionato
00512         if (x86instructions_names[instruction][0] == 'j')
00513         return FLOW_CJUMP;
00514         return FLOW_NONE;
00515   }
00516 }
00517 
00518 typedef enum { Assign,Negate,Complement,Zero,Xor,Sub,Add,And,Or } Operations;
00519 typedef enum { UsuallyFlag,FlagCarry,FlagZero,FlagParity,FlagNone } FlagCombine;
00520 void Operation1(Operations op,const Param& param,FlagCombine flag)
00521 {}
00522 void Operation2(Operations op,const Param* dst,const Param& p1,FlagCombine flag)
00523 {}
00524 void Operation3(Operations op,const Param* dst,const Param& p1,const Param& p2,FlagCombine flag)
00525 {}
00526 void SetFlag(FlagCombine flag,FlagCombine mask)
00527 {}
00528 
00529 void Instruction::WriteRegUsage(FILE* f) const
00530 {
00531   switch(instruction)
00532   {
00533   case istr_sbb:
00534   case istr_adc:
00535     // leggono in piu' CF
00536     //goto intere;
00537     break;
00538 
00539   case istr_xor:
00540   case istr_sub:
00541     // caso speciale: se 2 registri uguali scrive solo
00542     if (Args[0].RegEqual(Args[1]))
00543     {
00544       Operation1(Zero,Args[0],UsuallyFlag);
00545       break;
00546     }
00547     if (instruction == istr_xor)
00548       Operation3(Xor,&Args[0],Args[0],Args[1],UsuallyFlag);
00549     else
00550       Operation3(Sub,&Args[0],Args[0],Args[1],UsuallyFlag);
00551     break;
00552 
00553   case istr_inc:
00554     Operation3(Add,&Args[0],Args[0],Param(Param::Literal,1,(unsigned char)4),(FlagCombine)(UsuallyFlag&~FlagCarry));
00555     break;
00556 
00557   case istr_dec:
00558     Operation3(Sub,&Args[0],Args[0],Param(Param::Literal,1,(unsigned char)4),(FlagCombine)(UsuallyFlag&~FlagCarry));
00559     break;
00560 
00561     // la maggior parte delle operazioni intere
00562 //intere:
00563     // legge il secondo
00564     // scrive e legge il primo
00565     // scrive flag in base al risultato
00566   case istr_and:
00567     Operation3(And,&Args[0],Args[0],Args[1],UsuallyFlag);
00568     break;
00569 
00570   case istr_or:
00571     Operation3(Or,&Args[0],Args[0],Args[1],UsuallyFlag);
00572     break;
00573 
00574   case istr_add:
00575     Operation3(Add,&Args[0],Args[0],Args[1],UsuallyFlag);
00576     break;
00577 
00578   case istr_neg:
00579     Operation2(Complement,&Args[0],Args[0],UsuallyFlag);
00580     break;
00581 
00582   case istr_not:
00583     // unaria legge e scrive il primo
00584     Operation2(Negate,&Args[0],Args[0],UsuallyFlag);
00585     break;
00586 
00587   case istr_mov:
00588     // sembra uguale alle aritmetiche ma non scrive flag ne legge dest
00589 
00590     // registri uguali e' un NOP
00591     if (Args[0].RegEqual(Args[1]))
00592       break;
00593     //HandleRead(Args[1]);
00594     //HandleWrite(Args[0]);
00595     Operation2(Assign,&Args[0],Args[1],FlagNone); // assegnazione
00596     break;
00597 
00598   case istr_lea:
00599     // caso speciale, NOP complessi
00600     if (Args[1].literal == 0)
00601     {
00602       // lea eax,[eax+0]
00603       if (Args[0].mem_reg1 == Args[1].mem_reg1 && Args[1].mem_reg2 == null_reg)
00604         break;
00605       // lea eax,[eax*1+0]
00606       if (Args[0].mem_reg1 == Args[1].mem_reg2 && Args[1].mem_reg1 == null_reg && Args[1].factor == 1)
00607         break;
00608     }
00609 
00610     // carica costanti
00611     //!!!Operation2(Assign,&TempReg0,Param(ParaM::Literal,Args[1].literal,4),0);
00612     //!!!if (Args[1].mem_reg1 != null_reg)
00613       //!!!Operation3(Add,&TempReg0,TempReg0,Param(ParaM::Registry,Args[1].mem_reg1),0);
00614     if (Args[1].mem_reg2 != null_reg)
00615     {
00616       int s = 1;
00617       switch(Args[1].factor)
00618       {
00619       case 1:
00620         //!!!Operation3(Add,&TempReg0,TempReg0,Param(ParaM::Registry,Args[1].mem_reg2),0);
00621         break;
00622       case 8:
00623         ++s;
00624       case 4:
00625         ++s;
00626       case 2:
00627         //!!!Operation2(Assign,&TempReg1,Param(ParaM::Registry,Args[1].mem_reg2),0);
00628         //!!!Operation3(ShiftLeft,&TempReg1,TempReg1,Param(ParaM::Literal,s,4),0);
00629         //!!!Operation3(Add,&TempReg0,TempReg0,TempReg1,0);
00630         break;
00631       }
00632     }
00633 
00634     //!!!Operation2(Assign,&Args[0],TempReg0,0);
00635     break;
00636 
00637     // uguali aritmetiche ma non modificano destinazione
00638   case istr_test:
00639     Operation3(And,NULL,Args[0],Args[1],UsuallyFlag);
00640     break;
00641 
00642   case istr_cmp:
00643     // registri uguali setta solo flags
00644     if (Args[0].RegEqual(Args[1]))
00645     {
00646       SetFlag((FlagCombine)(FlagParity|FlagZero),UsuallyFlag);
00647       break;
00648     }
00649     Operation3(Sub,NULL,Args[0],Args[1],UsuallyFlag);
00650     break;
00651 
00652   case istr_jnz:
00653     // legge ZF , flusso
00654     break;
00655 
00656   case istr_push:
00657     // !!! no support for 16bit
00658     {
00659     // traduci in sub esp,size src; mov [esp], src
00660     Param resp(Param::Registry,REG(esp));
00661     Operation3(Sub,&resp,resp,Param(Param::Literal,Args[0].GetSize()==2?2:4,(unsigned char)4),FlagNone);
00662     Param stack(Param::Memory,REG(esp));
00663     Operation2(Assign,&stack,Args[0],FlagNone); // assegnazione
00664     }
00665     break;
00666   case istr_pop:
00667     // !!! no support for 16bit
00668     // traduci in mov dst,[esp]; add esp,size dst
00669     {
00670     Param stack(Param::Memory,REG(esp));
00671     Operation2(Assign,&Args[0],stack,FlagNone);
00672     Param resp(Param::Registry,REG(esp));
00673     Operation3(Add,&resp,resp,Param(Param::Literal,Args[0].GetSize()==2?2:4,(unsigned char)4),FlagNone);
00674     }
00675     break;
00676 
00677   case istr_call:
00678     // traduci in sub esp,2/4; mov [esp], next_istr; jmp dst
00679     break;
00680 
00681   case istr_ret:
00682     // traduci in mov temp,[esp]; add esp,2/4; jmp temp
00683     break;
00684   case istr_leave:
00685     // e se parametri ??
00686     // traduci in mov esp,ebp pop ebp
00687     break;
00688 
00689   // qualcosa di sconosciuto
00690   default:
00691     fprintf(f,"unknown");
00692   }
00693   fprintf(f,"\n");
00694 }
00695 

Generated on Mon Jan 13 22:20:34 2003 for perdr by doxygen1.2.15