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