1. Assembler / Говнокод #25249

    −2

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    execute = 0
    i = 100
    while i < $
        load a byte from i
        if a = 0xc3
            execute = i
            i = $
        else
            i = i + 1
        end if
    end while
    
    if execute = 0
    display "ret not found", 13, 10
    execute = $
    ret
    end if

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

    Запостил: 3oJloTou_neTyx, 01 Января 2019

    Комментарии (23) RSS

    • Жаль, что с того места где первый раз используется execute уже не проверишь.
      Ответить
    • Именно поэтому я за «реальный режим»: в нём можно просканировать всю память.
      Ответить
    • А зачем эта штука ищет ret?
      Ответить
      • Мне нужна попдрограмма из одной этой инструкции, но я её нигде больше не юзал, думал, может этот байт найдётся где-нибудь в коде, но не нашлось. Можно ещё как-нибудь попробовать поперемещать подпрограммы, чтобы где-нибудь в смещениях получилось C3. Но это так, в порядке бреда ;)
        Ответить
        • С3 — это -61 (mod 256). Значит, нужно найти в программе JMP SHORT (или условный переход вроде JZ/JC) на 61 байт назад от конца инструкции, т. е. на 59 байтов от начала.

          Ещё можно попытаться найти C3 в байте mod R/M (в 32- или в 64-битном режиме ещё и в s-i-b).

          C3 расшифровывается как reg = AX (AL/EAX/RAX); r/m = BX (BL/EBX/RBX). Т. е. оба аргумента в регистрах, без ссылок на память. Это, например, MOV AX, BX (в одной кодировке) или MOV BX, AX (в другой кодировке).

          Для байта s-i-b C3 означает base = EBX (RBX), index = EAX (RAX), scale = 3, итого [EBX+EAX*8].
          Ответить
          • Так цикол это и делает, ищет в программе байт C3. И кстати вместо execute = i в 6 сторчке лучше написать label execute at i.
            Ответить
          • Замечание про кодировки. У того же MOV есть две формы:
            1. MOV R/M, reg
            Пример: 89 C3 = MOV BX, AX
            Другой ассемблер эту же инструкцию (MOV BX, AX) может закодировать как 8B D8.

            2. MOV reg, R/M
            Пример: 8B C3 = MOV AX, BX
            Другой ассемблер эту же инструкцию (MOV AX, BX) может закодировать как 89 D8.

            Опасно, правда?

            Есть инструкции, имеющие единственную кодировку. Например, в которых вместо одного из аргументов используются специальные регистры.
            8C C3 = MOV BX, ES
            8E C3 = MOV ES, BX
            Ответить
            • Хм, у меня в коде есь OR AX, BX, заменю на
              db 0x0b
              execute:
                  db 0xc3
              Спасибо, ты убил ещо один байт)
              Ответить
              • Мы недавно обсуждали 64-битную Винду. Чтобы не переключаться из «длинного» режима в «короткий», но при этом не потерять возможность вызывать функции BIOS, рассчитанные на реальный режим (или на V86), в HAL.DLL встроили эмулятор x86. Этот эмулятор заточен на то, что код BIOS будет генерироваться MASM'ом или Visual C, поэтому в нём реализованы не все варианты кодирования инструкций.

                В общем, если ты пишешь BIOS для машины, на которой будет запускаться 64-битная Windows, то при такой ручной сборке HAL.DLL может сглючить. В остальных случаях можешь смело использовать.
                Ответить
              • Не знаю, хорошо это или плохо, но для арм похожего не получится. И в машкодах для него прогромировать сложнее, я как-то пробовал, приходиться команду по битам собирать.
                Ответить
      • Если я правильно понял, другой петух хочет реализовать оптимизатор программ по размеру путём повторного использования цепочек опкодов.
        Ответить
        • Нет ты не правильно понял, я оптимизирую по размеру свою программу, и использую для автоматизацим этого препроцессор fasm'а.
          Ответить

    Добавить комментарий