NASM猜测数字游戏错了

我决定创build一个简单的使用Linux系统调用的猜数字游戏,以及一些C函数来提供更简单的接口。 当我将int转换为string并在屏幕上输出正确答案时,我似乎遇到了分段错误。

这是输出:

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代码:

       ; 声明的C函数。
        外部打印 
        外部比较
        外部鸿沟
        外部randnum
        外部stoi
        外部itos
        部分.data 
             msg:db'通过十进入一个数字:“:',10
             ml:equ $  -  msg
             t:db'Response did match!',10
             tl:equ $  -  t
             f:db'响应不匹配! 答案是:',0
             fl:equ $  -  f
             str2:db'你好'
        部分.bss
             ; srnum:resb 255
             snum:resb 255
             rnum:resb 255
             num:resb 255
        部分.text
            全球_start; 入口点function或标签。
         _开始:
             ; 系统调用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

这个代码有一个问题:

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

buf是只读内存的指针,sprintf希望能够修改其内容。 你应该把buf改成一个数组: char buf[20] (或者20以外的任意数字,可以容纳你想要的内容)

 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... 

或者更好的只是一个空的数组大数字的数字:

 char buf[1024]; 

在你的函数itos() ,你试图修改字符串文字"5" 。 字符串文字是不可修改的(在这种情况下,您的操作系统将它们存储在映射为只读的内存中)。

在这种情况下,你的itos()函数是不必要的复杂 – 你可以简单地用下面的代替它:

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

(..或者你可以直接从你的asm代码中调用printf() )。