Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Assembler

Автор: ne_viens
Дата сообщения: 29.11.2012 10:35
>Nastya19kiss О каком коде речь идёт?
Автор: Nastya19kiss
Дата сообщения: 29.11.2012 13:20
ne_viens
[more]
ORG 0
;------------------------init
mov 30h, #67h ;unsigned char a[10]
mov 31h, #91h
mov 32h, #40h
mov 33h, #0a5h
mov 34h, #3ch
mov 35h, #98h
mov 36h, #0f7h
mov 37h, #41h
mov 38h, #18h
mov 39h, #0e0h
mov 40h, #99h ;unsigned char b[10]
mov 41h, #21h
mov 42h, #0ffh
mov 43h, #17h
mov 44h, #45h
mov 45h, #4eh
mov 46h, #32h
mov 47h, #7bh
mov 48h, #0d9h
mov 49h, #0dah

mov R0, #30h ;&a
mov R1, #40h ;&b
mov R2, #0 ;loResult
mov R3, #0 ;hiResult
L1:
;------------------------unsigned int Result += ((a[j]+b[j])/(a[j]-b[j]))*b[j]
mov A, @R0
clr C
subb A, @R1
jz err

mov B, A
mov A, @R0
add A, @R1
div AB
mov B, A
mov A, @R1
mul AB

add A, R2
mov R2, A
mov A, B
addc A, R3
mov R3, A

inc R0
inc R1
cjne R0, #3ah, L1
nop

[/more]
Автор: ne_viens
Дата сообщения: 29.11.2012 13:25
Так условие задачи было:
"Числа беззнаковые целые, значит и результат суммы - беззнаковое целое"
Передумала?
Автор: Nastya19kiss
Дата сообщения: 29.11.2012 16:35
ne_viens

я запуталась тогда...если числа беззнаковые это не значит что результат будет беззнаковым. я пересчитала и может получиться так что из меньшего числа вычтется большее и результат будет отрицательным у всей дроби
Автор: Nastya19kiss
Дата сообщения: 01.12.2012 10:19
ne_viens
Можно еще тебя попросить... Мне необходимо подключить матричную клавиатуру 3х4 к МК51 (строки и столбцы к разным портам) и произвести сканирование нажатой клавиши и вывод ее на семисегментный индикатор. Всего необходимо подключить 3 семисегментных индикатора, на которые будут выводиться 3 цифры с клавиатуры. Можешь какую нибудь статью дать по этому поводу?
Автор: netfil
Дата сообщения: 24.12.2012 16:47
Всем привет, имеется программа, умножающая матрицу на вектор:

Код:
{$APPTYPE CONSOLE}
const
n = 8; // столбцов
m = 8; // строк

var
a: array[1..n,1..m] of smallint; // матрица
c: array[1..m] of smallint; // вектор
d,e: array[1..m] of integer; // результат
i,j: integer;
begin
for i:=1 to n do
for j:=1 to m do
a[i,j]:=random(128);

for i:=1 to m do
c[i]:=random(128);

for i:=1 to n do
begin
d[i]:=0;
for j:=1 to m do
inc(d[i],a[i,j]*c[j]);
end;

asm
mov eax,(m*n-m)*2
mov ecx,n
@1:pxor mm0,mm0
mov edx,m*2
@2:movq mm1,qword[a+eax+edx-8]
pmaddwd mm1,qword[c+edx-8]
paddd mm0,mm1
sub edx,8
jnz @2
phaddd mm0,mm0
movd dword[e+ecx*4-4],mm0
sub eax,m*2
loop @1
end;

writeln('pascal':6,' ','asm':6);
for i:=1 to m do
writeln(d[i]:6,' : ',e[i]:6);
readln;
end.
Автор: akaGM
Дата сообщения: 24.12.2012 17:27
netfil
а это вообще возможно?

phaddd хрен заменишь...
Автор: netfil
Дата сообщения: 24.12.2012 19:22
akaGM
если есть такое задание то, наверное возможно...

как я понимаю, вместо mm0 и mm1 будет хmm0 и хmm1;
потом заменить окончания d на s где это возможно( например, movd на movs ),
а по поводу phaddd не знаю, скорее всего его нужно заменять несколькими строками кода, но все мои попытки проделать вышесказанное оказались не особо рабочими - потому и написал сюда.
Автор: akaGM
Дата сообщения: 24.12.2012 20:54
netfil

а что (где) за задание-то? и кто писал этот вариант, знаток дельфей :) ?
Автор: netfil
Дата сообщения: 24.12.2012 21:30
akaGM
ну задание и есть умножить матрицу на вектор, при помощи asm вставки двумя способами:
1. используя SSE3
2. используя SSE1

