[英]NASM assembly code working before, but not now and is dropping a segmentation fault
[英]Segmentation fault in NASM assembly code
我的匯編程序是YASM,我在64位Linux上編碼。
我使用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輸出
; 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]
不是一個好主意。
我認為你在實現的細節上迷失了,忘記了代碼應該做的事情。 我建議您首先在C中實現代碼,然后逐漸將其更改為類似ASM,直到您可以完全在ASM中編寫它為止。
請注意從sortC1()
中的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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.