【问题标题】:KMP prefix construction with NASM使用 NASM 构建 KMP 前缀
【发布时间】:2015-10-05 12:32:54
【问题描述】:

我正在尝试在 NASM 中实现以下 C 代码,然后将其链接到 C 程序并从那里运行。

我正在尝试实现的代码:

   void preKmp(char *x, int m, int kmpNext[]) {
   int i, j;

   i = 0;
   j = kmpNext[0] = -1;
   while (i < m) {
      while (j > -1 && x[i] != x[j])
         j = kmpNext[j];
      i++;
      j++;
      if (x[i] == x[j])
         kmpNext[i] = kmpNext[j];
      else
         kmpNext[i] = j;
   }
}

我在 NASM 中与我的 cmets 的尝试:

;nasm -f elf32 table.asm -o table.o

segment .bss
kmpNext resd 256


segment .text
global table

table:
    push ebp          ;save the old base pointer value
    mov  ebp,esp      ;base pointer <- stack pointer

    mov eax,[ebp+8]     ;function argument, eax = search_string
    mov ecx, 0          ;i = 0
    mov edx, -1         ;j = -1
    mov [kmpNext], edx  ;kmpNext[0] = -1
oWhile:
    cmp byte [eax + ecx*4], 0  ;end of array control
    je finished
iWhile:
    cmp edx, -1
    jle pass
    mov edi,[eax + ecx*4] ;edi = x[i]
    mov esi,[eax + edx*4] ;esi = x[j]
    cmp edi, esi
    je pass
    mov edx, [kmpNext +edx*4] ;j = kmpNext[j]
pass:
    inc ecx
    inc edx
    mov edi,[eax + ecx*4] ;edi = x[i]
    mov esi,[eax + edx*4] ;esi = x[j]
    cmp edi, esi
    jne store
    mov edi, [kmpNext + edx*4]  ;edi = kmpNext[j]
    mov [kmpNext + ecx*4], edi  ;kmpNext[i] = edi
store:
    mov [kmpNext + ecx*4], edx  ;kmpNext[i] = j
    jmp oWhile
finished:
    mov eax, kmpNext;

    pop ebp
    ret

我在其中调用 NASM 函数的 C 代码:

#include <stdio.h>
#include <string.h>

int* table(char *str);

int main(void)
{
    char str[256];
    int i, n, *pre;

    printf("Enter string: ");
    scanf("%s" , str) ;
    n = strlen(str);
    pre = table(str);
    for (i = 0; i < n; i++){
      printf("%d ", pre[i]);

    }
    printf("\n");
    return 0;
}

一切都编译并运行正常,但输出错误。例如,

对于“可口可乐”,我应该得到:-1 -1 0 -1 0 1 -1 -1

我得到的地方:-1 0 0 0 0 0 0 0

有人能指出我在 NASM 代码中的错误吗?

我怀疑问题出在这一行:

mov esi, [eax + ecx*4]

当我运行调试器时,我没有看到 esi 的内容发生变化。

【问题讨论】:

  • 那么为什么你认为每个人都知道“KMP”是什么意思,而你不需要提供一个清晰的描述呢?使用调试器。
  • 这无关紧要,每个人都有谷歌。我只是在尝试实现我在顶部提供的功能。
  • 这是寻求帮助,这是本网站的规则。否则你应该使用谷歌来找到你问题的答案! “寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题是没有用的给其他读者。请参阅:如何创建minimal reproducible example。"
  • 我的问题很清楚。停止抱怨。如果您想对其他用户有所帮助,请提供答案。我只是没有调试程序集的经验。这就是我不能更精确的原因。
  • 带着这种态度,你最好在 Facebook 上试试。这里的人自愿提供帮助。 EOM

标签: c linux assembly nasm


【解决方案1】:

1) 主要错误是,str 是字节数组(8 位),但您将其视为整数数组(32 位)。

2) 有两个 while 循环。 两个都需要跳回来重复。

3) storeelse 的情况。如果if-case 适合,它不能运行。在这种情况下,适合跳转到oWhile

这是修正后的函数:

table:
    push ebp          ;save the old base pointer value
    mov  ebp,esp      ;base pointer <- stack pointer

    push edi          ; callee saved
    push ebx

    mov eax,[ebp+8]     ;function argument, eax = search_string
    mov ecx, 0          ;i = 0
    mov edx, -1         ;j = -1
    mov [kmpNext], edx  ;kmpNext[0] = -1

oWhile:
    cmp byte [eax + ecx], 0  ;end of array control
    je finished

iWhile:
    cmp edx, -1
    jle pass

    mov bl,[eax + ecx] ; bl = x[i]
    mov bh,[eax + edx] ; bh = x[j]
    cmp bl, bh

    je pass
    mov edx, [kmpNext +edx*4] ;j = kmpNext[j]
    jmp iWhile

pass:
    inc ecx
    inc edx

    mov bl,[eax + ecx] ; bl = x[i]
    mov bh,[eax + edx] ; bh = x[j]
    cmp bl, bh

    jne store
    mov edi, [kmpNext + edx*4]  ;edi = kmpNext[j]
    mov [kmpNext + ecx*4], edi  ;kmpNext[i] = edi

    jmp oWhile

store:
    mov [kmpNext + ecx*4], edx  ;kmpNext[i] = j
    jmp oWhile

finished:
    mov eax, kmpNext;

    pop ebx
    pop edi
    pop ebp
    ret

【讨论】:

  • 我认为仍然缺少一些部分。例如,aaaa 应该返回 -1,0,1,2 rite ?
  • @SpiderRico:它做 C 函数所做的事情。我仍然相信你的算法是错误的。但这不是问题。
  • 啊,你太老实了!我发布的原始算法是错误的。无论如何,我都会使用您的代码。谢谢
  • 或者也许只是一个不同的小鬼。它来自那里 -> www-igm.univ-mlv.fr/~lecroq/string/node8.html
  • @SpiderRico:似乎有不同的算法产生不同的表。我个人对this algorithm 的实现确实产生了 -1,0,1,2 。
【解决方案2】:
oWhile:
    cmp byte [eax + ecx*4], 0

这不等于while (i &lt; m)。应该是:

oWhile:
    cmp ecx,[ebp+12]
    jge finished

您不应该在返回之前mov eax, [kmpNext];它是一个 void 函数(虽然没有害处 - 编译器会忽略返回值)。

此外,您可能需要保存 ediesi 以及可能的其他寄存器,否则调用者可能会感到困惑。检查你的 C 编译器手册。

【讨论】:

  • 这并没有解决问题。问题似乎与比较有关。
  • eax 在我的代码中到底包含什么?它是对我提供的字符串的引用吗?错误似乎与它有关。
  • 如果kmpNext 是整数,请检查寄存器的cmp bl, bh': why load/compare the l` 部分?您应该加载完整的寄存器。您的问题:eax 包含一个指针。您可以正确使用它。
猜你喜欢
  • 2012-11-27
  • 1970-01-01
  • 1970-01-01
  • 2012-08-02
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
  • 2014-05-02
  • 2018-09-15
相关资源
最近更新 更多