LINUX.ORG.RU

segv при элементарном обходе массива

 ,


0

1

Здарова. Ниже - решение, которое вызывает segv по непонятной причине. пробовал заменить loopneq на loop с ручным выходом, но segv никуда не исчез (loopq вместо loopneq и je exit под cmoveq EXIT_SUCCESS). задача - найти val в arr

.equ QLEN, 8 # размер quadword

.equ SYS_EXIT, 60 # номер выхода

.equ EXIT_FAILURE, 0 # код "не найден"
.equ EXIT_SUCCESS, 1 # код "найден"

.section .data
val: .quad 9 # значение, которое ищем в массиве

len: .quad 5 # длина массива
arr: .quad 4, 9, 3, 8, 4 # массив

.section .text
.globl _start

_start:
  movq val, %rax # грузим val, который ищем в массиве
  movq EXIT_FAILURE, %rdi # грузим код "не найден"

  movq len, %rcx # грузим длину массива
  cmpq $0, %rcx # проверяем на наличие элементов
  je exit # завершаем при отсутствии элементов
loop:
  # итерация с последнего элемента по первый
  movq arr-QLEN(,%rcx,QLEN), %rdx # arr - 8 + rcx * 8 (первая итерация - последний элемент)

  cmpq %rdx, %rax # сравниваем загруженный элемент с val
  cmoveq EXIT_SUCCESS, %rdi # если равен, грузим код успеха

  loopneq loop # если не равен, итерируем (декремент rcx, итерация. если rcx == 1, итерация превратит его в 0 и не прыгнет)
exit:
  movq SYS_EXIT, %rax # грузим код выхода
  syscall # выходим

c чем связан segv? спс


вызывает segv по непонятной причине

Абсолютная адресация в 64битном режиме может вычислять некорректный арес, так как компоновщик размещает дату в произвеольном мете витуальной памяти. Что если использовать относительную?

.equ QLEN, 8

.equ SYS_EXIT, 60
.equ EXIT_FAILURE, 0
.equ EXIT_SUCCESS, 1

.section .data
.align 8
val: .quad 9
len: .quad 5
arr: .quad 4, 9, 3, 8, 4

.section .text
.globl _start
.align 16

_start:
  movq val(%rip), %rax
  movq $EXIT_FAILURE, %rdi
  movq len(%rip), %rcx
  cmpq $0, %rcx
  je exit

  leaq arr(%rip), %rsi

loop:
  movq -QLEN(%rsi,%rcx,QLEN), %rdx
  cmpq %rdx, %rax
  movq $EXIT_SUCCESS, %rdx
  cmoveq %rdx, %rdi
  loop loop

exit:
  movq $SYS_EXIT, %rax
  syscall
LightDiver ★★★★★
()
Ответ на: комментарий от P0085

Из забавного, я сделал такой же код на си - он в 0.4 раза быстрее ассемблерного. Хм, может я криво написал, оченьм мало с ним работаю. Примерно такой же кд на луа всего в 2 раза медленнее, что вообще поражает.

А теперь самое интересное: я сделал такой же код на раст и сишный медленнее в полтора раза.

Ладно, надо больше спать. Что я вообще творю.

LightDiver ★★★★★
()
Последнее исправление: LightDiver (всего исправлений: 1)
Ответ на: комментарий от LightDiver

надо смотреть на дисассембл, мож там другие инструкции. если as и gcc имеют разный уровень оптимизации (например, c может заменить весь цикл на exit(1) :)). насчёт rust и lua хз, но подобное возможно и там (или пляски с линкером в рантайм). спать то да. не спать не получится

P0085
() автор топика
Ответ на: комментарий от P0085

Гланый тормоз - loopne. Я сейчас попробовал dec/jnz - в 4.6 раз быстрее. Все еще медленнее раста вдвое. Но я хз как глянуть во что превращает код раст. Там какие то еще оптимизации свои.

LightDiver ★★★★★
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария