2017-02-13 3 views
0

Я пытаюсь написать код, который принимает 3 массива и возвращает максимальное число в последнем (да что-то вроде в книге ProgramminGroundUp), но я хочу, чтобы функция выходила в зависимости от размера массива не тогда, когда она достигает нулевого элемента но код Гав мнеОшибка сегментации (core dumbed) x86 Сборка синтаксиса AT & T

Segment fault (Core Dumped) 

Я использую «как» ассемблере»и ГНУ погрузчиком„л.д.“ Вот полный код

.section .data 
first_data_items: 
.long 48,65,49,25,36 
second_data_items: 
.long 123,15,48,67,25,69 
third_data_items: 
.long 102,120,156,32,14,78,100 
.section .text 
.globl _start 
_start: 
pushl $first_data_items 
pushl $5 
call max 
addl $8, %esp 
pushl $second_data_items 
pushl $6 
call max 
addl $8, %esp 
pushl $third_data_items 
pushl $7 
call max 
addl $8, %esp 
movl %eax, %ebx 
movl $1, %eax 
int $0x80 

.type max, @function 
max: 
pushl %ebp 
movl %esp, %ebp 
movl 8(%ebp), %ecx #ecx will be the size of the array 
movl 12(%ebp), %ebx #ebx will be the base pointer 
movl $0, %edi   #edi will be the index 
movl 0(%ebx, %edi, 4), %eax #eax will hold the maximum number 
start_loop: 
cmpl $0, %ecx 
je end_loop 
incl %edi 
movl 0(%ebx, %edi,4), %esi  #esi will hold the current element 
cmpl %eax, %esi 
jle start_loop 
movl %esi, %eax 
decl %ecx 
jmp start_loop 
end_loop: 
movl %ebp, %esp 
popl %ebp 
ret 
+2

Что скажете, когда вы входите с отладчиком, например _GDB_? Мне кажется, что есть две очевидные проблемы. Вы зацикливаетесь на одно дополнительное время, чем следует, после 'movl 8 (% ebp),% ecx' Я думаю, вам нужно уменьшить _ECX_ на 1. Более важно, когда вы получите текущее значение в массиве с' movl 0 (% ebx, % edi, 4),% esi' вы сравниваете его с текущим высоким значением в _EAX_. Если новое значение меньше, вы неверно возвращаетесь к start_loop с помощью 'jle start_loop'. Выполнение этого не делает 'decl% ecx' Вам нужно перейти через' movl% esi,% eax' в 'decl% ecx', если текущее значение меньше текущего max –

+0

Или переписать чтение элементов массива с помощью' lodsd 'и завершить цикл, когда' esi> = array.end() 'address, что, вероятно, значительно сократит количество инструкций. – Ped7g

+0

Я решил, что проблема была в том, что Майкл Петч сказал, что мне нужно уменьшить ecx, поэтому я переместил инструкцию decl сразу после сравнения между 0 и ecx, и он отлично работает, Thx – Nasser

ответ

0

I переехали decl %ecx (Th anks Майклу Petch) сразу после сравнивающейся statemnt сделать ECX декремент на 1 в каждом цикле поэтому код будет

.section .data 
first_data_items: 
.long 48,65,49,25,36 
second_data_items: 
.long 123,15,48,67,25,69 
third_data_items: 
.long 102,120,156,32,14,170,100 
.section .text 
.globl _start 
_start: 
pushl $first_data_items 
pushl $5 
call max 
addl $8, %esp 
pushl $second_data_items 
pushl $6 
call max 
addl $8, %esp 
pushl $third_data_items 
pushl $7 
call max 
addl $8, %esp 
movl %eax, %ebx 
movl $1, %eax 
int $0x80 
.type max, @function 
max: 
pushl %ebp 
movl %esp, %ebp 
movl 8(%ebp), %ecx #ecx will be the size of the array 
movl 12(%ebp), %ebx #ebx will be the base pointer 
movl $0, %edi   #edi will be the index 
movl 0(%ebx, %edi, 4), %eax #eax will hold the maximum number 
start_loop: 
cmpl $0, %ecx 
je end_loop 
decl %ecx 
incl %edi 
movl 0(%ebx, %edi,4), %esi   #esi will hold the current element 
cmpl %eax, %esi 
jle start_loop 
movl %esi, %eax 
jmp start_loop 
end_loop: 
movl %ebp, %esp 
popl %ebp 
ret 
0

О мой комментарий о lodsd использования, пример max функции:

.type max, @function 
max: 
    pushl %ebp 
    movl %esp, %ebp 
    movl 8(%ebp), %ecx  # ecx will be the size of the array 
    movl 12(%ebp), %esi  # esi will be the base pointer 
    popl %ebp    # stack_frame usage complete, restore ebp 
    lea  (%esi,%ecx,4), %ecx # ecx = (base pointer + 4*size) (end() ptr) 
    mov  $0x80000000,%edi # current max = INT_MIN 
start_loop: 
    cmp  %ecx, %esi 
    jae  end_loop   # end() ptr reached (esi >= ecx) 
    lodsl      # eax = [esi+=4] 
    cmp  %edi, %eax   # check if it is new max 
    cmovg %eax, %edi   # update max as needed (eax > edi) 
    jmp  start_loop   # go through whole array 
end_loop: 
    mov  %edi, %eax   # eax = current_max 
    ret 

(CMOVcc требует архитектуры i686 + target)

+0

На самом деле у меня есть googled, но похоже Я не дошел до него в книге, которую я использую. (Программирование на земле вверх) Но это выглядит неплохо, Thx для ура усилия это действительно помогло мне растянуть мои мысли – Nasser

+0

@Nasser: Вы имеете в виду 'lods' себя? Ну, в этом случае он может быть записан как «mov (% esi),% eax'' добавить $ 4,% esi' -> код должен оставаться« простым »для вас (надеюсь) ... Если вы означает «CMOVcc», то да, этот для меня тоже «новый» (я знаю это всего около 10 лет), поскольку он не был доступен, когда я программировал на сборке x86 (80586 был новейшим), поэтому я все еще чувствую себя немного странно, когда я его использую. «Строковое» семейство функций 'lods/stos/movs/scans/cmps' является частью x86 с первого 8086. – Ped7g

+0

Отлично, это похоже на новую инструкцию, которую я использую для изучения, не включает ее, это был действительно полезен – Nasser

Смежные вопросы