2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Еще раз о пользе от ассемблера
Сообщение21.01.2024, 09:04 


18/11/18
498
 i  Ende
Выделено из темы «Первые и последующие шаги в ассемблере x86/x64»

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

 Профиль  
                  
 
 Re: Первые и последующие шаги в ассемблере x86/x64
Сообщение21.01.2024, 15:02 
Заслуженный участник


20/08/14
11177
Россия, Москва
A_I
Пока не умрёт, слишком уж заметное ускорение пока что даёт, которое не могут показать ни существующие оптимизирующие компиляторы ЯВУ, ни нейросети. Когда научатся выдавать столь же быстрый код - вот тогда и поговорим. Я всем таким энтузиастам предлагаю пойти в соседнюю тему (приёмы на SSE/AVX) и показать компилятор ЯВУ (или нейросеть), выдающий ровно тот же асм код (или любой другой не меньшей скорости) что и приведённый мой. Дерзайте!
Кому скорость не столь важна - ЯВУ в помощь. Я тоже ими пользуюсь - для интерфейса, внешних циклов, предпросчёта таблиц, организации многозадачности, допроверки найденных решений (например чтобы не писать тест простоты больших чисел самому на асме) - всё что не занимает много (в процентах от общего) времени.
FPGA не выход - рассматривал я их, несколько раз и для разных задач, не конкурент даже обычному процу с SSE/AVX (не говоря уж про GPU), ну вот не тянут, считают то быстро, но памяти кот наплакал, а внешние шины медленные и узкие. Покажите к какой FPGA можно как родную подключить 128 битную DDR4 гигагерц так на 3 эффективных (это обычный проц если что). А потом посмотрите на цену этой FPGA! Ещё не самолёт, но уже хороший такой сервер, который снова будет на порядок быстрее найденной FPGA.
Вот полностью заказная ASIC - это да, обогнала бы только в путь (пару ГГц тактовой частоты плюс штук 20 внешних DDR5 на 8ГГц (эффективных) с шиной 1024 бита). Но у меня нет лишнего десятка миллионов уе на это. А если б и был - жалко. И приходится справляться тем что есть - обычными процами.

 Профиль  
                  
 
 Re: Первые и последующие шаги в ассемблере x86/x64
Сообщение21.01.2024, 17:41 


18/11/18
498
Dmitriy40 в сообщении #1626687 писал(а):
A_I
Пока не умрёт


Всё же асм больше подходит для низкого уровня - драйверов, например (я не сторонник разных теоретико-академических задач типа факторизации сверхбольших, хотя и понимаю, что такого плана исследования тоже нужны, хотя не ясно кому 8-) )
Поэтому вот реальный пример - часть драйвера, а именно - слой апи взаимодействия с одной тепловизионной матрицей от мелексис, и да - на плюсах. (Заказали матрицу для своих поделок, пока не пришла - теоретически готовимся..) По объему - ничего примечательного, средний такой драйверок. Причем особо извращенной логики там нет, - достаточно всё просто, но сомнительно, как это всё в асме писать да ещё потом поддерживать.. Приведу меньше половины, т.к. местный редактор ругается на превышение макс. кол-ва знаков.
Однако только в инклудах, к примеру, один матн хедер чего стоит..
Во что это выльется на асме? Я уж не говорю о том, что никакого прироста быстродействия не будет в принципе - инертность ик- пикселов сводит на нет все попытки снимать данные чаще чем 16 Гц (хотя в даташите указывается до 64-х - но, пишут шумы возрастают непропорционально сильно, так что без толку). За это время всё прекрасно обработается.

(Оффтоп)

Код:
#include <MLX90640_I2C_Driver.h>
#include <MLX90640_API.h>
#include <math.h>

void ExtractVDDParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractPTATParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractGainParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractTgcParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractResolutionParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractKsTaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractKsToParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractAlphaParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractOffsetParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractKtaPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractKvPixelParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractCPParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
void ExtractCILCParameters(uint16_t *eeData, paramsMLX90640 *mlx90640);
int ExtractDeviatingPixels(uint16_t *eeData, paramsMLX90640 *mlx90640);
int CheckAdjacentPixels(uint16_t pix1, uint16_t pix2); 
float GetMedian(float *values, int n);
int IsPixelBad(uint16_t pixel,paramsMLX90640 *params);
int ValidateFrameData(uint16_t *frameData);
int ValidateAuxData(uint16_t *auxData);
 
int MLX90640_DumpEE(uint8_t slaveAddr, uint16_t *eeData)
{
     return MLX90640_I2CRead(slaveAddr, 0x2400, 832, eeData);
}

int MLX90640_SynchFrame(uint8_t slaveAddr)
{
    uint16_t dataReady = 0;
    uint16_t statusRegister;
    int error = 1;
   
    error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030);
    if(error == -1)
    {
        return error;
    }
   
    while(dataReady == 0)
    {
        error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister);
        if(error != 0)
        {
            return error;
        }   
        dataReady = statusRegister & 0x0008;
    }     
   
   return 0;   
}

int MLX90640_TriggerMeasurement(uint8_t slaveAddr)
{
    int error = 1;
    uint16_t ctrlReg;
   
    error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg);
   
    if ( error != 0)
    {
        return error;
    }   
                                               
    ctrlReg |= 0x8000;
    error = MLX90640_I2CWrite(slaveAddr, 0x800D, ctrlReg);
   
    if ( error != 0)
    {
        return error;
    }   
   
    error = MLX90640_I2CGeneralReset();
   
    if ( error != 0)
    {
        return error;
    }   
   
    error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &ctrlReg);
   
    if ( error != 0)
    {
        return error;
    }   
   
    if ((ctrlReg & 0x8000) != 0)
    {
        return -9;
    }
   
    return 0;   
}
   
int MLX90640_GetFrameData(uint8_t slaveAddr, uint16_t *frameData)
{
    uint16_t dataReady = 0;
    uint16_t controlRegister1;
    uint16_t statusRegister;
    int error = 1;
    uint16_t data[64];
    uint8_t cnt = 0;
   
    while(dataReady == 0)
    {
        error = MLX90640_I2CRead(slaveAddr, 0x8000, 1, &statusRegister);
        if(error != 0)
        {
            return error;
        }   
        dataReady = statusRegister & 0x0008;
    }     
   
    error = MLX90640_I2CWrite(slaveAddr, 0x8000, 0x0030);
    if(error == -1)
    {
        return error;
    }
                     
    error = MLX90640_I2CRead(slaveAddr, 0x0400, 768, frameData);
    if(error != 0)
    {
        return error;
    }                       
   
    error = MLX90640_I2CRead(slaveAddr, 0x0700, 64, data);
    if(error != 0)
    {
        return error;
    }     
       
    error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
    frameData[832] = controlRegister1;
    frameData[833] = statusRegister & 0x0001;
   
    if(error != 0)
    {
        return error;
    }
   
    error = ValidateAuxData(data);
    if(error == 0)
    {
        for(cnt=0; cnt<64; cnt++)
        {
            frameData[cnt+768] = data[cnt];
        }
    }       
   
    error = ValidateFrameData(frameData);
    if (error != 0)
    {
        return error;
    }
   
    return frameData[833];   
}

int ValidateFrameData(uint16_t *frameData)
{
    uint8_t line = 0;
   
    for(int i=0; i<768; i+=32)
    {
        if((frameData[i] == 0x7FFF) && (line%2 == frameData[833])) return -8;
        line = line + 1;
    }   
       
    return 0;   
}