по первому пункту помогли написать( код выше ), а вот с SSE1 уже проблемы...

а если временно забыть про строчку phaddd mm0,mm0, то как мог бы выглядеть код?
Автор: akaGM
Дата сообщения: 24.12.2012 21:35
netfil

не, извини, я с sse не связывался никогда...
Автор: netfil
Дата сообщения: 24.12.2012 22:05
akaGM
(
ну буду надеяться, что кто-нибудь еще ответит...
Автор: akaGM
Дата сообщения: 24.12.2012 22:13
позови Abs62 и Меркурия

хотя, щас рождество -- заняты, небось :)
Автор: Abs62
Дата сообщения: 24.12.2012 22:32
Я могу лишь пояснить, что к этой задаче лучше подходить с другой стороны. Сначала сделать алгоритм на чистом x86, а потом уже смотреть, как его можно упростить и ускорить за счёт SSE-инструкций. Тогда и просить кого-то сделать это за тебя не придётся.

Цитата:
[no]по первому пункту помогли написать( код выше ), а вот с SSE1 уже проблемы...[/no]

Вот потому и проблемы, что "помогли написать". Теперь приходится просить помочь перевести с написанного.
Автор: MERCURY127
Дата сообщения: 25.12.2012 18:39
netfil
с ССЕ пока не встречался, с Паскалем не дружу вообще...
но в целом задача заинтересовала
написал аналогичный код на Си
[more]
Код: [no]
#include <stdio.h>

#define n 8 // столбцов
#define m 8 // строк

__int16 a[n][m]=
{{1,2,3,4,5,6,7,8},
{2,3,4,5,6,7,8,1},
{3,4,5,6,7,8,1,2},
{4,5,6,7,8,1,2,3},

{5,6,7,8,1,2,3,4},
{6,7,8,1,2,3,4,5},
{7,8,1,2,3,4,5,6},
{8,1,2,3,4,5,6,7},
}; // матрица

__int16 c[m]= {-9,-8,-7,-6,-5,-4,-3,-2}; // вектор

__int32 d[m], e[m]; // результат
int i,j;

main(){
    for( i=1; i<=n; i++)
    for( j=1; j<=m;j++)
        //a[i][j]=rand()/512;

    for( i=1; i<=m; i++)
    //c[i]=rand()/512;

    for( i=1; i<=n; i++){
    d[i]=0;
    for( j=1; j<=m; j++)
        d[i]+=a[i][j]*c[j];
    }

    __asm{
        mov eax,(m*n-m)*2
        mov ecx,n
        l1: pxor mm0,mm0
        mov edx,m*2
        l2: movq mm1,[a+eax+edx-8]
        pmaddwd mm1,[c+edx-8]
        paddd mm0,mm1
        sub edx,8
            jnz l2
        phaddd mm0,mm0
        movd [e+ecx*4-4],mm0
        sub eax,m*2
        loop l1
    }

    printf("\npascal\t\tasm\n");
    for( i=1; i<=m; i++)
    printf("%d\t\t%d\n", d[i],e[i]);
}
[/no]
Автор: Abs62
Дата сообщения: 25.12.2012 18:48
MERCURY127

Цитата:
а вывод результата тоже ручками писать?..

Ну, если очень хочется...
Я воообще-то говорил об алгоритме перемножения, а не программе в целом. Сдаётся мне, переводить на asm86 несколько легче с паскаля/C, чем с SSE3.
Автор: netfil
Дата сообщения: 25.12.2012 20:25
MERCURY127

Цитата:
ЧЯДНТ? оно вообще работает?

честно признаться, ни мой, ни ваш код у меня скомпилировать не вышло(
компиляторы всегда ругаются на строчку phaddd mm0,mm0( как я, при помощи гугла, понял это может зависеть от моего процессора ),
а просто глядя на код прикинуть ход его работы мои знания ассемблера сделать не позволяют...
Автор: MERCURY127
Дата сообщения: 25.12.2012 20:41
У меня с 2005 студии норм только до этого тоже ругалось
Автор: akaGM
Дата сообщения: 25.12.2012 20:47
cl /arch:SSEx
где x = версия SSE

в паскаль я могу вставить...
Автор: netfil
Дата сообщения: 25.12.2012 21:46
MERCURY127
ну переустанавливать 10ую студию для меня явно не вариант)

akaGM

Цитата:
cl /arch:SSEx
где x = версия SSE

что это? какой то параметр компиляции?
Автор: akaGM
Дата сообщения: 25.12.2012 22:19
это для Си
Автор: MERCURY127
Дата сообщения: 26.12.2012 12:20

