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: https://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