2011-02-17 77 views
5

我已經決定創建一個簡單的猜數字遊戲,它使用Linux系統調用和一些C函數來提供更簡單的接口。當我將int轉換爲字符串並在屏幕上打印正確答案時,我似乎遇到了分段錯誤。NASM猜數遊戲錯了

這裏是輸出:

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

下面是C語言代碼:

// 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; 

} 

這裏是NASM代碼:

 
     ; 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 2011-02-17 01:30:02

+1

好吧,我要抗拒我的第一個傾向(這是問「爲什麼?認真,爲什麼?」:-)我認爲你有正確的答案,但我是好奇爲什麼`f`消息是空終止的。這對系統調用4不是必需的。也許它是從剪切和粘貼中遺留下來的? – paxdiablo 2011-02-17 02:07:41

+0

Daniel,你可以使用`#include `而不是`#include「/usr/include/header.h」`作爲系統頭文件(除非存在一些路徑配置問題?) – Fernando 2011-02-17 03:00:01

回答

4

有一個這個問題代碼:

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

buf是隻讀存儲器的指針,和sprintf希望能夠修改其內容。 你應該改變buf到一個數組:char buf[20](或大於20的其他一些數字,任意大到足以容納你所需的內容)

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]; 
2

在你的函數itos(),你正試圖您可以在接下來的方式聲明文本字符串的堆棧副本修改字符串文字"5"。字符串文字是不可修改的(在這種情況下,您的操作系統將它們存儲在映射爲只讀的內存中)。

在這種情況下,您的itos()功能是不必要的複雜 - 你可以簡單地將其替換爲:

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

(..或者你可以只直接調用printf()從你的彙編代碼)。