Цитата:
ну переустанавливать 10ую студию для меня явно не вариант)

господь с вами, какая студия? неужто я их буду полностью ставить? просто выдрал бинарники, сложил в соот иерархию папок, и дальше ручками через батничек
...
cl /nologo /O1sb2 /GF /Gy /MD ssse3.c /link /map %libs% >> log.log
...

Добавлено:
netfil, виноват я неправильно переписал ваш код на си, забыв про другой оригин массивов в паскале (будь он проклят...)
в общем код работает
[more]
Код: [no]
#include <stdio.h>

#define n 8 // столбцов
#define m 8 // строк

__int16 a[n][m]=
{{1,2,3,4,5,6,7,8},
{2,3,4,5,6,7,8,1},
{3,4,5,6,7,8,1,2},
{4,5,6,7,8,1,2,3},

{5,6,7,8,1,2,3,4},
{6,7,8,1,2,3,4,5},
{7,8,1,2,3,4,5,6},
{8,1,2,3,4,5,6,7},
}; // матрица

__int16 c[m]= {-9,-8,-7,-6,-5,-4,-3,-2}; // вектор

__int32 d[m], e[m]; // результат
int i,j;

main(){
    for( i=0; i<n; i++)
    for( j=0; j<m;j++)
        ;//a[i][j]=rand()/512;

    for( i=0; i<m; i++)
    ;//c[i]=rand()/512;

    for( i=0; i<n; i++){
    d[i]=0;
    for( j=0; j<m; j++)
        d[i]+=a[i][j]*c[j];
    }// for

    __asm{
        emms
        mov eax,(n*m-n)*2 // two byte per __int16?
        mov ecx,n
        l1: pxor mm0,mm0
        mov edx,m*2
        l2: movq mm1,[a+eax+edx-8]
        pmaddwd mm1,[c+edx-8]
        paddd mm0,mm1
        sub edx,8
            jnz l2
        phaddd mm0,mm0
        movd [e+ecx*4-4],mm0
        sub eax,m*2
            loop l1
    }// asm

    printf("\npascal\t\tasm\n");
    for( i=0; i<m; i++)
    printf("%d\t\t%d\n", d[i],e[i]);
}
[/no]
Автор: akaGM
Дата сообщения: 26.12.2012 15:28
MERCURY127


Цитата:
я неправильно переписал ваш код на си
это недопустимо!
низачот!


Цитата:
осталось переписать на ССЕ1...
:)
Автор: MERCURY127
Дата сообщения: 26.12.2012 15:59

Цитата:
это недопустимо!

ну так я ж лично себе, чтоб паскаль не пытать...
и ведь хоть бы какой отладчик норм поиметь, чтоб эти xyzmm показывал...
а то все приходится скилл телепатии прокачивать... что то не очень с этими параллельным регистрами получается... трудновообразимые они, однако
Автор: akaGM
Дата сообщения: 26.12.2012 16:23
MERCURY127

да ладно тебе, без смайла уже и шутка -- не шутка?
просто кому-то дают онанистические задачи, и эти кто-то пытаются решить эти задачи нашими руками :)

борландОвский вроде показывает...
всё равно компилятор лучше сделает...
я попытался на интел-фортране забабахать, так он мне эти 8 циклов просто-напросто раскрыл...
правда у меня и проц не "SS-тришный"...
Автор: MERCURY127
Дата сообщения: 26.12.2012 16:48

Цитата:
да ладно тебе, без смайла уже и шутка -- не шутка?

до оно то как раз понятно
но мне самому интересно стало... видимо проще переписать всю эту ассемблерную врезку
да и вообще - нафиг нужна эта "оптимизация"? все равно два цикла получаются, что само по себе далеко не оптимально...
Автор: ne_viens
Дата сообщения: 26.12.2012 17:34
phaddd можно сдвигом+суммой заменить как-то так:

.code
start:

push ebx
mov ebx, 8
lea edx, matrix ;16 aligned
lea ecx, vector ;16 aligned
lea eax, result ;16 aligned
align 16
L1:
movq mm0, [edx]
movq mm1, [edx+8]

pmaddwd mm0, [ecx]
pmaddwd mm1, [ecx+8]

; phaddd mm0, mm1
paddd mm0, mm1
movq mm1, mm0
psrlq mm0, 32
paddd mm0, mm1

movd dword ptr[eax], mm0
add edx, 10h
add eax, 4
dec ebx
jne L1

pop ebx
invoke ExitProcess, 0
END start
Автор: cp58
Дата сообщения: 26.12.2012 18:26
netfil

