2013-03-05 30 views
6

Ho scritto un piccolo programma c:Dove sono memorizzati i dati di stringa?

#include <stdio.h> 

int main() 
{ 
    char s[] = "Hello, world!"; 
    printf("%s\n", s); 
    return 0; 
} 

che raccoglie al (sulla mia macchina linux):

.file "hello.c" 
    .text 
    .globl main 
    .type main, @function 
main: 
.LFB0: 
    .cfi_startproc 
    pushq %rbp 
    .cfi_def_cfa_offset 16 
    .cfi_offset 6, -16 
    movq %rsp, %rbp 
    .cfi_def_cfa_register 6 
    subq $32, %rsp 
    movq %fs:40, %rax 
    movq %rax, -8(%rbp) 
    xorl %eax, %eax 
    movl $1819043144, -32(%rbp) 
    movl $1998597231, -28(%rbp) 
    movl $1684828783, -24(%rbp) 
    movw $33, -20(%rbp) 
    leaq -32(%rbp), %rax 
    movq %rax, %rdi 
    call puts 
    movl $0, %eax 
    movq -8(%rbp), %rdx 
    xorq %fs:40, %rdx 
    je .L3 
    call __stack_chk_fail 
.L3: 
    leave 
    .cfi_def_cfa 7, 8 
    ret 
    .cfi_endproc 
.LFE0: 
    .size main, .-main 
    .ident "GCC: (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2" 
    .section .note.GNU-stack,"",@progbits 

Non capisco il codice assembly, ma non riesco a vedere da nessuna parte la messaggio di stringa. Quindi, come l'eseguibile sa cosa stampare?

+0

La stringa è una costante nella memoria, dovrebbe essere visibile anche se si apre il file binario con un editor; i dati vengono poi copiati nell'array tramite movl visibile nel tuo smontaggio. – Dariusz

+0

Usa il comando 'stringhe' sul tuo file eseguibile ELF. – cdarke

risposta

12

E 'qui:

movl $1819043144, -32(%rbp) ; 1819043144 = 0x6C6C6548 = "lleH" 
movl $1998597231, -28(%rbp) ; 1998597231 = 0x77202C6F = "w ,o" 
movl $1684828783, -24(%rbp) ; 1684828783 = 0x646C726F = "dlro" 
movw $33, -20(%rbp)   ;   33 =  0x0021 = "\0!" 

In questo caso particolare il compilatore genera le istruzioni in linea per generare la stringa letterale costante prima di chiamare printf. Ovviamente in altre situazioni potrebbe non farlo ma potrebbe invece memorizzare una costante di stringa in un'altra sezione della memoria. In conclusione: non è possibile formulare ipotesi su come o dove il compilatore genererà e memorizzerà le stringhe letterali.

+0

Come decodificare questi valori in ASCII? – kamituel

+1

Utilizzando una [tabella ASCII] (http://www.asciitable.com/). – pmg

+0

Perché se fornisco una stringa più lunga, appare in testo semplice, come: .string "una stringa molto lunga"? – kaspersky

3

la stringa è qui:

movl $1819043144, -32(%rbp) 
movl $1998597231, -28(%rbp) 
movl $1684828783, -24(%rbp) 

Questa copia di un mazzo di valori nello stack. Questi valori sono la tua stringa.

1

stringa costanti sono memorizzate nel file binario dell'applicazione. Esattamente dove sta il tuo compilatore.

1

L'assembly non ha un concetto di "stringa". Quindi, la "stringa" è in realtà un blocco di memoria. La stringa è memorizzata da qualche parte nella memoria (fino al compilatore), quindi è possibile manipolare questo blocco di dati utilizzando il suo indirizzo di memoria (puntatore).

Se la stringa è costante, compilatore potrebbe vuole usarlo come costanti invece di immagazzinarla nella memoria, che è più veloce. Questo è il vostro caso, come ha sottolineato Paul R:

movl $1819043144, -32(%rbp) 
movl $1998597231, -28(%rbp) 
movl $1684828783, -24(%rbp) 

Non si possono fare ipotesi su come il compilatore tratterà la stringa.

0

In aggiunta a quanto sopra, il compilatore può vedere che la stringa letterale non può essere referenziata direttamente (cioè non ci possono essere indicatori validi per la stringa), motivo per cui può semplicemente copiarla in linea. Se invece si assegna un puntatore a carattere, invece, vale a dire

char *s = "Hello, world!";

Il compilatore inizializzare una stringa letterale da qualche parte nella memoria, dal momento che si può ovviamente ora puntare ad esso. Questa modifica produce sulla mia macchina:

.LC0: 
    .string "Hello, world!" 
    .text 
    .globl main 
    .type main, @function 

Un'ipotesi può essere fatta circa letterali stringa: se un puntatore è inizializzata ad un letterale, punterà ad una matrice char statico tenuto trattenuti nella memoria. Di conseguenza il puntatore è valido in qualsiasi parte del programma, ad es. è possibile restituire un puntatore a un valore letterale stringa inizializzato in una funzione e sarà comunque valido.

Problemi correlati