int ValidateAuxData(uint16_t *auxData)
{
   
    if(auxData[0] == 0x7FFF) return -8;   
   
    for(int i=8; i<19; i++)
    {
        if(auxData[i] == 0x7FFF) return -8;
    }
   
    for(int i=20; i<23; i++)
    {
        if(auxData[i] == 0x7FFF) return -8;
    }
   
    for(int i=24; i<33; i++)
    {
        if(auxData[i] == 0x7FFF) return -8;
    }
   
    for(int i=40; i<51; i++)
    {
        if(auxData[i] == 0x7FFF) return -8;
    }
   
    for(int i=52; i<55; i++)
    {
        if(auxData[i] == 0x7FFF) return -8;
    }
   
    for(int i=56; i<64; i++)
    {
        if(auxData[i] == 0x7FFF) return -8;
    }
   
    return 0;
   
}
   
int MLX90640_ExtractParameters(uint16_t *eeData, paramsMLX90640 *mlx90640)
{
    int error = 0;
   
    ExtractVDDParameters(eeData, mlx90640);
    ExtractPTATParameters(eeData, mlx90640);
    ExtractGainParameters(eeData, mlx90640);
    ExtractTgcParameters(eeData, mlx90640);
    ExtractResolutionParameters(eeData, mlx90640);
    ExtractKsTaParameters(eeData, mlx90640);
    ExtractKsToParameters(eeData, mlx90640);
    ExtractCPParameters(eeData, mlx90640);
    ExtractAlphaParameters(eeData, mlx90640);
    ExtractOffsetParameters(eeData, mlx90640);
    ExtractKtaPixelParameters(eeData, mlx90640);
    ExtractKvPixelParameters(eeData, mlx90640);
    ExtractCILCParameters(eeData, mlx90640);
    error = ExtractDeviatingPixels(eeData, mlx90640); 
   
    return error;

}

//------------------------------------------------------------------------------

int MLX90640_SetResolution(uint8_t slaveAddr, uint8_t resolution)
{
    uint16_t controlRegister1;
    int value;
    int error;
   
    value = (resolution & 0x03) << 10;
   
    error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
   
    if(error == 0)
    {
        value = (controlRegister1 & 0xF3FF) | value;
        error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);       
    }   
   
    return error;
}

//------------------------------------------------------------------------------

int MLX90640_GetCurResolution(uint8_t slaveAddr)
{
    uint16_t controlRegister1;
    int resolutionRAM;
    int error;
   
    error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
    if(error != 0)
    {
        return error;
    }   
    resolutionRAM = (controlRegister1 & 0x0C00) >> 10;
   
    return resolutionRAM;
}

//------------------------------------------------------------------------------

int MLX90640_SetRefreshRate(uint8_t slaveAddr, uint8_t refreshRate)
{
    uint16_t controlRegister1;
    int value;
    int error;
   
    value = (refreshRate & 0x07)<<7;
   
    error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
    if(error == 0)
    {
        value = (controlRegister1 & 0xFC7F) | value;
        error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);
    }   
   
    return error;
}

//------------------------------------------------------------------------------

int MLX90640_GetRefreshRate(uint8_t slaveAddr)
{
    uint16_t controlRegister1;
    int refreshRate;
    int error;
   
    error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
    if(error != 0)
    {
        return error;
    }   
    refreshRate = (controlRegister1 & 0x0380) >> 7;
   
    return refreshRate;
}

//------------------------------------------------------------------------------

int MLX90640_SetInterleavedMode(uint8_t slaveAddr)
{
    uint16_t controlRegister1;
    int value;
    int error;
   
    error = MLX90640_I2CRead(slaveAddr, 0x800D, 1, &controlRegister1);
   
    if(error == 0)
    {
        value = (controlRegister1 & 0xEFFF);
        error = MLX90640_I2CWrite(slaveAddr, 0x800D, value);       
    }   
   
    return error;
}

//------------------------------------------------------------------------------

...


...
//------------------------------------------------------------------------------

