2010-11-10 15 views
5

Sto cercando di capire un po 'di codice:Esistono valori predefiniti per i registri?

jg 0x00000047 
dec esp 
inc esi 
add [ecx],eax 

Qual è il valore di eax? Queste sono le prime quattro frasi del programma e non so se c'è un valore predefinito o se le frasi precedenti aggiungono qualcosa a eax.

Il mio sistema operativo è Linux e l'eseguibile viene compilato da gcc4.3 da un codice sorgente C (gcc file.c exec)

+1

Non 'is', ma' are'. – leppie

+0

Se fornisci alcune informazioni sulla tua piattaforma (sistema operativo, formato eseguibile) sono sicuro che qualcuno può dirti a cosa è impostato "eax" al punto di ingresso del programma. – Edmund

+0

Modificato, grazie per il suggerimento. –

risposta

3

Alcune istruzioni aggiornano implicitamente i registri, anche se le destinazioni non sono elencate esplicitamente nel codice. Alcuni esempi:

  • cpuid valori ritorna in EAX, EBX, ECX, EDX
  • loop decrementi ECX
  • rep istruzioni stringa cambiano ecx, EDI e esi
  • rdmsr cambiamenti EAX e EDX
  • mul e div cambia eax ed edx

E ci sono molti altri esempi.

Non si può supporre solo vedendo che eax non è elencato nel codice che non è cambiato.

Anche supponendo di sapere quali registri sono affetti da quali istruzioni, le uniche volte che avete alcuna garanzia per un valore sono:

  • dopo un'istruzione che si sa aggiorna
  • subito dopo reset hardware

In qualsiasi altro momento, non è mai possibile formulare ipotesi sui valori.

+0

Quindi diremmo che eax ha un valore casuale (almeno casuale per me)? –

+1

@Vaul: sì, vorremmo –

5

dipende dalla piattaforma, la lingua, e/o convenzione di chiamata. Ma sì, il codice prima di questo normalmente dovrebbe avere impostato EAX su qualche valore. EAX è uno di quei registri che è stato modificato così spesso da non essere normalmente utilizzato per tenere oggetti in giro.

Le istruzioni sembrano un po 'casuali. In particolare, il "dec esp" è normalmente un no-no enorme, poiché lo stack dovrebbe sempre essere allineato con dword. Sei sicuro che questo sia il codice vero? I byte di istruzioni si traducono in "\ x7fELF" se sto traducendo correttamente, il che mi suggerisce che si tratta solo dei byte di intestazione di un programma Linux, non di byte di codice reali.

+0

Ho disassemblato un piccolo codice di programma scritto da me in C cercando di capire il codice asm, suppongo che non siano istruzioni casuali. Come dico non ci sono frasi precedenti, quindi eax potrebbe avere un valore casuale. Grazie. –

+0

Come stai smontando il codice? Tieni presente che un eseguibile raramente è solo codice raw. (L'unico formato che conosco sono i file .com, e quelli sono obsoleti da circa 10 anni.) Esiste un intero tipo di formato complesso per gli eseguibili nella maggior parte dei sistemi operativi a 32 bit. – cHao

+0

L'uso di x86dis è ok? –

2

Non sembra un codice valido. Sei sicuro che non fosse un testo?

decodifica come a 32 bit x86 dà stringa ELF:

00: 7F 45 // 0x7F E 
02: 4C  // L 
03: 46  // F 
04: 01 01 // ?? ?? 

Provare ad aprire il file in formato ELF e non solo come binario.

4

Penso che quello che stai veramente chiedendo sia calling convention, che descrive come le subroutine in un programma passano le informazioni l'una all'altra, e come il sistema operativo trasmette le informazioni al programma, e in generale cosa si intende che i diversi registri significano .

Ad esempio, lo cdecl calling convention on the x86, che viene utilizzato dalla maggior parte dei compilatori C, dice che quando una funzione ritorna, il valore del valore di ritorno va sul registro eax. Quindi, se hai una funzione int foo(), sai che dopo foo esegue il suo codice operativo ret, eax conterrà quella int restituita da foo.

Al contrario, il processore PowerPC (di solito) ha (almeno) 32 registri, semplicemente chiamati r0, r1, ... r31. The AIX calling convention per questo chip dice che il puntatore dello stack va su r1, che i parametri di funzione vengono passati da r3 a r11, che i valori di ritorno ritorna su r3 e così via.

È importante ricordare che una convenzione di chiamata è un po 'come un accordo tra le funzioni di un programma o tra le librerie. Non fa parte dell'hardware o di una legge e di solito esistono molte convenzioni di chiamata diverse che possono essere utilizzate su una piattaforma. Questo è il motivo per cui a volte si vedrà il codice come

struct CFoo { void __stdcall method(); }; 

Questo è un'istruzione per MSVC, che di solito ama usare la convenzione fastcall, dicendogli di utilizzare una convenzione diversa per quella funzione. Questo è importante se , ad esempio, la funzione è definita in una libreria creata da un altro compilatore che utilizza invece stdcall.

Quando parliamo di come il sistema operativo trasmette le informazioni a un programma (o l'hardware al sistema operativo), di solito lo chiamiamo un ABI invece di una convenzione di chiamata, ma è la stessa idea. Quindi, nel caso del tuo programma, è stato scritto assumendo che il sistema operativo avrebbe passato alcune informazioni particolari su eax. Tale ipotesi sarebbe particolare per il sistema operativo, il compilatore e, eventualmente, anche per il singolo programma.

+0

Grazie mille, questo mi dà un buon punto per capire ASM. –

Problemi correlati