2011-02-17 11 views
5

मैंने एक साधारण अनुमान लगाने वाला गेम गेम बनाने का निर्णय लिया है जो लिनक्स सिस्टम कॉल का उपयोग करता है, और कुछ सी फ़ंक्शन एक अधिक सरल इंटरफ़ेस प्रदान करने के लिए। मुझे एक सेगमेंटेशन गलती मिलती है जब मैं int को स्ट्रिंग में परिवर्तित करता हूं और सही उत्तर स्क्रीन को प्रिंट करता हूं।NASM अनुमान संख्या गेम गॉन गलत

Enter A Number One Through Ten:" : 
3 
Response did not match! The Answer Is:Segmentation fault 

यहाँ सी कोड है::

// print.c 
#include "/usr/include/stdio.h" 
#include "/usr/include/string.h" 
#include "/usr/include/stdlib.h" 
#include "/usr/include/time.h" 
void print(const char* msg) 
{ 
    printf(msg); 
    return; 
} 
int compare(const char* str, const char* str2) 
{ 
    int i = strcmp(str, str2); 
    if (i == 0) 
    { 
     return 1; 
    } 
    else 
    { 
     return 0; 
    } 
} 
int divide(int num, int dem) 
{ 
    if (dem == 0) 
    { 
     printf("Undefined"); 
     return 0; 
    } 
    else { 
     return (num/dem); 
    } 
} 
int randnum(int maxn) 
{ 

    if (maxn == 0) 
    { 
     maxn = 1; 
    } 
    srand(time(0)); 
    return rand() % maxn; 
} 
int stoi(const char* str) 
{ 
    return atoi("str"); 
} 
void itos(int n) 
{ 

    char* buf = "5"; 
    int ret = sprintf(buf, "%i\n", n); 
    if (ret == -1){ 
    printf("Error!"); 
    return; 
    } 
    else{ 
    printf(buf); 
    } 
    return; 

} 

यहाँ है एनएएसएम कोड:

 
     ; Declared C functions. 
     extern print 
     extern compare 
     extern divide 
     extern randnum 
     extern stoi 
     extern itos 
     section .data 
      msg: db 'Enter A Number One Through Ten:" : ', 10 
      ml: equ $ - msg 
      t: db 'Response did match!', 10 
      tl: equ $ - t 
      f: db 'Response did not match! The Answer Is:', 0 
      fl: equ $ - f 
      str2: db 'Hello' 
     section .bss 
      ;srnum: resb 255 
      snum: resb 255 
      rnum: resb 255 
      num: resb 255 
     section .text 
      global _start ; Entry point function or label. 
     _start: 
      ; System call sys_write 
      mov eax, 4 
      mov ebx, 1 
      mov ecx, msg 
      mov edx, ml 
      int 80h

; System call sys_read mov eax, 3 mov ebx, 0 mov ecx, snum mov edx, 255 int 80h ; Call stoi which converts string to int (parameter 1: is string to convert). push snum call stoi mov [num], eax mov ecx, esp sub ecx, 4 mov esp, ecx ; Call random push 10 call randnum mov [rnum], eax mov ecx, esp sub ecx, 4 mov esp, ecx ; Compare the two integers. mov eax, num cmp eax, [rnum] je true jne false true: ; Call sys_write mov eax, 4 mov ebx, 1 mov ecx, t mov edx, tl int 80h false: ; Segmentation fault is somewhere in this label mov eax, 4 mov ebx, 1 mov ecx, f mov edx, fl int 80h push rnum call itos ; Calling sys_exit with exit code (0 = ERROR_SUCCESS) mov eax, 1 mov ebx, 0 int 80h

+2

सिर्फ शीर्षक के लिए +1 :) – Earlz

+1

ठीक है, मैं अपने पहले झुकाव का विरोध करने जा रहा हूं (जो पूछना है "क्यों? गंभीरता से, क्यों?" :-) मुझे लगता है कि आपके पास सही जवाब है लेकिन मैं हूं उत्सुक क्यों है कि 'एफ' संदेश शून्य समाप्त हो गया है। सिस्कोल 4 के लिए यह आवश्यक नहीं है। शायद यह एक कट और पेस्ट से बचा है? – paxdiablo

+0

डैनियल, आप सिस्टम हेडर के लिए '# शामिल" /usr/include/header.h "के बजाय' # शामिल करें 'का उपयोग कर सकते हैं (जब तक कि कुछ पथ कॉन्फ़िगरेशन समस्या न हो?) – Fernando