void MLX90640_CalculateTo(uint16_t *frameData, const paramsMLX90640 *params, float emissivity, float tr, float *result)
{
    float vdd;
    float ta;
    float ta4;
    float tr4;
    float taTr;
    float gain;
    float irDataCP[2];
    float irData;
    float alphaCompensated;
    uint8_t mode;
    int8_t ilPattern;
    int8_t chessPattern;
    int8_t pattern;
    int8_t conversionPattern;
    float Sx;
    float To;
    float alphaCorrR[4];
    int8_t range;
    uint16_t subPage;
    float ktaScale;
    float kvScale;
    float alphaScale;
    float kta;
    float kv;
   
    subPage = frameData[833];
    vdd = MLX90640_GetVdd(frameData, params);
    ta = MLX90640_GetTa(frameData, params);
   
    ta4 = (ta + 273.15);
    ta4 = ta4 * ta4;
    ta4 = ta4 * ta4;
    tr4 = (tr + 273.15);
    tr4 = tr4 * tr4;
    tr4 = tr4 * tr4;
    taTr = tr4 - (tr4-ta4)/emissivity;
   
    ktaScale = pow(2,(double)params->ktaScale);
    kvScale = pow(2,(double)params->kvScale);
    alphaScale = pow(2,(double)params->alphaScale);
   
    alphaCorrR[0] = 1 / (1 + params->ksTo[0] * 40);
    alphaCorrR[1] = 1 ;
    alphaCorrR[2] = (1 + params->ksTo[1] * params->ct[2]);
    alphaCorrR[3] = alphaCorrR[2] * (1 + params->ksTo[2] * (params->ct[3] - params->ct[2]));
   
//------------------------- Gain calculation -----------------------------------   
    gain = frameData[778];
    if(gain > 32767)
    {
        gain = gain - 65536;
    }
   
    gain = params->gainEE / gain;
 
//------------------------- To calculation -------------------------------------   
    mode = (frameData[832] & 0x1000) >> 5;
   
    irDataCP[0] = frameData[776]; 
    irDataCP[1] = frameData[808];
    for( int i = 0; i < 2; i++)
    {
        if(irDataCP[i] > 32767)
        {
            irDataCP[i] = irDataCP[i] - 65536;
        }
        irDataCP[i] = irDataCP[i] * gain;
    }
    irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
    if( mode ==  params->calibrationModeEE)
    {
        irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
    }
    else
    {
      irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
    }

    for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++)
    {
        ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2;
        chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2);
        conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern);
       
        if(mode == 0)
        {
          pattern = ilPattern;
        }
        else
        {
          pattern = chessPattern;
        }               
       
        if(pattern == frameData[833])
        {   
            irData = frameData[pixelNumber];
            if(irData > 32767)
            {
                irData = irData - 65536;
            }
            irData = irData * gain;
           
            kta = params->kta[pixelNumber]/ktaScale;
            kv = params->kv[pixelNumber]/kvScale;
            irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3));
           
            if(mode !=  params->calibrationModeEE)
            {
              irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern;
            }                       
   
            irData = irData - params->tgc * irDataCP[subPage];
            irData = irData / emissivity;
           
            alphaCompensated = SCALEALPHA*alphaScale/params->alpha[pixelNumber];
            alphaCompensated = alphaCompensated*(1 + params->KsTa * (ta - 25));
                       
            Sx = alphaCompensated * alphaCompensated * alphaCompensated * (irData + alphaCompensated * taTr);
            Sx = sqrt(sqrt(Sx)) * params->ksTo[1];           
           
            To = sqrt(sqrt(irData/(alphaCompensated * (1 - params->ksTo[1] * 273.15) + Sx) + taTr)) - 273.15;                     
                   
            if(To < params->ct[1])
            {
                range = 0;
            }
            else if(To < params->ct[2])   
            {
                range = 1;           
            }   
            else if(To < params->ct[3])
            {
                range = 2;           
            }
            else
            {
                range = 3;           
            }     
           
            To = sqrt(sqrt(irData / (alphaCompensated * alphaCorrR[range] * (1 + params->ksTo[range] * (To - params->ct[range]))) + taTr)) - 273.15;
                       
            result[pixelNumber] = To;
        }
    }
}

