Я работаю над школьным проектом с участием NASM, и, хотя язык делает для меня какой-то смысл, у меня всегда возникает проблема, которая не имеет никакого смысла.Ошибка сегментации вызова подпрограммы NASM
Программа, которую я пишу, включает в себя 1 аргумент командной строки, который должен быть строкой 0s, 1s и/или 2s. Если это не так, отображается сообщение об ошибке, и программа заканчивается.
Если ошибок нет, «суффиксы» строки отображаются в порядке.
Пример:
"./sufsort 00100102" should produce
sorted suffixes:
00100102
00102
0100102
0102
02
100102
102
2
Прямо сейчас, я получаю ошибку сегментации, когда я пытаюсь вызвать моей подпрограмму sufcmp
%include "asm_io.inc"
section .data
arg_error_msg: db "Error, incorrect number of arguments. Only 2 arguments are allowed.", 0
bad_char_msg: db "Error, invalid character used. Only 0, 1, or 2 are allowed.", 0
bad_length_msg: db "Error, invalid input length. Length must be between 1 and 30.", 0
sorted_msg: db "sorted suffixes:", 0
; y is an array of suffix indeces, which are sorted later by the main method
y: dd 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
section .bss
argc: resd 1 ; number of command line arguments
X: resb 31 ; array copy of the input string
N: resd 1 ; length of the input string
section .text
global asm_main
sufcmp: ; sufcmp(String Z, int i, int j)
enter 0, 0
pusha
mov edx, dword [ebp+16] ; edx = String Z
mov esi, dword [ebp+12] ; esi = int i
mov edi, dword [ebp+8] ; edi = int j
CMP_LOOP:
cmp byte [edx+esi], byte 0 ; if Z[i] = null, ret -1
je CMP_NEGATIVE
cmp byte [edx+edi], byte 0 ; if Z[j] = null, ret 1
je CMP_POSITIVE
mov al, byte [edx+edi]
cmp byte [edx+esi], al ; if Z[i] < Z[j], ret -1
jl CMP_NEGATIVE
cmp byte [edx+esi], al ; if Z[i] > Z[j], ret 1
jg CMP_POSITIVE
inc esi ; increment i and j
inc edi
jmp CMP_LOOP ; repeat
CMP_NEGATIVE:
popa
mov eax, dword -1
jmp CMP_DONE
CMP_POSITIVE:
popa
mov eax, dword 1
jmp CMP_DONE
CMP_DONE:
leave
ret
asm_main: ; sufsort(String inputString)
enter 0, 0
pusha
ARG_CHECK: ; Check number of arguments
mov eax, dword [ebp+8] ; eax = # of line arguments
cmp eax, dword 2 ; if there are just 2 line argument, skip the error
je CHAR_CHECK
mov eax, arg_error_msg ; display an error message
call print_string
call print_nl
jmp DONE ; terminate the program
CHAR_CHECK: ; Check characters & get length of string
mov ebx, dword [ebp+12]
mov ecx, dword [ebx+4] ; eax = input string
mov edi, dword 0 ; edi will be the counter
CHAR_LOOP:
cmp byte [ecx], byte 0 ; if Z[edi] = null, end the loop
je CHAR_LOOP_DONE
mov al, byte [ecx]
cmp al, '0' ; if byte [ecx} != '0', '1', '2', complain
je GOOD_CHAR
cmp al, '1'
je GOOD_CHAR
cmp al, '2'
je GOOD_CHAR
BAD_CHAR:
mov eax, bad_char_msg ; display an error message
call print_string
call print_nl
jmp DONE ; terminate the program
GOOD_CHAR:
mov [X + edi], al ; copy the character into X[edi]
inc ecx
inc edi
jmp CHAR_LOOP
CHAR_LOOP_DONE:
mov [N], edi ; N = length of Z
mov [X + edi], byte 0 ; add a null character to the end of X
LENGTH_CHECK: ; Check the length of the input string
cmp dword [N], 1 ; if N < 1 or N > 30, stop the program
jl BAD_LENGTH
cmp dword [N], 30
jg BAD_LENGTH
jmp SHOW_COPY ; else, continue
BAD_LENGTH:
mov eax, bad_length_msg ; display an error message
call print_string
call print_nl
jmp DONE ; terminate the program
SHOW_COPY: ; output X to check if it copied properly
mov eax, X
call print_string
call print_nl
BUBBLE_SORT: ; Bubble sort, which sorts substrings using array y
mov esi, [N] ; esi = i (counts from N to 0)
mov edi, dword 1 ; edi = j (counts from 1 to i)
BUBBLE_SORT_I:
cmp esi, dword 0 ; if i = 0, end the outer loop
je SORTED_SUFFIXES
BUBBLE_SORT_J:
cmp esi, edi ; if i = j, end the inner loop
je BUBBLE_SORT_J_DONE
push dword [X] ; call sufcmp, which takes 3 args (String Z, int i, int j)
push dword [edi]
push dword [esi]
call sufcmp
add esp, 12 ; move esp back 12 bytes, to undo the 3 pushes
cmp eax, dword -1
je NO_SWAP
mov ebx, dword [y + edi-1] ; temp = y[j-1]
mov edx, dword [y + edi-1] ; comparison temp
mov edx, dword [y + edi] ; y[j-1] = y[j]
mov [y + edi], ebx
NO_SWAP:
inc edi ; j += 1
jmp BUBBLE_SORT_J
BUBBLE_SORT_J_DONE:
dec esi ; i -= 1
jmp BUBBLE_SORT_I
SORTED_SUFFIXES_T: ; print "sorted suffixes"
mov eax, sorted_msg
call print_string
call print_nl
SORTED_SUFFIXES:
mov esi, dword 0 ; esi = i
PRINT_STR_LOOP:
cmp esi, dword [N-1] ; if i = N-1, end the outer loop
je DONE
mov eax, dword [X] ; move address of X to eax
add eax, [y + esi] ; move eax to address of X[y[i]]
call print_nl ; put each suffix on a separate line
inc esi ; i += 1
jmp PRINT_STR_LOOP
DONE:
popa
leave
ret
И я получаю эту
Я не могу найти ничего, что могло бы вызвать сегмент потому что я не манипулирую стек каким-либо образом, кроме нажатия аргументов функции и восстановления esp после возвращения подпрограммы.
Ошибка сегментации не означает, что с стеком возникает проблема. Это означает, что какой-то указатель где-то недействителен. Я заметил, что вы используете 'pusha' в 32-битном коде, который не делает то, что вы думаете. (Вероятно, вы хотите «pushad».) Пройдите код в отладчике, чтобы найти плохой указатель. –
@RaymondChen: 'pushad' является псевдонимом' pusha', код операции идентичен. CPU будет делать это в зависимости от того, в каком режиме он запускается. Но он определенно нуждается в отладчике в любом случае, также отображается недопустимая заметка указателя. – Ped7g
Используйте отладчик (например, gdb), чтобы узнать, какие инструкции неисправны (и каковы значения регистра в этой точке). См. Http://stackoverflow.com/tags/x86/info, особенно внизу, где есть подсказки gdb. –