Написание и отладка минимальной программы в asm - PullRequest
0 голосов
/ 06 октября 2019

Я пытаюсь написать программу, чтобы найти минимальное значение списка целых чисел в asm. Вот что у меня есть:

.section .data

data_items:
    .long 2,3,4,5,1,9,10            # set 10 as the sentinal value

.section text

.globl _start
_start:

    # %ebx holds min
    # %edi holds index (destination index)
    # %eax current data item

    movl $255, %ebx                 # set the current min to 255 
    movl $0, %edi                   # the index is also zero


start_loop:

    movl data_items(,%edi,4), %eax  # set %eax equal to the current data item
    cmpl $10, %eax                  # compare %eax with zero to see if we should exit 
    je exit_loop                    # if it's the sentinel value, exit
    incl %edi                       # increment the index
    cmpl %eax, %edi                 # compare the current value to the current min
    jge start_loop                  # if it's not less than the current value, go to start
    movl %eax, %ebx                 # move the current value if less that the current min
    jmp start_loop                  # always go back to the start if we've gotten this far  

exit_loop:
    movl $1, %eax                   # push the linux system call to %eax (1=exit)
    int $0x80                       # give linux control (so it will exit)      

Когда я запускаю это, я получаю следующее:

$ как min.s -o min.o && ld min. o -o min && ./min

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

Как предполагается отлаживать asm? Например, по крайней мере в C компилятор сообщает вам, в чем может быть ошибка и номер строки, тогда как здесь я знаю практически ничего. (Примечание: ошибка имеет .section text вместо .section .text, но как можно это выяснить?)

1 Ответ

0 голосов
/ 06 октября 2019

Очень возможно в C написать программу, которая компилируется без предупреждений, но вылетает (например, с пустым указателем NULL), и вы увидите точно то же самое. Однако в asm это гораздо более вероятно.

Вы отлаживаете asm с помощью отладчика, например, GDB. См. Советы внизу https://stackoverflow.com/tags/x86/info. И если вы делаете какие-либо системные вызовы, используйте strace, чтобы увидеть, что на самом деле делает ваша программа.

Чтобы отладить это, вы должны запустить его в GDB. и обратите внимание, что в первой инструкции он вышел из строя, movl $255, %ebx. Он не обращается к памяти, поэтому выборка кода должна быть ошибочной. Поэтому в ваших разделах должно быть что-то не так, что привело к тому, что ваш код в разделе был связан с неисполняемым сегментом вашего исполняемого файла.

objdump -d также дал бы вам подсказку: он разбирает .textраздел по умолчанию, и эта программа не имеет его.


Причина, по которой text вместо .text вызывает эту проблему, заключается в том, что значения по умолчанию для разделов со случайными именами, которые не являютсянемногие специально распознаваемые из них - чтение + запись без exec.

В GAS используют .text или .data, специальные директивы для быстрого доступа к .section .text или .data, которые избегают этогопроблема для тех разделов. https://sourceware.org/binutils/docs/as/Text.html

Но не во всех «стандартных» разделах есть специальные директивы, вам все равно нужно .section .rodata, чтобы переключиться на раздел данных только для чтения, где у вас должно иметьпоставь свой массив. (читай, не пиши. На новых инструментальных цепочках тоже нет exec). Вместо того чтобы перейти к разделу .bss, вы можете использовать .comm или .lcomm (https://sourceware.org/binutils/docs/as/bss.html)


). Другая возможная проблема заключается в том, что вы создаете этот 32-битный код как64-битный исполняемый файл (если только вы не используете 32-битную установку, где as --32 является значением по умолчанию). Использование 32-битных режимов адресации работает в 64-битных режимах, усечение адреса до 32 бит. Это работает, когдадоступ к статическим данным в зависящем от позиции исполняемом файле в Linux, потому что весь код + данные связан с низким 2 ГБ виртуального адресного пространства.

Но любой доступ к (%esp) или -4(%ebp) или что-либо другое может привести к ошибкестек в 64-битном процессе отображается на высокий адрес с ненулевыми битами вне 32.

Вы заметили бы эту проблему в GDB, потому что layout reg будет отображать все 16 64-битных целыхрегистры, RAX..R15.

...