4

私のアセンブラーはYASMで、64ビットLinuxでコーディングしています。

ldを使用して組み立てyasm -f elf -m amd64 -g dwarf2 filename.asm、ldを使用してリンクします

選択ソートを実装しようとしています。rdi配列のさまざまな部分をrsi指してい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()から、やや面倒ではあるが完全に同等な での ASM に似た実装への進行に注意してください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 に答える