【发布时间】:2019-12-08 20:57:53
【问题描述】:
我想在 x86 中编写一个函数,该函数将从 C 程序中调用。
该函数应如下所示:
char *remnth(char *s, int n);
我希望它从字符串 s 中删除每个第 n 个字母并返回该字符串。这是我的 remnth.s 文件:
section.text
global remnth
remnth:
; prolog
push ebp
mov ebp, esp
; procedure
mov eax, [ebp+8]; Text in which I'm removing every nth letter
mov ebx, [ebp+12]; = n
mov ecx, [ebp+8] ; pointer to next letter (replacement)
lopext:
mov edi, [ebp+12] ; edi = n //setting counter
dec edi ; edi-- //we don't go form 'n' to '1' but from 'n-1' to '0'
lop1:
mov cl, [ecx] ; letter which will be a replacement
mov byte [eax], cl ; replace
test cl,cl ; was the replacement equal to 0?
je exit ; if yes that means the function is over
inc eax ; else increment pointer to letter which will be replaced
inc ecx ; increment pointer to letter which is a replacement
dec edi ; is it already nth number?
jne lop1 ; if not then repeat the loop
inc ecx ; else skip that letter by proceeding to the next one
jmp lopext ; we need to set counter (edi) once more
exit:
; epilog
pop ebp
ret
问题是,当我在 C 中从 main() 调用此函数时,出现分段错误(核心转储)
据我所知,这与指针高度相关,在这种情况下,我将返回 *char,并且由于我已经看到一些返回 int 的函数并且它们工作得很好,我怀疑我忘记了正确返回 *char 很重要。
这是我的 C 文件的样子:
#include <stdio.h>
extern char *remnth(char *s,int n);
int main()
{
char txt[] = "some example text\0";
printf("orginal = %s\n",txt);
printf("after = %s\n",remnth(txt,3));
return 0;
}
任何帮助将不胜感激。
【问题讨论】:
-
您使用的是哪种 C 调用约定?上面的代码既不遵循 Microsoft 也不遵循 unix 约定。
-
@RaymondChen linux (unix),会不会是问题出在哪里?
-
了解linux的寄存器保存规则。具体来说,您没有保留 ebx 或 edi。
-
尝试一个更简单的程序,它只调用
remnth并将结果存储在一个变量中。然后查看调试器以单步执行该函数并查看返回的内容。 +1 给@TonyK。已经有一个计算机程序,其目的是获取 C 代码并将其转换为汇编。它被称为编译器。 -
看起来你正在返回一个指向新字符串 end 的指针。这实际上是一件好事。调用者已经知道它在开始时传递了什么地址。所以这让它计算长度,例如将其传递给
write系统调用或其他显式长度使用。不要丢掉工作(比如找到长度);strcat这样的 C 函数设计是一个糟糕的模型,它们很难有效地使用。
标签: c assembly x86 nasm inline-assembly