【问题标题】:Segmentation fault when trying to sort string elements尝试对字符串元素进行排序时出现分段错误
【发布时间】:2017-05-03 19:10:51
【问题描述】:

我正在尝试制作一个程序,它将字符串作为输入(由 0、1 和 2 组成),并检查 string[i+1] 元素是否大于 string[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

【问题讨论】:

  • 如果您与this one 的发帖人不同,那么也请检查这个,也是我的答案,它可能会对您的代码有所帮助,因为任务看起来与您的代码相同质量看起来也很相似。

标签: string sorting assembly x86 nasm


【解决方案1】:

不,您已确认排序引发了段错误,而不是其余代码有效,完全相反。

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

(要验证,请转到 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$

【讨论】:

  • 我不太明白您在回答的第一行中所说的内容。你是说他的原始代码工作正常,没有段错误?否则,你对他的代码做了什么改动?
  • @CodyGray 确切地说,有问题的代码可以正常工作。我没有改变它的任何东西。我只是正确地调用它,所以它不会出现段错误。我有点猜想 OP 在原始代码中有类似buffer: resb 32 的东西,并在使用push dword [buffer] 而不是push buffer 调用之前将其作为参数。然后排序例程在无效内存访问时出现段错误,因为[ebp+8] 不是buffer,而是类似于0x30313030 ('0010')。 (不知何故,我希望我的回答能给 OP 提供如何在 x86 程序集中编写某些东西的新想法)。
猜你喜欢
  • 2016-06-16
  • 1970-01-01
  • 1970-01-01
  • 2011-09-03
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多