Ошибка сегментации сравнения матриц сборки

#assembly #x86

#сборка #x86

Вопрос:

Моя цель — загрузить значения в матрицу 5×5, сравнить каждое значение и распечатать наибольшее число.

После запуска отладчика я получаю :

 0x080480bb < 0>:     mov    esi,DWORD PTR [eax edi*1]

0x080480be < 3>:     jmp    0x804809d <loop>
  

 segment .data
    matrix db   1,62,3,44,35, 
            61,52,43,45,55, 
            17,23,37,74,65, 
            13,12,93,94,95, 
            31,21,13,14,25

segment .bss

holder  resb    4

counter resb    4


segment .text

global _start

_start:

    mov eax, matrix
    call big

big:
    mov esi, holder
    mov edi, counter
    mov edi, 0
    jmp switch

loop:
    inc edi
    cmp esi, [eax   edi]
    jg switch
    cmp edi, 25 
    jle loop
    mov eax, [esi]
    sub eax, '0'
    mov eax, 4              
    mov ebx, 1
    mov ecx, esi
    mov edx, 4
    int 0x80

switch:
    mov esi, [eax   edi]
    jmp loop

exit:
    mov eax, 1
    xor ebx, ebx
    int 0x80
  

Комментарии:

1. Я отформатировал ваш код для вас (в будущем выделите весь ваш код, а затем нажмите Ctrl K или { } кнопку). Итак, используете ли вы отладчик уровня сборки? Если нет, то это первый шаг.

2. mov esi, holder перемещает адрес из holder в esi . Вероятно, вам нужен, mov esi, [holder] который перемещает содержимое holder в esi. Аналогично для edi. Вы также неправильно обрабатываете свои данные размером в байт.

3. @user786653 хорошо, я выполнил вышеуказанные настройки, я все еще, кажется, получаю ту же ошибку «Ошибка сегмента», это странно, логически это имеет смысл и должно работать, но ошибка сегмента на самом деле ничего для меня не значит, Грег спасибо, я запомню совет в следующий раз 🙂

4. я запустил отладчик, и он выдает: 0x080480bb < 0>: перемещение esi,DWORD PTR [eax edi * 1] 0x080480be < 3>: jmp 0x804809d <цикл>

Ответ №1:

Я вижу некоторые проблемы в вашем коде. Вот первая:

 cmp edi, 25 
jle loop
mov eax, [esi]   <--
sub eax, '0'
mov eax, 4 
  

На этом этапе вы проверили всю матрицу и хотите записать наибольшее найденное значение, которое уже есть в esi, поэтому вам не нужно разыменовывать, чтобы получить его. Кроме того, вы должны добавлять ‘0’ для чисел от 0 до 9, поэтому преобразование также неверно. И, наконец, после преобразования вы перезаписываете значение в eax, которое поэтому теряется.
Реальная ошибка сегментации, однако, происходит здесь,

 mov esi, [eax   edi]   <--
jmp loop
  

Сразу после записи результата. Проблема в том, что ecx должен содержать указатель на строку с нулевым завершением для записи. Вместо этого вы вводите в него число, которое хотите записать, что является неопределенным поведением (это означает, что все может произойти). Теперь eax содержит возвращаемое значение write, поэтому я предполагаю, что произошла ошибка, и eax теперь содержит -1, что приводит к сегментации. ошибка.
Одним из простых способов решения этой проблемы является добавление jmp exit после записи значения.

И, последнее, но не менее важное (и, как сказал @user786653), «неправильная обработка ваших данных размером в байт». Что это значит? По сути, ваша матрица представляет собой массив байтов, но каждый раз, когда вы читаете из памяти, вы извлекаете по 4 байта за раз. Самое простое решение — объявить вашу матрицу как массив из двух слов (dd или dword вместо db) и умножить смещение на 4 (пример: перемещение eax, [ebx ecx * 4]).

Да ладно, не волнуйся! Сборка — сложный зверь для игры 😉

Редактировать:
Часть, которая находит наибольшее число, верна. Вам просто нужно исправить часть «вывода» и адресацию, о которой я говорил ранее. На мой взгляд, если вы используете шестнадцатеричную базу для своих чисел, преобразовать ее в строку для печати будет намного проще (вы можете умножить на 2 ^ n, сдвинув влево на n мест -> shl eax, 5 = eax *= 32)

Комментарии:

1. небольшая поправка: это dd не dw для определения двойных слов (последнее определяет слова, используя древнюю терминологию). (И они должны быть индексированы на * 4 местами)

2. @BlackBear я думаю, что моя самая большая проблема прямо сейчас — это извлечение значения из матрицы, которая хранится в массиве, и отображение его на экране: S я не могу поверить, что выполнить такую маленькую процедуру в сборке намного сложнее

3. @Shawnricshawnawic: Найдите другие сообщения на этом сайте, в которых спрашивается о сборке / преобразовании / шестнадцатеричном / ascii. Также вы можете захотеть выполнить поиск, загрузить и включить Irvine32.inc для всех ваших потребностей в консоли. (или посмотрите на исходный код)

4. Эй, я внес изменения выше, но забавно, что я все еще получаю ошибку сегментации, вот изменения, которые я внес: 1) Изменил тип массива на dd 2) при преобразовании я добавляю ‘0’ 3) в моем коммутаторе, который я написал сразу после цикла jmp, я ввел jmp exit: S, что странно, поскольку это все еще не работает, ребята, мне действительно могла бы понадобиться ваша помощь в этом, так как я чувствую, что я близок, но пока нет сигары

5. ^^^ @BlackBear, любой совет помог бы.