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, "%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
I have decided to create a simple guessing number game that uses Linux system calls, and some C functions to provide a more simpler interface. I seem to get a segmentation fault when I convert the int to string and print the correct answeron the screen.
Here is the output:
Enter A Number One Through Ten:" :
3
Response did not match! The Answer Is:Segmentation fault
Here is the C code:
// 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;
}
Here is the NASM Code:
; 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这段代码有一个问题:
buf是一个指向只读内存的指针,而sprintf希望能够修改它的内容。
您应该将
buf
更改为数组:char buf[20]
(或 20 以外的某个任意大的数字,足以容纳您想要的内容)There is a problem with this code:
buf
is a pointer to readonly memory, and sprintf wants to be able to modify its contents.You should change
buf
to an array:char buf[20]
(or some number other than 20 that is arbitrarily large enough to hold your desired contents)在 buf 中,您有 2 个字符的空间(五个字符和 \0),
但是在这里:
您在其中插入至少 3 个字符、至少一位数字、换行符 \n,然后是 \0。
以这种方式修改文字字符串也是不正确的。您可以通过以下方式声明文字字符串的堆栈副本:
或者更好的是一个足以容纳几个数字的空数组:
In buf you have space for 2 chars (the five and \0)
But here:
you insert in it at least 3 chars, at least one digit of the number, the break line \n, and then \0.
Also is incorrect to modify a literal string this way. You can declare a stack copy of a literal string in the next way:
Or better just an empty array big enougth for several digits:
在函数
itos()
中,您尝试修改字符串文字"5"
。字符串文字是不可修改的(在这种情况下,您的操作系统将它们存储在映射为只读的内存中)。在这种情况下,您的
itos()
函数不必要地复杂 - 您只需将其替换为:(..或者您可以直接从 asm 代码调用
printf()
)。In your function
itos()
, you are attempting to modify the string literal"5"
. String literals are non-modifiable (in this case, your OS stores them in memory mapped as read-only).In this case, your
itos()
function is needlessly complicated - you could simply replace it with:(..or you could just directly call
printf()
from your asm code).