//------------------------------------------------------------------------------

void MLX90640_GetImage(uint16_t *frameData, const paramsMLX90640 *params, float *result)
{
    float vdd;
    float ta;
    float gain;
    float irDataCP[2];
    float irData;
    float alphaCompensated;
    uint8_t mode;
    int8_t ilPattern;
    int8_t chessPattern;
    int8_t pattern;
    int8_t conversionPattern;
    float image;
    uint16_t subPage;
    float ktaScale;
    float kvScale;
    float kta;
    float kv;
   
    subPage = frameData[833];
    vdd = MLX90640_GetVdd(frameData, params);
    ta = MLX90640_GetTa(frameData, params);
   
    ktaScale = pow(2,(double)params->ktaScale);
    kvScale = pow(2,(double)params->kvScale);
   
//------------------------- Gain calculation -----------------------------------   
    gain = frameData[778];
    if(gain > 32767)
    {
        gain = gain - 65536;
    }
   
    gain = params->gainEE / gain;
 
//------------------------- Image calculation -------------------------------------   
    mode = (frameData[832] & 0x1000) >> 5;
   
    irDataCP[0] = frameData[776]; 
    irDataCP[1] = frameData[808];
    for( int i = 0; i < 2; i++)
    {
        if(irDataCP[i] > 32767)
        {
            irDataCP[i] = irDataCP[i] - 65536;
        }
        irDataCP[i] = irDataCP[i] * gain;
    }
    irDataCP[0] = irDataCP[0] - params->cpOffset[0] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
    if( mode ==  params->calibrationModeEE)
    {
        irDataCP[1] = irDataCP[1] - params->cpOffset[1] * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
    }
    else
    {
      irDataCP[1] = irDataCP[1] - (params->cpOffset[1] + params->ilChessC[0]) * (1 + params->cpKta * (ta - 25)) * (1 + params->cpKv * (vdd - 3.3));
    }

    for( int pixelNumber = 0; pixelNumber < 768; pixelNumber++)
    {
        ilPattern = pixelNumber / 32 - (pixelNumber / 64) * 2;
        chessPattern = ilPattern ^ (pixelNumber - (pixelNumber/2)*2);
        conversionPattern = ((pixelNumber + 2) / 4 - (pixelNumber + 3) / 4 + (pixelNumber + 1) / 4 - pixelNumber / 4) * (1 - 2 * ilPattern);
       
        if(mode == 0)
        {
          pattern = ilPattern;
        }
        else
        {
          pattern = chessPattern;
        }
       
        if(pattern == frameData[833])
        {   
            irData = frameData[pixelNumber];
            if(irData > 32767)
            {
                irData = irData - 65536;
            }
            irData = irData * gain;
           
            kta = params->kta[pixelNumber]/ktaScale;
            kv = params->kv[pixelNumber]/kvScale;
            irData = irData - params->offset[pixelNumber]*(1 + kta*(ta - 25))*(1 + kv*(vdd - 3.3));

            if(mode !=  params->calibrationModeEE)
            {
              irData = irData + params->ilChessC[2] * (2 * ilPattern - 1) - params->ilChessC[1] * conversionPattern;
            }
           
            irData = irData - params->tgc * irDataCP[subPage];
                       
            alphaCompensated = params->alpha[pixelNumber];
           
            image = irData*alphaCompensated;
           
            result[pixelNumber] = image;
        }
    }
}

//------------------------------------------------------------------------------

float MLX90640_GetVdd(uint16_t *frameData, const paramsMLX90640 *params)
{
    float vdd;
    float resolutionCorrection;

    int resolutionRAM;   
   
    vdd = frameData[810];
    if(vdd > 32767)
    {
        vdd = vdd - 65536;
    }
    resolutionRAM = (frameData[832] & 0x0C00) >> 10;
    resolutionCorrection = pow(2, (double)params->resolutionEE) / pow(2, (double)resolutionRAM);
    vdd = (resolutionCorrection * vdd - params->vdd25) / params->kVdd + 3.3;
   
    return vdd;
}