उत्तर

4

वहाँ एक है

यहाँ उत्पादन होता है इसके साथ समस्या कोड:

char* buf = "5"; 
int ret = sprintf(buf, "%i\n", n); 

buf स्मृति केवल पढ़ने के लिए सूचक है, और sprintf इसकी सामग्री संशोधित करने में सक्षम होना चाहता है। आप एक सरणी के लिए buf बदलना चाहिए: char buf[20] (या कुछ संख्या 20 के अलावा अन्य है कि मनमाने ढंग से इतना बड़ा अपने वांछित सामग्री धारण करने के लिए है)

+0

चाहे स्ट्रिंग अक्षर केवल पढ़ने योग्य स्मृति में हैं भाषा (सी/सी ++) और कार्यान्वयन परिभाषित है ... यह नहीं कह रहा कि आप इस मामले में गलत हैं। "5" के लिए आवंटित स्मृति वैसे भी उस स्प्रिंटफ के आउटपुट को पकड़ने के लिए पर्याप्त नहीं है, लेकिन उस प्रकार का बफर ओवरफ़्लो आवश्यक रूप से तत्काल क्रैश नहीं करेगा (केवल बाद में :() – Splat

5
void itos(int n) 
{ 

    char* buf = "5"; 

buf में आप 2 वर्ण के लिए जगह है (पांच और \ 0)

लेकिन यहाँ:

int ret = sprintf(buf, "%i\n", n); 

आप इसे में डालने कम से कम 3 वर्ण, संख्या, विराम रेखा \ n के कम से कम एक अंक है, और फिर \ 0।

इस तरह एक शाब्दिक स्ट्रिंग को संशोधित करना भी गलत है।

char buf[] = "5"; // This sample will fail anyway, use a larger string... 

या बेहतर सिर्फ एक खाली सरणी बड़ा enougth कई अंकों के लिए:

char buf[1024]; 
+0

'char buf [] =" 5 "' 2 बाइट्स की एक सरणी आवंटित करेगा, 'sprintf ("% i \ n" ...)' एक बफर ओवरफ्लो का कारण बन जाएगा। बाद के उदाहरण के साथ जाएं: पी – Marlon

+0

@ मार्लोन 'चार buf [] =" नहीं, बस एक दे दो छोटा :-) "' –

+0

हां पहला उदाहरण अभी भी एक बुरा विचार है क्योंकि @ मार्लोन आरक्षित स्थान की वजह से कहता है, और यह भी आवश्यक है क्योंकि इस समस्या में कोई प्रारंभिकता नहीं है :) – Fernando

2

अपने कार्य itos() में, आप करने के लिए प्रयास कर रहे हैं आप अगले रास्ते में एक शाब्दिक स्ट्रिंग के ढेर प्रति घोषणा कर सकते हैं स्ट्रिंग शाब्दिक "5" को संशोधित करें। स्ट्रिंग अक्षर गैर-संशोधित हैं (इस मामले में, आपका ओएस उन्हें केवल पढ़ने के लिए मेमोरी मेमोरी में संग्रहीत करता है)।

इस मामले में, अपने itos() समारोह बेकार में जटिल है - तो आप बस से बदलने सकता है:

void itos(int n) 
{ 
    printf("%i\n", n); 
} 

(..or तुम सिर्फ सीधे अपने एएसएम कोड से printf() कह सकते हैं)।

+0

बहुत बहुत धन्यवाद, मुझे देखना चाहिए था चेतावनियां क्योंकि रोम स्ट्रिंग्स के बारे में आपने जो कहा वह वास्तव में मेरे कंपाइलर द्वारा भविष्यवाणी की जा रही थी। आम तौर पर मैं चेतावनियों को त्याग देता हूं लेकिन हे, आप हर रोज एक नया सबक सीखते हैं। मुझे लगता है कि मेरी समस्या की तुलना में मेरी समस्या बहुत सरल थी। –

+0

इससे कोई फर्क नहीं पड़ता कि उसने मुझे इसके बारे में चेतावनी नहीं दी, उसने मुझे कुछ और चेतावनी दी। किसी भी तरह से धन्यवाद, यह अब काम करता है। –

+0

आपको कभी भी चेतावनियों को अनदेखा नहीं करना चाहिए। अपने कोड को देखने से, आप एक नौसिखिया प्रतीत होते हैं, इस मामले में कि कथन दोगुना सच है। – Dan

संबंधित मुद्दे