NASM汇编代码中的分段错误

时间:2012-04-29 15:38:33

标签: assembly x86-64 nasm yasm

我的汇编程序是YASM,我在64位Linux上编码。

我使用yasm -f elf -m amd64 -g dwarf2 filename.asm汇编并使用ld

进行链接

我正在尝试实施选择排序。 rdirsi指向strbuf2 resb 10数组的各个部分。可能是这种分段错误的原因是什么?第105行和第106行执行完全相同类型的操作,那么为什么它会在第106行而不是第105行崩溃?

我已经包含了代码的相关部分,以及崩溃时的gdbtui屏幕截图。

更新:计数器已修复

; ====== Sorting begins here ======
; Register uses:
; bpl holds the current minimum value
; r8 holds the memory address of the current minimum value
; rdi points to the boundary of the "outer loop"
; rsi points to the boundary of the "inner loop"
sorting:
    mov rdi, strbuf2  ; outer loop pointer
    mov rsi, strbuf2+1  ; inner loop pointer
    mov rax, 1  ; inner loop counter
    mov rbx, 0  ; outer loop counter

innerloop:
    mov bpl, [rdi] ; assume beginning element of unsorted array is minimum

    ; store the value of first element of unsorted array
    mov dl, [rdi]

    ; compare the current small value with the value in rsi
    mov cl, [rsi]   
    cmp bpl, cl 
    jg  new_small

    inc rsi
    inc rax
    cmp rax, 9
    jle innerloop
    jg  innerloop_done

new_small:
    inc rax
    mov bpl, cl; save the new small value
    mov r8, rsi  ; save its index 
    inc rsi 
    cmp rax, 9
    jle     innerloop

innerloop_done:
    ; When the inner loop is completed...
    ; First, do the swap
    ; to swap r8 (target memory address)  with [rdi] (outer array boundary)
    mov dl, 0 ; initialise
    mov dl, [rdi]
    mov [rdi], bpl
    mov [r8], dl 

    inc rdi  ; move the outer loop pointer forward
    inc rsi  ; move the inner loop pointer forward
    inc rbx  ; increment the outer loop counter (the unsorted array becomes smaller)

    ; set the inner loop counter to the appropriate position
    mov rax, 1 
    add rax, rbx  ; now rax (inner loop counter)
                  ; will always be rbx+1 (outer loop counter + 1) 
    cmp rbx, 9  
    jle innerloop
; ====== Sorting ends here ======

分段错误gdb输出

2 个答案:

答案 0 :(得分:4)

; store the value of first element in [small]
mov rdx, [rsi]
mov r9, rdx

; compare the current small value with the value in rsi
mov rcx, [rsi]  
cmp r9, rcx

您正在将[rsi][rsi]进行比较,它们将是平等的......

此外,r8仅在new_small块内初始化 - 如果您从未进入过该块,则写入[r8]不是一个好主意。

答案 1 :(得分:3)

我认为你在实现的细节上迷失了,忘记了代码应该做的事情。我建议您首先在C中实现代码,然后逐渐将其更改为类似ASM,直到您可以完全在ASM中编写它为止。

请注意从sortC1()中C中的小而干净且易于理解的实现到sortAsm()中有点混乱但完全等效的ASM类实现的进展。使用您最喜欢的文件比较工具来查看实现之间的变化。

代码:

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

char strOriginal[11] = "8163045297";
char str[11];

void sortC1(void)
{
  int outIdx, inIdx, minIdx;
  char min, tmp;

  for (outIdx = 0; outIdx < 10; outIdx++)
  {
    minIdx = outIdx;
    min = str[minIdx];

    for (inIdx = outIdx; inIdx < 10; inIdx++)
    {
      if (min > str[inIdx])
      {
        minIdx = inIdx;
        min = str[minIdx];
      }
    }

    tmp = str[outIdx];
    str[outIdx] = min;
    str[minIdx] = tmp;
  }
}

