尝试排序字符串元素时出现分段错误

时间:2016-12-18 16:49:56

标签: string sorting assembly x86 nasm

我正在尝试创建一个以字符串作为输入(由0,1和2组成)的程序,并检查字符串[i + 1]元素是否大于字符串[i]。如果它更大,程序返回1,如果它不大,它返回-1。我一直遇到分段错误,我不知道它可能在哪里。

程序的其余部分有更多的代码,但我已经确认其余的工作,并且只在调用“sort”时引发Seg Fault。

我的代码:

sort:  
enter 0,0
pusha

mov edx, dword [ebp+8]        ;address of string
mov edi, dword [ebp+12]       ;first index
mov esi, dword [ebp+16]       ;second index
LOOPYDOOPY:
  cmp byte [edx+edi], 0       ;check if the character at first index is 0
  je RETMINUS                                                   
  cmp byte [edx+esi], 0       ;if character at second is 0
  je RETPLUS
  mov al, byte [edx+esi]      ;if first element is greater than second element
  cmp byte [edx+edi], al
  jl RETMINUS
  cmp byte [edx+edi], al      ;firstt < second
  jg RETPLUS
  inc edi
  inc esi
  jmp LOOPYDOOPY
RETPLUS:
  popa
  mov eax, 1                  ;return 1
  jmp END
RETMINUS:
  popa
  mov eax, -1                 ;return -1
END:
  leave
  ret

1 个答案:

答案 0 :(得分:0)

不,你被证实排序引发了段错误,而不是代码的其余部分正好相反。

实际上排序本身没问题,我从你的问题中1:1复制了它,只添加了调用排序并显示结果的测试(你可以验证我没有修改你的#34中的单个字符;排序:&#34;),它有效:

(要验证转到http://www.tutorialspoint.com/compile_assembly_online.php并粘贴此来源+运行它。)

section .text
    global _start
_start:
    lea ebx,[testString]
    xor ecx,ecx     ; ecx (i) = 0
.loopI:
    cmp [ebx+ecx+2],byte 0
    je  .allCompared  ; not "all", should have been ecx+1 above.
    lea edx,[ecx+1] ; edx (j) = i+1
.loopJ:
    ; call sort
    push edx        ; j
    push ecx        ; i
    push ebx        ; string adr (! OP missing the diff betwen adr and content)
    call sort
    add esp,12
    ; display result
    mov esi,ecx     ; copy i/j to esi/edi
    mov edi,edx
    test eax,eax
    js  .firstWasSmaller
    xchg esi,edi    ; swap esi/edi, esi is "smaller" now
.firstWasSmaller:
    pushad
    call displaySingleString
    mov  edx,lenLess
    mov  ecx,msgLess
    call displayStr
    xchg esi,edi    ; swap esi/edi, esi is "smaller" now
    call displaySingleString
    mov  edx,lenNL
    mov  ecx,msgNL
    call displayStr
    popad
    ; continue in loop
    inc edx
    cmp [ebx+edx],byte 0
    jnz .loopJ
    inc ecx
    jmp .loopI

.allCompared:
    mov eax, 1      ;system call number (sys_exit)
    int 0x80        ;call kernel

displaySingleString: ; display partial string from testString+esi
    mov edx,testLen
    sub edx,esi
    lea ecx,[testString+esi]
displayStr:
    mov ebx, 1      ;file descriptor (stdout)
    mov eax, 4      ;system call number (sys_write)
    int 0x80        ;call kernel
    ret

; original poster code follows, as is (intact):

sort:  
enter 0,0
pusha

mov edx, dword [ebp+8]        ;address of string
mov edi, dword [ebp+12]       ;first index
mov esi, dword [ebp+16]       ;second index
LOOPYDOOPY:
  cmp byte [edx+edi], 0       ;check if the character at first index is 0
  je RETMINUS                                                   
  cmp byte [edx+esi], 0       ;if character at second is 0
  je RETPLUS
  mov al, byte [edx+esi]      ;if first element is greater than second element
  cmp byte [edx+edi], al
  jl RETMINUS
  cmp byte [edx+edi], al      ;firstt < second
  jg RETPLUS
  inc edi
  inc esi
  jmp LOOPYDOOPY
RETPLUS:
  popa
  mov eax, 1                  ;return 1
  jmp END
RETMINUS:
  popa
  mov eax, -1                 ;return -1
END:
  leave
  ret

; read only test data + formatting strings

section .rodata

testString: db '00100102', 0
testLen equ $ - testString - 1

msgLess db  ' < '
lenLess equ $ - msgLess

msgNL   db  0x0a
lenNL   equ $ - msgNL

输出我得到:

sh-4.3$ nasm -f elf *.asm; ld -m elf_i386 -s -o demo *.o
sh-4.3$ demo
00100102 < 0100102
00100102 < 100102
00100102 < 00102
00100102 < 0102
00100102 < 102
00100102 < 02
00100102 < 2
0100102 < 100102
00102 < 0100102
0100102 < 0102
0100102 < 102
0100102 < 02
0100102 < 2
00102 < 100102
0102 < 100102
100102 < 102
02 < 100102
100102 < 2
00102 < 0102
00102 < 102
00102 < 02
00102 < 2
0102 < 102
0102 < 02
0102 < 2
02 < 102
102 < 2
sh-4.3$