Ответы пользователя по тегу Assembler
  • Не работает деление в ассемблере. Что я сделал не так?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    mov edx, [arr16] ; заносим в edx первый элемент массива
    mov eax, [arr16+4] ; заносим в eax второй элемент массива

    Начнём с того, что в edx нужно поместить старшую часть делимого, а в eax -- младшую, а на x86 слова в память записываются младшей частью вперёд (little endian).

    Если результат деления не помещается в eax вы получите исключение #DE, а при делении числа 0x0000000100000000 (а именно его вы делите, загрузив в eax 0 а в edx 1) на 1 результат определённо в 32 бита не влезет.

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

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    А вы можете объяснить, что у вас происходит здесь:
    srav:
        repe cmps s1,s2
        mov bx,0
        dec di
        mov s3[bx],di
        inc di
        inc bx
        loop srav


    Кроме того, для вывода строки функцией 9 int21 она должна заканчиваться символом '$'.
    Ответ написан
  • Почему сопроцессор в тысячу раз медленнее процессора?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Кто подскажет, что я делаю не так?


    Это:
    clock_t strt = clock();
    ...
    clock_t bk1 = clock() - strt;
    ...
    clock_t bk2 = clock() - bk1;

    bk1 -- это разность абсолютных времён, т.е. продолжительность, а bk2 -- это разность абсолютного времени и продолжительности, т.е. абсолютное время.

    Ок, после исправления этого бага я вижу проблему с переполнением стека сопроцессора: fadd не сдвигает стек обратно и fld его очень быстро переполняет.

    С переполнением стека я тоже наблюдаю, что fpu работает ~ в 1000 раз медленнее чем ALU. Но если сбалансировать загрузки, операции и выгрузки так, чтобы стек не переполнялся у меня все работает со сравнимой скоростью. Подозреваю, что там случается исключение, но оно не фатальное и молча глотается ядром.

    Я тестировал следующий код (выкинул вообще всё лишнее):
    #include <stdio.h>
    #include <inttypes.h>
    #include <time.h>
    
    #define MAX_I 4000000
    
    int32_t rezult[64];
    
    void StartPR(int str)
    {
            asm volatile ("mov $4000000, %%eax\n\t"
                          "xor %%ebx, %%ebx\n\t"
                          "xor %%ecx, %%ecx\n\t"
                          "xor %%edx, %%edx\n"
    
                          "circle:\n\t"
                          "add %%eax, %%ebx\n\t"
                          "add %%eax, %%ecx\n\t"
                          "add %%eax, %%edx\n\t"
                          "dec %%eax\n\t"
                          "jnz circle\n\t" ::: "memory");
    }
    
    void StartMMX(int str)
    {
            double v = 4000000;
            asm volatile ("mov $4000000, %%eax\n\t"
                          "fldz\n\t"
    
                          "circle2:\n\t"
                          "fld %0\n\t"
                          "faddp \n\t"
                          "fld %0\n\t"
                          "faddp \n\t"
                          "fld %0\n\t"
                          "faddp \n\t"
                          "fld %0\n\t"
                          "faddp \n\t"
                          "sub $4, %%eax\n\t"
                          "jnz circle2\n\t"
                          "fstp %0" :"+m"(v):: "memory");
    }
    
    void stardThreads(int numOfThread)
    {
            printf("threads: %i", numOfThread);
            int i = 0;
            clock_t strt = clock();
            StartPR(0);
    
            clock_t strt2 = clock();
            clock_t bk1 = strt2 - strt;
    
            StartMMX(i);
            clock_t bk2 = clock() - strt2;
            printf("time block1:%i, block2:%i, tics per second:%i\n", (int32_t)bk1, (int32_t)bk2, CLOCKS_PER_SEC);
    }
    
    int main(int argc, char *argv[])
    {
            int i;
            for (i = 1; i < 9; i++)
                    stardThreads(i);
    
            return 0;
    }


    Результат:
    threads: 1time block1:6949, block2:9311, tics per second:1000000
    threads: 2time block1:4061, block2:7872, tics per second:1000000
    threads: 3time block1:3901, block2:7398, tics per second:1000000
    threads: 4time block1:3615, block2:7045, tics per second:1000000
    threads: 5time block1:3389, block2:6716, tics per second:1000000
    threads: 6time block1:3250, block2:6342, tics per second:1000000
    threads: 7time block1:3189, block2:6036, tics per second:1000000
    threads: 8time block1:3032, block2:5885, tics per second:1000000
    Ответ написан
    4 комментария
  • Как вывести формулу из дизассемблерного кода?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как вывести формулу из дизассемблерного кода

    Выписав выражения элементарных математических действий соответствующих ассемблерным командам и подставив выражения друг в друга, согласно тому, как использованы регистры и переменные в памяти.
    Например:
    mov 0x10(%ebp),%edx
    -- это "поместить в edx третий параметр функции (назовём их a (0x8(%ebp)), b (0xc(%ebp)) и c (0x10(%ebp))): edx = c"

    mov %edx,%eax
    -- "поместить в eax edx, который равен c, т.е. eax = c"

    shl $0x2,%eax
    -- сдвинуть eax на 2 влево, т.е. умножить на 4, т.е. eax = c * 4

    и т. д.

    Результат -- то что останется в eax перед возвратом.
    Ответ написан
    Комментировать
  • Чем ASEM51 отличается от A51?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    чем кросс-ассемблер отличается от макроассемблера?

    Макроассемблер -- это ассемблер поддерживающий макросы.
    Кросс-ассемблер -- это ассемблер, генерирующий код для процессора, архитектура которого отлична от той, на которой он сам выполняется.
    Макроассемблер может быть кросс-ассемблером.
    Ответ написан
    Комментировать
  • Вопрос о сегментных регистрах и процессе загрузки регистра DS?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    откуда программа может знать где окажутся ее данные чтобы самой указать это значение?

    Она не может знать до загрузки, поэтому все сегментные части адресов записаны как смещения относительно начала программы, т.е. как будто программа будет загружена по адресу 0. EXE-файл содержит таблицу релокаций, это массив смещений относительно начала программы, по которым находятся сегментные части адресов. Загрузчик EXE-файла проходит по этому массиву и прибавляет к словам в памяти фактический сегментный адрес, по которому программа загружена.
    Ответ написан
    2 комментария
  • Как поделить числа в неполных регистрах?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Помимо ручного обнуления верхних половин 16-битных регистров есть (начиная с i386) инструкции movzx и movsx, перемещающие данные между регистрами разного размера, расширяя их нулём или знаком.
    Т.е.
    mov al, dl
    mov ah, 0

    это
    movzx ax, dl
    Ответ написан
    Комментировать
  • Зачем нужно выравнивание (ассемблерного) кода при компиляции (линковке)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Зачем нужно выравнивание (ассемблерного) кода

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

    Нет.
    Ответ написан
    Комментировать
  • Как исправить код так, чтобы заменялись все символы (tasm/masm)?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что-то такое должно быть во втором примере:

    ...
      lea di, s 				; s строка приёмник
    
      cld 					; читаем строку слева направо
    m0:
      mov al, ast
      repne scasb  				; поиск совпадения
      jne m1				; если символ не найден переход на m1
    
      mov al, oct
      dec di
      stosb  				; замена символа
      jmp m0
    
    m1:	mov ah, 09h
      ...
    Ответ написан
  • Не пойму почему метка не работает так как нужно masm32?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    mov eax,offset i
    mov ebx,zero
    next:cmp eax,pr
    jne nextEl; если пробел равен элементу строки то должно перейти на следующую строку

    ...а сравниваются, между тем, адрес строки и адрес переменной содержащей пробел.
    Должно быть как-то так:
    mov eax,offset i
    mov ebx,zero
    next:cmp byte ptr [eax], 20h
    jne nextEl

    Дальше код тоже барахло.
    Изучите то, как записываются разные виды адресации в вашем ассемблере. Например: www.c-jump.com/CIS77/ASM/Addressing/lecture.html#R...
    Ответ написан
    1 комментарий
  • Алгоритм приведения вещественного числа к одинарной точности?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Примерно так это можно сделать:
    • скопировать знак;
    • извлечь порядок, отделить специальные случаи:
      • 0 и денормализованные числа становятся нулём;
      • бесконечность -- бесконечностью;
      • не-числа -- не-числами с обрезанной под новую точность мантиссой
    • в противном случае (обычное значение) убрать смещение порядка для double;
    • проверить, что несмещённый порядок помещается в диапазон float. Возможны 4 варианта:
      • не помещается (больше) -- записать в результат бесконечность;
      • помещается -- извлечь мантиссу;
      • не помещается (меньше, но может поместиться как денормализованное) -- извлечь мантиссу, добавить явный старший бит, сдвинуть вправо на разность порядка, извлечённого из double и минимального порядка float. Заменить извлечённый порядок минимальным порядком float;
      • не помещается (меньше) -- записать в результат 0;
    • добавить смещение порядка для float и запаковать в результат;
    • извлечь мантиссу, округлить, согласно текущей модели округления (см. [3]);
      • если при этом случилось переполнение увеличить порядок float (если тут тоже случилось переполнение, то в результате будет записан INF, что и требовалось);
    • запаковать мантиссу в результат.


    Ссылки:
    [1] https://en.wikipedia.org/wiki/Single-precision_flo...
    [2] https://en.wikipedia.org/wiki/Double-precision_flo...
    [3] https://en.wikipedia.org/wiki/IEEE_floating_point#...
    Ответ написан
    2 комментария
  • Си в высокоуровневый ассемблер?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что отличает высокоуровневый ассемблер от низкоуровневого?
    Может вам не ассемблер нужен, а какая-нибудь SSA-форма?
    Ответ написан
    Комментировать
  • Как работать со строками на AVR Assembler?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Какой инструкцией можно читать данные из флеша?

    lpm
    Возможны ли конструкции
    mov bx,byte[i+1]

    Для программной памяти -- нет.

    ldi r30, lo8(Message)
    ldi r31, hi8(Message)
    
    loop:
    
    lpm
    adiw r30, 1
    mov byte, r0
    ldi temp,0x01		;RS-bit (0 - sending command, 1 - send data)
    rcall send_byte		;Call procedure for send a symbol as 4-bit mode
    delayClocks 100,1,1     ;some delay
    dec len	                ;len is length of string
    brne loop
    Ответ написан
    4 комментария
  • Как изменить код функции на ассемблере?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как изменить эту функцию, чтобы она преобразовывала результат в Integer, а не LongInt

    Если integer имеет ту же или меньшую ширину, что и longint (что, например, так для компилятора fpc), то ничего менять не надо.

    function sar32(value: Int64; shift: longint): longint;

    Для такого прототипа надо поменять примерно так (для borland register calling convention):

    function sar32(value: Int64; shift: longint): longint;
    asm
      shrd eax, edx, cl
      end;
    Ответ написан
    8 комментариев
  • Какую литературу выбрать крайне ленивому студенту?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Написать эту программу на С, оттранслировать в ассемблер, прочитать и понять, что получилось и как это работает.
    Ответ написан
    Комментировать
  • Вывод диагонали квадратной матрицы. Как правильно на АСМ + Си?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    imul eax, 4

    shl eax, 2 же. Или даже
    lea edx, dword ptr [eсx * 4 + 4]
    (почему +4 -- см. ниже).

    push edx
    ...
    pop edx

    Зачем? У тебя полно регистров -- используй их.

    add eax, edx
    add eax, 4

    Слабо было перед циклом сделать edx сразу правильным?
    Ответ написан
    1 комментарий
  • Для чего нужен этот участок кода?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Это организация кадра стека: pushq %rbp сохраняет текущий указатель кадра стека, movq %rsp, %rbp устанавливает новый.
    Аннотации начинающиеся с .cfi_ управляют отладочной информацией, которой пользуются дебагер и механизм раскручивания стека при исключениях:
    .cfi_startproc задаёт начало процедуры и устанавливает начальный регистр и смещение для расчёта адреса CFA (Canonical Frame Address).
    .cfi_def_cfa_offset 16 обновляет смещение CFA, говоря, что оно стало равно 16 относительно заданного (директивой .cfi_startproc) регистра (%rsp).
    .cfi_offset 6, -16 говорит, что теперь регистр 6 лежит по смещению -16 от CFA (таким образом была описана инструкция pushq %rbp).
    .cfi_def_cfa_register 6 говорит, что теперь для расчёта адреса CFA используется регистр 6.

    Подробности о .cfi_ можно найти в info as, а большую картину -- в главе 6.4 стандарта DWARF.
    Ответ написан
    Комментировать
  • Есть ли хорошие книги про 64-битный ассемблер?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Ответ написан
    Комментировать
  • Что делает этот участок кода?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Что делает этот участок кода ?

    Возвращает 0x00234D30

    Чему будет pwd равен ?

    Полагаю, что "12j3h0Fv7k8L85f93u3TT023m8n3", но это вопрос больше по .net чем по asm.
    Ответ написан
    1 комментарий
  • Как использовать opendir в NASM?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Не могу найти номер системного вызова opendir

    Нет такого системного вызова.
    Простым вызовом open, дескриптор каталога не возвращается

    Добавьте флаг O_DIRECTORY в параметр flags.
    Ответ написан