void sortC2(void)
{
  char *outPtr, *inPtr, *minPtr;
  int outCnt, inCnt;
  char min, tmp;

  for (outPtr = str, outCnt = 0;
       outCnt < 10;
       outPtr++, outCnt++)
  {
    minPtr = outPtr;
    min = *minPtr;

    for (inPtr = outPtr, inCnt = 10 - outCnt;
         inCnt > 0;
         inPtr++, inCnt--)
    {
      if (min > *inPtr)
      {
        minPtr = inPtr;
        min = *minPtr;
      }
    }

    tmp = *outPtr;
    *outPtr = min;
    *minPtr = tmp;
  }
}

void sortC3(void)
{
  char *outPtr, *inPtr, *minPtr;
  int outCnt, inCnt;
  char min, tmp;

  outPtr = str;
  outCnt = 0;

  while (outCnt < 10)
  {
    minPtr = outPtr;
    min = *minPtr;

    inPtr = outPtr;
    inCnt = 10 - outCnt;

    while (inCnt > 0)
    {
      if (min > *inPtr)
      {
        minPtr = inPtr;
        min = *minPtr;
      }

      inPtr++;
      inCnt--;
    }

    tmp = *outPtr;
    *outPtr = min;
    *minPtr = tmp;

    outPtr++;
    outCnt++;
  }
}

void sortC4(void)
{
  char *outPtr, *inPtr, *minPtr;
  int outCnt, inCnt;
  char min, tmp;

  outPtr = str;
  outCnt = 0;

outerloop:

  minPtr = outPtr;
  min = *minPtr;

  inPtr = outPtr;
  inCnt = 10 - outCnt;

innerloop:

  if (min > *inPtr)
  {
    minPtr = inPtr;
    min = *minPtr;
  }

  inPtr++;
  inCnt--;

  if (inCnt > 0)
    goto innerloop;

  tmp = *outPtr;
  *outPtr = min;
  *minPtr = tmp;

  outPtr++;
  outCnt++;
  if (outCnt < 10)
    goto outerloop;
}

void sortAsm(void)
{
  char* rdi; // points to the boundary of the "outer loop"
  char* rsi; // points to the boundary of the "inner loop"
  char* r8; // holds the current minimum value
  char r9b; // holds the current minimum value
  char r10b; // temporary storage for character exchange
  long long rbx; // outer loop counter
  long long rax; // inner loop counter

  rdi = str; // initialize outer loop pointer
  rbx = 0; // initialize outer loop counter

outerloop:

  r8 = rdi; // assume current element of partially sorted array is minimum,
  r9b = *r8; // save its index and value

  rsi = rdi; // initialize inner loop pointer
  rax = 10; // initialize inner loop counter
  rax -= rbx;

innerloop:

  // compare the current small value with the value in [rsi]
  if (r9b > *rsi)
  {
    r8 = rsi; // save the new small value's index
    r9b = *r8; // save the new small value
  }

  rsi++; // move the inner loop pointer forward
  rax--; // decrement the inner loop counter
  if (rax > 0)
    goto innerloop;

  // When the inner loop is completed...
  // First, do the swap
  // to swap [r8] (target memory address) with [rdi] (outer array boundary)
  r10b = *rdi;
  *rdi = r9b;
  *r8 = r10b;

  rdi++; // move the outer loop pointer forward
  rbx++; // increment the outer loop counter
  if (rbx < 10)
    goto outerloop;
}

int main(void)
{
  strcpy(str, strOriginal);
  printf("before sorting: %s\n", str);
  sortC1();
  printf("after sorting : %s\n\n", str);

  strcpy(str, strOriginal);
  printf("before sorting: %s\n", str);
  sortC2();
  printf("after sorting : %s\n\n", str);

  strcpy(str, strOriginal);
  printf("before sorting: %s\n", str);
  sortC3();
  printf("after sorting : %s\n\n", str);

  strcpy(str, strOriginal);
  printf("before sorting: %s\n", str);
  sortC4();
  printf("after sorting : %s\n\n", str);

  strcpy(str, strOriginal);
  printf("before sorting: %s\n", str);
  sortAsm();
  printf("after sorting : %s\n\n", str);

  return 0;
}

输出:

before sorting: 8163045297
after sorting : 0123456789

before sorting: 8163045297
after sorting : 0123456789

before sorting: 8163045297
after sorting : 0123456789

before sorting: 8163045297
after sorting : 0123456789

before sorting: 8163045297
after sorting : 0123456789