我决定创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()
)。