//------------------------------------------------------------------------------

float MLX90640_GetTa(uint16_t *frameData, const paramsMLX90640 *params)
{
    float ptat;
    float ptatArt;
    float vdd;
    float ta;
   
    vdd = MLX90640_GetVdd(frameData, params);
   
    ptat = frameData[800];
    if(ptat > 32767)
    {
        ptat = ptat - 65536;
    }
   
    ptatArt = frameData[768];
    if(ptatArt > 32767)
    {
        ptatArt = ptatArt - 65536;
    }
    ptatArt = (ptat / (ptat * params->alphaPTAT + ptatArt)) * pow(2, (double)18);
   
    ta = (ptatArt / (1 + params->KvPTAT * (vdd - 3.3)) - params->vPTAT25);
    ta = ta / params->KtPTAT + 25;
   
    return ta;
}

//------------------------------------------------------------------------------

int MLX90640_GetSubPageNumber(uint16_t *frameData)
{
    return frameData[833];   

}   

//------------------------------------------------------------------------------
...


...


...
}     

//------------------------------------------------------------------------------

 Профиль  
                  
 
 Re: Первые и последующие шаги в ассемблере x86/x64
Сообщение21.01.2024, 18:41 
Заслуженный участник


20/08/14
11177
Россия, Москва
A_I в сообщении #1626700 писал(а):
Всё же асм больше подходит для низкого уровня - драйверов, например
Не согласен, критерий должен быть другим: для высоких скоростей работы. Пока скорости хватает, можно писать на чём угодно, хоть на бейсике или лиспе. Про драйвера - это предубеждение из 70-80-х.
С другой стороны, на асме намного удобнее работать с физической аппаратурой: те же биты, байты, адреса, регистры. На многих ЯВУ к аппаратуре просто не долезешь - нет механизмов в языке!
Но когда я вижу (да и пишу) код на том же С для замены команды rcl/rcr (сдвиг через перенос) - у меня волосы дыбом. Адекватной замены командам adc/sbb/mul/div (c xDX) в языках семейства C тоже нет - а это базовые операции с длинной арифметикой! popcnt, bsf/bsr, pdep/pext - да полно команд, на С выглядящих как куча непонятного кода, а уж во что превращающихся в машинном коде ... лучше и не знать, спать спокойнее.
Если вам всё равно во что превращается код после компилятора ЯВУ и как быстро он в результате работает (а это на секундочку и энергопотребление!) - асм вам и не нужен. Что бы вы ни писали, хоть ОС с драйверами (пример Форта наглядно демонстрирует, он умеет и без ОС работать, и программы короче в разы).

 Профиль  
                  
 
 Re: Первые и последующие шаги в ассемблере x86/x64
Сообщение21.01.2024, 18:56 


18/11/18
498
Dmitriy40 в сообщении #1626707 писал(а):
Не согласен, критерий должен быть другим: для высоких скоростей работы. Пока скорости хватает, можно писать на чём угодно, хоть на бейсике или лиспе. Про драйвера - это предубеждение из 70-80-х.


Ну вот ещё реальные примеры из современности (а не 70-80 :lol: ) - все высокоскоростные преобразователи интерфейсов, например, где скорость работы важна по определению, работают за счет вычислительной пары контроллер - плис. Языки С и для плис свой какой-то соответственно.
Ещё примеры - маршрутизаторы, к примеру, 3-го уровня, также высокопроизводительные (например, на 1 Гбит) с кучей портов и проч. приблудами, а также, соответственно 3-му уровню - программное управление маршрутизацией в онлайн режиме. Та же самая пара (С-контроллер-процессор + плис и без всякого асма) - причем, ещё и линуксоидная ОС может быть (пример - швейцарский випер 212 на 12 портов со своей проприетарной ОС "ВеОС" ).
Обработка сигналов - те же плис или сигнальники (по сути - близкие к асикам, так что их можно туда же) - тоже без асма.
И т.д. и т.п.

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 19:03 
Заслуженный участник


