Игра угадывания чисел NASM пошла не так - PullRequest
6 голосов
/ 17 февраля 2011

Я решил создать простую игру с угадыванием чисел, которая использует системные вызовы Linux и некоторые функции C, чтобы обеспечить более простой интерфейс. Я, кажется, получаю ошибку сегментации, когда я преобразовываю int в строку и печатаю правильный ответ на экране.

Вот вывод:

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

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

Ответы [ 3 ]

5 голосов
/ 17 февраля 2011
void itos(int n)
{

     char* buf = "5";

В буфере у вас есть место для 2 символов (пять и \ 0)

Но здесь:

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

вы вставляете в него как минимум 3 символа, как минимумодна цифра числа, строка разрыва \ n, а затем \ 0.

Также неверно изменять такую ​​строку.Вы можете объявить стековую копию литеральной строки следующим образом:

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

Или лучше просто большой массив из нескольких чисел:

char buf[1024];
5 голосов
/ 17 февраля 2011

Существует проблема с этим кодом:

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

buf - указатель на постоянную память, и sprintf хочет иметь возможность изменять ее содержимое.Вы должны изменить buf на массив: char buf[20] (или другое число, отличное от 20, которое будет достаточно большим, чтобы вместить желаемое содержимое)

3 голосов
/ 17 февраля 2011

В вашей функции itos() вы пытаетесь изменить строковый литерал "5".Строковые литералы не модифицируются (в этом случае ваша ОС сохраняет их в памяти, отображаемой как доступная только для чтения).

В этом случае ваша функция itos() излишне сложна - вы можете просто заменить ее на

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

(.. или вы можете просто позвонить printf() из своего кода asm).

...