Цитата:
был бы очень признателен если кто-нибудь помог переписать ее под SSE1 инструкции.

Вы уверены что именно SSE1?

Цитата:
ассемблерная вставка в ней написана с использованием SSE3 инструкций;

Тут и SSSE3 присутствует.

Перевести на SSE1 можно несколькими способами. Можно, например, перевести целочисленный тип в тип с плавающей запятой и использовать доступные инструкции, вроде mulps, addps или mulss, addss для скалярных операций; а ниже показан код, использующий операции для целочисленных данных. Работает для матриц с небольшим значением элементов, чтобы работало с большими необходимо произвести считывание поэлементно, вместо операции psadbw, также если размерность вектора будет отличаться от 8, то необходимо добавить второй цикл.

Код: __asm__ volatile
    (    
        "pinsrw $0, (%1), %%xmm2\n\t"
        "pinsrw $1, 2(%1), %%xmm2\n\t"
        "pinsrw $2, 4(%1), %%xmm2\n\t"
"pinsrw $3, 6(%1), %%xmm2\n\t"
        "pinsrw $4, 8(%1), %%xmm2\n\t"
"pinsrw $5, 10(%1), %%xmm2\n\t"
        "pinsrw $6, 12(%1), %%xmm2\n\t"
"pinsrw $7, 14(%1), %%xmm2\n\t"
        "pxor %%xmm1, %%xmm1\n\t"
        "movl %2, %%ecx\n\t"
        "b:\n\t"
        "xorl %%edx, %%edx\n\t"
        "pxor %%xmm0, %%xmm0\n\t"
        "pinsrw $0, (%0), %%xmm0\n\t"
        "pinsrw $1, 2(%0), %%xmm0\n\t"
        "pinsrw $2, 4(%0), %%xmm0\n\t"
        "pinsrw $3, 6(%0), %%xmm0\n\t"
        "pinsrw $4, 8(%0), %%xmm0\n\t"
"pinsrw $5, 10(%0), %%xmm0\n\t"
"pinsrw $6, 12(%0), %%xmm0\n\t"
"pinsrw $7, 14(%0), %%xmm0\n\t"
        "pmullw %%xmm2, %%xmm0\n\t"
        "psadbw %%xmm1, %%xmm0\n\t"
        "pextrw $0, %%xmm0, %%eax\n\t"
"addl %%eax, %%edx\n\t"
"pextrw $4, %%xmm0, %%eax\n\t"
"addl %%eax, %%edx\n\t"
        "movl %%edx, (%3)\n\t"
        "addl $0x10, %0\n\t"
        "addl $4, %3\n\t"
        "dec %%ecx\n\t"
        "test %%ecx, %%ecx\n\t"
        "jne b\n\t"
        :
        :"D"(mx),"S"(v),"i"(m),"r"(e)
        :"eax", "edx", "ecx", "xmm0", "xmm1", "xmm2"
    );
Автор: svch0st
Дата сообщения: 06.01.2013 08:47
помогите пожалуйста решить задачу:

реализовать на встроенном ассемблере для 32-х разрядных
исполнительных адресов эквивалент следующего расчетного выражения


short Y[150][600];
short p,q;
short *pm;
s s6;
short w;
int i,j;
struct s{
char d[12];
float r;
short g;
};
w = s6.g + p*q - pm[j]/Y[i][j];



возможно исходый код вот такой:
    
short Y[150][600]; struct s{
short p,q; char d[12];
short *pm; float r;
s s6; short g;
short w; };
int i,j;

w = s6.g + p*q - pm[j]/Y[i][j];



в книге написано так а копируется как в первом варианте
Автор: MERCURY127
Дата сообщения: 06.01.2013 17:44
копируется правильно

[more]
Код: [no]
short Y[150][600];
short p,q;
short *pm;
short w;
int i,j;

struct s{
char d[12];
float r;
short g;
} s6;

//w = s6.g + p*q - pm[j]/Y[i][j];

main(){
    __asm{

        lea     ebx, s6 // загружаем адрес s6
        mov     ax, [ebx+10h] // берем смещение offset g = 12+4
        mov     w, ax
        
        movsx    eax, p
        movsx     ebx, q
        imul     ebx
        add     w, ax // сложили с w

        mov     ecx, j
        shl     ecx, 1
        mov     eax, i
        imul     eax, 150 // множим на 150 слов (2 байта каждое)
        movsx    ebx, [Y+eax*2+ecx]
        movsx    eax, [pm+ecx]
        xor     edx, edx
        idiv    ebx
        sub    w, ax

    }// asm
}
[/no]

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384

Предыдущая тема: .NET GUI компоненты


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.