Я пытался использовать AVX в программе Мандельброта, и это не работает правильно.
Я пытаюсь его отладить, но GDB отказывается показывать мне значения с плавающей запятой в регистрах YMM. Вот минимальный пример
т.к
#include <stdio.h>
extern void loadnum(void);
extern double input[4];
extern double output[4];
int main(void)
{
/*
input[0] = 1.1;
input[1] = 2.2;
input[2] = 3.3;
input[3] = 3.14159;
*/
printf("%f %f %f %f\n",input[0],input[1],input[2],input[3]);
loadnum();
printf("%f %f %f %f\n",output[0],output[1],output[2],output[3]);
return 0;
}
л.асм
section .data
global input
global output
align 64
input dq 1.1,2.2,3.3,3.14159
output dq 0,0,0,0
section .text
global loadnum
loadnum:
vmovapd ymm0, [input]
vmovapd [output],ymm0
ret
как это скомпилировано
OBJECTS = t.o l.o
CFLAGS = -c -O2 -g -no-pie -mavx -Wall
t: $(OBJECTS)
gcc -g -no-pie $(OBJECTS) -o t
t.o: t.c
gcc $(CFLAGS) t.c
l.o: l.asm
nasm -felf64 -gdwarf l.asm
Выход
> 1.100000 2.200000 3.300000 3.141590
> 1.100000 2.200000 3.300000 3.141590
который показывает, что он загружает и сохраняет эти двойники, как и ожидалось, но в gdb он показывает
> gdb t (followed by some boilerplate)
> Reading symbols from t...
> (gdb) b loadnum
> Breakpoint 1 at 0x4011b0: file l.asm, line 15.
> (gdb) run
> Starting program: /somedir/t
> 1.100000 2.200000 3.300000 3.141590
> Breakpoint 1, loadnum () at l.asm:15
> 15 vmovapd ymm0, [input]
> (gdb) n
> 16 vmovapd [output],ymm0
> (gdb)
тогда я говорю
> (gdb) info all-registers
и это проявляется.
> ymm0 (blah blah) v4_double = {0x1, 0x2, 0x3, 0x3}
когда я ожидал, что это покажет
> ymm0 (blah blah) v4_double = {1.100000 2.200000 3.300000 3.141590}
None of the other fields show anything like that, unless you want to parse the floating point bits
> v4_int64 = {0x3ff199999999999a, 0x400199999999999a, 0x400a666666666666, 0x400921f9f01b866e}
Как я могу это исправить?
Спасибо, "display $ymm0.v4_double" сработало прекрасно! Теперь, если бы вы добавили это в ответ, я мог бы принять это.
Поскольку я опубликовал это, у меня возникла проблема с загрузкой vars и отображением странных результатов в gdb, изменение «align 32» на «align 64» исправило это, если кто-нибудь попытается собрать этот код. Отредактировал оригинал, пока я был на нем.
Это не должно иметь никакого значения для правильного кода и правильного использования GDB. (Если нет ошибок GDB). Необычность вашего исходного кода заключалась в том, что он не использует относительную RIP-адресацию для статических данных (default rel) и что источник и место назначения были в .data, а не копировались из .rodata в .bss. Хотя это правдоподобно для реального случая использования, когда другой код, не показанный здесь, может изменить исходные данные, и, возможно, вы хотите, чтобы место назначения находилось в той же строке кэша, если в некоторых случаях это лучше для производительности.





p $ymm0.v4_double (команда print) по умолчанию использует десятичное форматирование.
Используйте p /whatever для других форматов, например p /x $ymm0.v4_int64, чтобы увидеть шестнадцатеричный формат битовых шаблонов. help p больше.
display $ymm0.v4_double может работать в качестве замены layout reg + tui reg vec, поскольку в некоторых версиях содержит ошибки/неисправен, и всегда является бесполезной мешаниной различных форматов для таких широких и многочисленных регистров, как ymm0-15. Он принимает те же параметры, что и print, и печатает перед каждым приглашением. (undisplay 1 или undisplay (все), чтобы отключить некоторые настроенные вами выражения.)
Он может быть загроможден в режиме TUI (layout asm или layout reg + layout next, чтобы увидеть целочисленные регистры и дизассемблирование), если вы хотите отслеживать более пары регистров, поэтому вы можете предпочесть использовать режим без TUI, либо не используйте layout в первое место или tui dis.
(При отладке написанного от руки ассемблера я почти всегда хочу смотреть на дизассемблирование, а не на исходный код; но, может быть, для сложного алгоритма я иногда хотел бы видеть исходный код с комментариями в качестве напоминания о том, какими значения должны быть/значить в определенный момент времени. точка.)
p $ymm0.v4_doubleпо умолчанию используется десятичное форматирование. Используйтеp /whateverдля других форматов. (display $ymm0.v4_doubleможет работать вместоlayout reg vecв некоторых версиях с ошибками/неисправностями, и всегда беспорядок разных форматов.)