20/08/14
11177
Россия, Москва
A_I
4 года на форуме, а не знаете про Подсветку синтаксиса для языка Cи C++ прямо под кнопкой code, аналогичной как для асм у меня выше, которая аккуратно сворачивается в компактную штуку. Нет, надо вывалить море кода ... :facepalm: Хорошо хоть в офтопе.
Глянул я Ваш исходник. Про макросы не слышали (свернуть if(error OP CONST) return error в один оператор). Что ValidateAuxData сворачивается в один for(...) if(i!=9 && i!=23 ... && auxData[i] == 0x7FFF) return не подумали. Я бы просто поленился столько писать (и даже дублировать), его же проматывать замучаешься. Куча пустых строк - вам за количество строк что ли платят? ;-) Я люблю компактность.
Похоже обычный быстро написанный исходник, без прикладывания лишнего ума. "Скорость работы?! Да какая разница?! Лучше быстрее написать и сдать.". Асм тут не нужен. Это не мой стиль, простите.

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 19:12 


18/11/18
498
Ваш стиль понятен. :mrgreen:

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 19:13 
Заслуженный участник


20/08/14
11177
Россия, Москва
A_I в сообщении #1626710 писал(а):
Ну вот ещё реальные примеры из современности (а не 70-80 :lol: )
Разумеется можно и С и С++ и даже бейсик ускорить аппаратными методами (асики, плисы, дсп) до желаемой скорости. Можно. Только они денег стоят, и к обычному компу не очень-то подключаются (по USB что ли?!) для ускорения вычислений. А асм позволяет ускорить программу ровно на той же уже имеющейся аппаратуре! И на DSP, и на FPGA (только кто будет таким заниматься? всем быстрее сдать и денег получить, и это в каком-то смысле и правильно), и на ARM.
Примеров для DSP, FPGA, ARM у меня готовых нет. Но я видел код что везде там получается на уровне аппаратуры - иногда ничего так, даже бывает на 4 с минусом, особенно если вычисления ложатся как родные на архитектуру, а иногда страх и ужас.

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 19:17 


18/11/18
498
Dmitriy40 в сообщении #1626723 писал(а):
Разумеется можно и С и С++ и даже бейсик ускорить аппаратными методами (асики, плисы, дсп) до желаемой скорости.


Так и я начал ровно с того же - асм умирает, так как другие высокопроизводительные технологии (верхнего уровня) становятся более доступными.

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 19:20 
Заслуженный участник


20/08/14
11177
Россия, Москва
Мой стиль - скорость и компактность. А не побыстрее/побольше продать. Каждому своё. Я не асмом (вернее им лишь изредка, ради фана) зарабатываю на жизнь если что, это хобби.
Хотел бы я посмотреть на программу на Питоне или даже С++ под PIC с 256 командами кода. А я уложился в 70 из них! На асме. Потому что цена вопроса! Такой PIC самый дешёвый (в разы дешевле самого наипростейшего ARM).

A_I в сообщении #1626725 писал(а):
другие высокопроизводительные технологии (верхнего уровня) становятся более доступными.
Из которых снова можно выжать больше за те же деньги. :mrgreen:

Спор беспредметный. Вы считаете чипы бьют асм (поставим чип побольше), я считаю что асм из любого чипа выжмет больше ЯВУ. Иногда важно одно, иногда другое. А иногда и вовсе третье.

Грубо говоря если у вас нет задач требующих асм и не решаемых аппаратурой за вменяемые деньги - то он вам и ненужен. ;-)

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 19:25 


18/11/18
498
Полностью согласен, но это не отменяет того, что всё меньше и меньше у фирм-разработчиков ПО спецов по ассемблеру. :-)

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 19:33 
Заслуженный участник


