LINUX.ORG.RU

с++, nasm, массивы и деление

 , ,


0

2

Ввожу массив через С++, вызываю ассемблеровскую функцию, которая каждый элемент массива делит на два, а потом вывожу через С++:

main.cpp

#include <iostream>

extern "C" void ms(int *, int);

int main()
{
	int n = 3;
	int b[n];

	std::cout << "Введите массив: " << std::endl;

	for (int i = 0; i < n; i++)
	{
		std::cout << "array[" << i << "]: ";
		std::cin >> b[i];
	}

	ms(b, n);

	std::cout << "Результат: " << std::endl;

	for (int i = 0; i < n; i++)
	{
		std::cout << "array[" << i << "]: " << b[i] << std::endl;
	}

	return 0;
}

main.asm

section .text

global ms

ms:
	mov rbx, 0
	mov rcx, rsi

	cycl:

	mov rax, [rdi+rbx*4]

	push rbx
		mov rbx, 2
		xor rdx, rdx
		;add rax, rbx
		div rbx
	pop rbx

	mov [rdi+rbx*4], rax

	inc rbx

	loop cycl

Makefile

TARGET=main

.PHONY: all cln

all: $(TARGET)

$(TARGET): main.cpp main-asm.o
	g++ main.cpp main-asm.o -o $@
main-asm.o: main.asm
	nasm -f elf64 main.asm -o $@
cln:
	rm -rf $(TARGET) main-asm.o

mov [rdi+rbx*4], rax

Можно заменить на mov [rdi+rbx*4], eax,
eax - 4 младших байта от rax.
А rax - 64-битный регистр, потому каждый раз перезаписывает лишний int в массиве, а в конце вообще выходит за границу массива

TheAnonymous ★★★★★
()
Последнее исправление: TheAnonymous (всего исправлений: 1)

или можно поменять инты на long long, и читать по 8 байт

TheAnonymous ★★★★★
()
Ответ на: комментарий от xaizek

А вот насчёт rbx не совсем понял, можно подробнее? Уже понял.

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

Вполне вероятно что нет. Оптимизировать отдельные инструкции не имеет смысла. Код сгенерённый нормальным компилятором работает быстрее ваших потуг, тк учитывает шедулинг инструкций и прочие вещи, о которых вы представления или не имеете, либо не способны составить в голове общую картину.

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

нормальным компилятором

у ТСа редкостное говно - g++, а нормальным да, ручная оптимизация ни к чему.

anonymous
()
Ответ на: комментарий от svh50696

ret обязателен даже если void?

Конечно. Он же не данные возвращает, а управление. Оно без него работает случайно (там где-то дальше в памяти ret попался).

xaizek ★★★★★
()
Ответ на: комментарий от anonymous

у ТСа редкостное говно - g++, а нормальным да, ручная оптимизация ни к чему.

тут ниже должен быть список «нормальных», или балабол :) Хотя все эти древние трюки в гамаке на лыжах с делением-умножением сдвигом из времен i386, про которые вчера узнал мамкин оптимизатор, не нужны от слова совсем чуть более чем везде.

anonymous
()

На сколько я знаю, использование asm инструкции div в более менее
новых CPU очень медленное, поэтому во всех компиляторах
операция оптимизируется до нескольких инструкций и умножения.
http://libdivide.com/

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

А loop вообще тормозная с аж 386-х. Но тут ТС тренируется стыковать ассемблерные реализации с сишными.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

Ты хороший анонимус, не пудришь мозг всякими шедулингами.

superuser ★★★★★
()
Последнее исправление: superuser (всего исправлений: 1)

А еще можно написать код ms на плюсах в https://godbolt.org/ и развлекаться с результатом. Тока позаботиться, чтобы он не заинлайнился (написать только ms(), например). Заодно станет понятно, что массив у тебя из int, а деление беззнаковое.

https://godbolt.org/z/EwLzhj

/* -O3 -mno-sse */
ms:
        test    esi, esi
        jle     .L1
        lea     eax, [rsi-1]
        lea     rcx, [rdi+4+rax*4]
.L3:
        mov     edx, DWORD PTR [rdi]
        add     rdi, 4
        mov     eax, edx
        shr     eax, 31
        add     eax, edx
        sar     eax
        mov     DWORD PTR [rdi-4], eax
        cmp     rdi, rcx
        jne     .L3
.L1:
        ret
anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.