Commits

insolor committed 37ff200

Some general machcodeworking functions moved to disasm.e

  • Participants
  • Parent commits a300472

Comments (0)

Files changed (2)

 function align(atom n, atom edge = 4)
     return and_bits(n+edge-1, -edge)
 end function
+
+-- В соответствии с битом знака изменить знак числа
+public
+function check_sign_bit(atom x, integer w) -- x - значение, w - ширина в битах (номер бита знака + 1)
+    if and_bits(x, power(2, w-1)) then
+        x -= power(2, w)
+    end if
+    return x
+end function
+
+-- Функция по данным, полученным из analyse_modrm(), определяет место назначения
+public
+function process_operands(sequence x)
+    sequence modrm = x[1], sib
+    integer basereg, disp -- текущие базовый регистр и смещение
+    
+    -- Узнаем базовый регистр
+    if modrm[3] != 4 then -- без байта SIB (Scale/Index/Base)
+        basereg = modrm[3]
+    else  -- используется байт SIB
+        sib = x[2]
+        if sib[1] != 0 or sib[2] != 4 then -- масштаб != 2 pow 0 или указан индексный регистр
+            return -1
+        end if
+        basereg = sib[3]
+    end if
+    
+    if modrm[1] = 0 then -- без смещения
+        disp = 0
+    else
+        disp = x[$-1]
+    end if
+    
+    return {basereg, disp, x[$]} -- x[$] возвращается для совместимости
+end function
+
+-- Анализ байта mod r/m и выбор соответствующего типа адресации
+-- На входе: набор байт машинного кода. Первый байт - mod r/m
+public
+function analyse_modrm(sequence s, integer i)
+    sequence modrm, sib
+    sequence result
+    atom disp = 0
+    modrm = triads(s[i])
+    i += 1
+    result = {modrm}
+    if modrm[1] != 3 then -- Не регистровая адресация
+        if modrm[1] = 0 and modrm[3] = 5 then
+            -- Прямая адресация [imm32]
+            result &= bytes_to_int(s[i..i+3])
+            i += 4
+        else
+            if modrm[3] = 4 then
+                -- Косвенная адресация по базе с масштабированием
+                sib = triads(s[i])
+                i += 1
+                result = append(result, sib)
+            end if
+            
+            if modrm[1] = 1 then
+                disp = check_sign_bit(s[i], 8)
+                i += 1
+                result &= disp
+            elsif modrm[1] = 2 then
+                disp = check_sign_bit(bytes_to_int(s[i..i+3]), 32)
+                i += 4
+                result &= disp
+            end if
+        end if
+    end if
+    return result & i -- {{триады байта modrm}, [{триады байта sib},] смещение, i}
+end function
+
+-- Попытка вынести анализирующий код в отдельную функцию
+-- На входе: набор байт машинного кода
+-- На выходе: см. последний return.
+public
+function analyse_mach(sequence s, integer i=1)
+    integer op, j = i
+    sequence modrm, sib
+    sequence result
+    if s[i] = PREFIX_OPERAND_SIZE then
+        i += 1
+    end if
+    -- Префикс смены режима адресации пока не поддерживается
+    op = s[i]
+    result = {s[j..i]}
+    i += 1
+    if and_bits(op, #FE) = MOV_ACC_MEM then
+        result &= {bytes_to_int(s[i..i+3]), i+4}
+    elsif and_bits(op, #FC) = MOV_RM_REG or op = LEA then
+        result &= analyse_modrm(s, i)
+    else
+        return -1
+    end if
+    return result -- {{операция}, {modrm}, {sib}, непосредственный операнд, индекс следующей инструкции}
+end function
     end if
 end procedure
 
--- В соответствии с битом знака изменить знак числа
--- @todo: переместить в disasm.e
-function check_sign_bit(atom x, integer w) -- x - значение, w - ширина в битах (номер бита знака + 1)
-    if and_bits(x, power(2, w-1)) then
-        x -= power(2, w)
-    end if
-    return x
-end function
-
--- Функция по данным, полученным из analyse_modrm(), определяет место назначения
-function process_operands(sequence x)
-    sequence modrm = x[1], sib
-    integer basereg, disp -- текущие базовый регистр и смещение
-    
-    -- Узнаем базовый регистр
-    if modrm[3] != 4 then -- без байта SIB (Scale/Index/Base)
-        basereg = modrm[3]
-    else  -- используется байт SIB
-        sib = x[2]
-        if sib[1] != 0 or sib[2] != 4 then -- масштаб != 2 pow 0 или указан индексный регистр
-            return -1
-        end if
-        basereg = sib[3]
-    end if
-    
-    if modrm[1] = 0 then -- без смещения
-        disp = 0
-    else
-        disp = x[$-1]
-    end if
-    
-    return {basereg, disp, x[$]} -- x[$] возвращается для совместимости
-end function
-
--- Анализ байта mod r/m и выбор соответствующего типа адресации
--- На входе: набор байт машинного кода. Первый байт - mod r/m
-function analyse_modrm(sequence s, integer i)
-    sequence modrm, sib
-    sequence result
-    atom disp = 0
-    modrm = triads(s[i])
-    i += 1
-    result = {modrm}
-    if modrm[1] != 3 then -- Не регистровая адресация
-        if modrm[1] = 0 and modrm[3] = 5 then
-            -- Прямая адресация [imm32]
-            result &= bytes_to_int(s[i..i+3])
-            i += 4
-        else
-            if modrm[3] = 4 then
-                -- Косвенная адресация по базе с масштабированием
-                sib = triads(s[i])
-                i += 1
-                result = append(result, sib)
-            end if
-            
-            if modrm[1] = 1 then
-                disp = check_sign_bit(s[i], 8)
-                i += 1
-                result &= disp
-            elsif modrm[1] = 2 then
-                disp = check_sign_bit(bytes_to_int(s[i..i+3]), 32)
-                i += 4
-                result &= disp
-            end if
-        end if
-    end if
-    return result & i -- {{триады байта modrm}, [{триады байта sib},] смещение, i}
-end function
-
--- Попытка вынести анализирующий код в отдельную функцию
--- На входе: набор байт машинного кода
--- На выходе: см. последний return.
-function analyse_mach(sequence s, integer i=1)
-    integer op, j = i
-    sequence modrm, sib
-    sequence result
-    if s[i] = PREFIX_OPERAND_SIZE then
-        i += 1
-    end if
-    -- Префикс смены режима адресации пока не поддерживается
-    op = s[i]
-    result = {s[j..i]}
-    i += 1
-    if and_bits(op, #FE) = MOV_ACC_MEM then
-        result &= {bytes_to_int(s[i..i+3]), i+4}
-    elsif and_bits(op, #FC) = MOV_RM_REG or op = LEA then
-        result &= analyse_modrm(s, i)
-    else
-        return -1
-    end if
-    return result -- {{операция}, {modrm}, {sib}, непосредственный операнд, индекс следующей инструкции}
-end function
-
 -- Определить длину (в байтах) инструкций, копирующих строку, также нужно определить куда копируется строка
 -- На входе: набор байт машинного кода
 -- На выходе: см. последний return.