20/08/14
11177
Россия, Москва
A_I в сообщении #1626728 писал(а):
всё меньше и меньше у фирм-разработчиков ПО спецов по ассемблеру. :-)
Да. Потому что критерии успеха другие: не написать лучший код, а написать его больше за единицу времени - и соответственно больше заработать. Ничего личного, только бизнес.
Потому у меня асм - хобби. И подпадает под первый критерий (фан). А на продажу пишу и на С, и на дельфи, и на AHDL (если случается под FPGA, жаль редко, Verilog же как ЯВУ не уважаю, мне схемы ближе программ хоть и программист, потому же и асм люблю). Смотрю что получается после компилятора, ужасаюсь, побыстрее закрываю и стараюсь забыть - и продолжаю писать на ЯВУ и продавать. Работает, заказчик удовлетворён - и ладно. А что там в коде за кошмар - никого не волнует. А я отведу душу в хобби с асмом.

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 19:42 


18/11/18
498
Dmitriy40 в сообщении #1626730 писал(а):
Verilog же как ЯВУ не уважаю


У нас спец по плискам обижается, когда его называют программистом Типа он выше этого - он дизайнер схем, а верилог соответственно - язык дизайна..
(у меня небольшой опыт тоже есть - самый большой проект кан- интерфейс реализовал, но работал только с верилогом, поэтому сравнивать не с чем)

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 20:04 
Заслуженный участник


20/08/14
11177
Россия, Москва
Процедуры и функции - не дизайн и уж точно не схемы. Это алгоритм - т.е. натуральная программа, а их пишут программисты (про кодеров не будем).
Сказал бы он про графы управления (а себя графоманом? :mrgreen:) - я бы согласился. Но графы на Верилог вроде бы не ложатся ...
Впрочем разумеется переубеждать его не собираюсь, просто личное мнение.

Вот про трансляцию схем в программы и обратно - это круто, да. Только качество результата ... Лучше промолчу. Пожалуй как лет 15 назад с онлайн переводчиками, слова умеют, смысл фразы (кроме самых простых из пары-тройки слов) - не, не слышали. Зато накидал инженер схему, а искать/покупать детали и паять не нужно - скомпилил в плис и вперёд, проверять/тестировать/продавать. А как скорости перестало хватать - перекомпилил обратно в схему, развёл плату, купил всё, спаял - и скорость улетела к небесам. Красота же! Нет, серьёзно, это прорыв. Осталось допилить до нормального качества.

Кстати, про ЯВУ и компиляторы. По моему опыту я больше борюсь с компиляторами пытаясь понятным им языком объяснить что я хочу (что за структуру данных или функционал процедуры), чем реально придумываю/пишу код. Вот как объяснить компилятору С что мне нужен двухмерный массив, у которого в разных частях индексы меняются местами (то один первым увеличивается, то второй)? А вот нужно! Под имеющиеся аппаратные команды, выигрыш скорости больше порядка, год счёта или 10 лет, простите есть разница. Или структуры переменной длины полей, типа PNG файл, когда длина следующего поля зависит от кода в предыдущем. По моему в принципе невозможно, только побайтно разбирать, без всякого статического контроля типов. Зафига тогда тут вообще типизация, наследование, вся эта ООП? Да, наверное как-то всё это можно, и объяснить и написать и не смотреть что получится ... Но лично мне нравится именно низкий уровень, от транзисторов и немного выше, но сильно пониже функций ОС и уж тем более прикладных вещей типа GUI. Так я никого и не агитирую за асм на продажу и заработки.

 Профиль  
                  
 
 Re: Еще раз о пользе от ассемблера
Сообщение21.01.2024, 20:28 


18/11/18
498
Всё-таки, если ближе к телу, то есть, к железу - под любые семейства контроллеров не то что драйвера, а и сдк и тулчейны под что угодно разработаны.
Другое дело - разработчики самих контроллеров и драйверов, - тут возможно ещё долго останется низкоуровневое программирование. Но таких специалистов много и не надо.
Вообще не знаю, остались ли где ещё даже в профильных вузах дисциплины типа асма и проч. машинных кодов (хотя бы факультативно)?

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 25 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group