#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, любой совет помог бы.