4

我的汇编程序是 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 输出

4

2 回答 2

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]不是一个好主意。

于 2012-04-29T15:45:45.767 回答
3

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

请注意从 C 中小巧、干净且易于理解sortC1()的实现到sortAsm(). 使用您最喜欢的文件比较工具来查看实现之间的哪些变化。

编码:

#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
于 2012-04-30T07:58:06.803 回答