Как мне добавить два числа по 12 байт каждый? - PullRequest
0 голосов
/ 30 января 2019

Я хочу добавить два числа по 12 байт и сохранить результат в 16-байтовой переменной.Как я могу это сделать?

section .data
    big_num1 dd 0x11111111, 0x22222222, 0x33333333
    big_num2 dd 0xffffffff, 0x22222222, 0x33333333
section .bss   
    result_4word resd 4

Я думаю, что могу добавить первые 4 байта из числа 1 с другими первыми 4 байтами из числа 2 и так далее ... но я не знаю, как это сделатьобъединить результаты в моей переменной результата.Как мне сделать переноску, если она нужна?Является ли это решение правильным?

xor eax, eax
xor ebx, ebx
mov ecx, 3
loop1:
mov eax, dword[big_num1+4*(ecx-1)]
mov ebx, dword[big_num2+4*(ecx-1)]
mov [result_4word+4*(ecx-1)], eax
adc [result_4word+4*(ecx-1)], ebx
loop loop1

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Начальная школа:

   1234
+  5678
========

начните заполнять ее

     1
   1234
+  5678
========
      2

4 + 8 = 12, поэтому 2 носите одну.

на компьютере, который выдобавит a = 4 + 8 adc b = 3 + 7 adc c = 2 + 6 adc d = 1 + 5

, тогда dcba будет содержать ваш результат, он масштабируется так, как вы хотите.d, c, b, a могут быть 8-битными, 16-битными, 32-битными или 64-битными в зависимости от набора команд.у большинства есть add и adc, если у них есть флаги, те, у которых нет флагов, тогда вы можете синтезировать их различными способами, которые совсем не сложны ... (разбейте ваши операнды на 16-битные величины, используя 32-битные регистры / память, делайте 32bit add now bit 16 - это ваш результат, добавьте его в следующий 16-битный блок, он требует некоторого сдвига и маскирования, но все работает одинаково, так как у вас, вероятно, есть adc, вам не нужно делать ничего из этого, просто выполните тривиальное добавление, adc, adc, adc ... до завершения.

Если вы снимаете флажок перед началом, вы можете использовать adc в цикле.

Теперь, если ваши переменные не совпадают ссумматор в процессоре, то вам нужно каким-то образом его синтезировать.

Математика начальной школы для той же задачи, теперь вы должны сделать столбцы отдельно.

  4
+ 8
====
 12

и у вас естьчтобы вручную замаскировать и сдвинуть результат (12 >> 1)% 9 = 1 в базе 10.

  1
  3
+ 7
====
 11

, затем

  1
  2
+ 6
====
  9

этот несет ноль

  0
  1
+ 5
====
  6
0 голосов
/ 31 января 2019
big_num1 dd 0x11111111, 0x22222222, 0x33333333
big_num2 dd 0xffffffff, 0x22222222, 0x33333333

Какие числа определены здесь?

Поскольку - это архитектура с прямым порядком байтов, самая низкая часть числа хранится в памяти всамые низкие адреса.Для big_num1 первое определенное слово (значение 0x11111111) находится по самому низкому адресу и, следовательно, является самой низкой частью числа.В обычном представлении чисел это то, что идет справа:

big_num1 == 0x333333332222222211111111
big_num2 == 0x3333333322222222FFFFFFFF

Добавление больших чисел

Вы добавляете соответствующие цифры, идущие справа налево, как все учили в школе.

В шестнадцатеричном представлении этих чисел необходимо рассмотреть 24 цифры.Однако, поскольку архитектура 32-разрядная, мы можем сделать 3 группы по 8 цифр.

Для 1-й группы мы просто используем ADD:

mov     eax, [big_num1]           ;   0x11111111
add     eax, [big_num2]           ; + 0xFFFFFFFF <-- This produces a carry
mov     [result_4dword], eax      ;   0x00000000

Для 2-й группы мыиспользуйте ADC, чтобы подобрать возможный перенос из предыдущего дополнения:

mov     eax, [big_num1 + 4]       ;   0x22222222
adc     eax, [big_num2 + 4]       ; + 0x22222222 + CF=1  <-- No new carry
mov     [result_4dword + 4], eax  ;   0x44444445

Для 3-й группы мы используем ADC, чтобы подобрать возможный перенос из предыдущего дополнения:

mov     eax, [big_num1 + 8]       ;   0x33333333
adc     eax, [big_num2 + 8]       ; + 0x33333333 + CF=0  <-- No new carry
mov     [result_4dword + 8], eax  ;   0x66666666

Превращая это в цикл

Ключ в том, что мы также можем использовать ADC для 1-й группы , если мы явно очистим флаг переноса заранее:

clc
mov     eax, [big_num1]           ;   0x11111111
adc     eax, [big_num2]           ; + 0xFFFFFFFF + CF=0 <-- This produces a carry
mov     [result_4dword], eax      ;   0x00000000

Теперь мы можем написать цикл с 3 итерациями, но у нас есть , чтобы не допустить случайного изменения флага переноса .Вот почему я использую LEA вместо ADD, чтобы увеличить смещение.DEC также инструкция, которая не уничтожает флаг переноса.Я предпочел комбо DEC ECX JNZ ..., потому что оно лучше, чем LOOP ...:

    mov     ecx, 3
    xor     ebx, ebx              ; This additionally clears the carry flag
Again:
    mov     eax, [big_num1 + ebx]
    adc     eax, [big_num2 + ebx] ; Can produce a new carry flag
    mov     [result_4dword + ebx], eax
    lea     ebx, [ebx + 4]        ; This does not clobber the carry flag
    dec     ecx                   ; This does not clobber the carry flag
    jnz     Again

Если после этих 3 дополнений все еще есть набор переносов, вам придется написать 1 в 4-м dword result_4dword , иначе вам придется написать 0 здесь.Поскольку result_4dword находится в разделе .bss, вы не должны рассчитывать на любое заданное значение, например, ноль!

    setc    cl
    mov     [result_4dword + ebx], ecx  ; ECX=[0,1]

Обратите внимание, что я изменил result_4word в result_4 d word .Имеет больше смысла ...

...