NASM猜测数字游戏错了
我决定创建一个使用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, "%in", 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
此代码存在问题:
char* buf = "5";
int ret = sprintf(buf, "%in", n);
buf
是一个指向只读内存的指针,sprintf希望能够修改其内容。 您应该将buf
更改为数组: char buf[20]
(或者20以外的任何数字,它们的大小足以容纳您所需的内容)
void itos(int n)
{
char* buf = "5";
在buf你有2个字符的空间(五个和 0)
但在这儿:
int ret = sprintf(buf, "%in", 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("%in", n);
}
(..或者你可以直接从你的asm代码中调用printf()
)。