2016-04-02 5 views
1

В классе, в котором я находится, мы назначаем простой симулятор mips. Инструкции, которые моя программа должна обрабатывать, приводятся в двоичном файле. Я понятия не имею, как извлечь из этого файла что-нибудь полезное. Вот мой код:Как я могу преобразовать двоичные данные из файла в читаемую базу двоичных двоичных файлов в python?

import struct 
import argparse 

'''open a parser to get command line arguments ''' 
parser = argparse.ArgumentParser(description='Mips instruction simulator') 

'''add two required arguments for the input file and the output file''' 
parser.add_argument('-i', action="store", dest='infile_name', help="-i INPUT_FILE", required=True) 
parser.add_argument('-o', action="store", dest='outfile_name', help="-o OUTPUT_FILE_NAME", required=True) 

'''get the passed arguments''' 
args = parser.parse_args() 


class Disassembler: 
    '''Disassembler for mips code''' 
    instruction_buffer = None 
    instructions_read = 0 

    def __init__(self, filename): 
     bin_file = None 
     try: 
      bin_file = open(filename, 'rb') 
     except: 
      print("Input file: ", filename, " could not be opened. Check the name, permissions, or path") 
      quit() 

     while True: 
      read_bytes = bin_file.read(4) 
      if (read_bytes == b''): 
       break 
      int_var = struct.unpack('>I', read_bytes) 
      print(int_var) 

     bin_file.close() 


disembler = Disassembler(args.infile_name) 

Итак, сначала я только что напечатал 4 байта, которые я прочитал, чтобы увидеть, что было возвращено. Я надеялся увидеть простые биты (только 1 и 0). То, что я получил, это байтовые строки из того, что я прочитал. Поэтому я попробовал поиск в Google, чтобы узнать, что я могу с этим поделать. Поэтому я нашел, что могу использовать struct для преобразования этих строк байтов в целые числа. Это выводит их в формате (4294967295,).

Это все еще раздражает, потому что мне нужно обрезать это, чтобы сделать его полезным целое, а затем еще нужно преобразовать его в биты (база 2). Приятно, что я могу читать байты со структурой как подписанные или без знака, потому что половина входного файла вводится 32-разрядными номерами.

Все это кажется более сложным, чем нужно, чтобы просто извлечь биты из двоичного файла. Есть ли более простой способ сделать это? Также вы можете объяснить это так, как если бы вы были знакомы с эзотерическим кодом на языке python и новичок в двоичных данных?

Моя общая цель - получить прямые 32 бита из каждых 4 байтов, которые я прочитал. Начало файла - это список кодов операций mips. Поэтому мне нужно уметь видеть определенные части этих чисел, например, первые 5 бит, затем следующие 6 или так далее. Конец файла содержит 32-битные знаковые значения со знаком. Две половины файлов разделяются кодом операции перерыва.

Благодарим за помощь, которую вы можете мне дать. Это сводит меня с ума, что я не могу найти прямых ответов при поиске. Если вы хотите увидеть двоичный файл, скажите мне, где и я опубликую его.

+0

Вы просто хотите [визуализировать] (https://stackoverflow.com/questions/18111488/convert-integer-to-binary-in-python-and-compare-the-bits) бит значения, или вы хотите, чтобы они были в [integer] (https: // stackoverflow.com/questions/30971079/how-do-i-convert-an-integer-to-a-list-of-bits-in-python) для дальнейшей манипуляции? – Reti43

+0

Мне нужно прочитать их как биты, которые я думаю. Потому что мне нужна определенная длина из каждого 32-битного значения. Например, мне нужно увидеть, что такое первые 6 бит, затем следующие 5 и т. Д. Поэтому мне нужны значения в прямых битах, которые я думаю. Если нет лучшего способа сделать это, но, насколько мне известно, это единственный способ, которым я знаю, как работать с данными. – Jacob

+0

Есть несколько способов сделать это. Посмотрите на ссылки выше в моем комментарии. Я бы посоветовал вам также указать в вопросе, какова ваша цель, иначе мы не сможем предложить лучшие подходы к решению, которое вы пытаетесь реализовать в вопросе. – Reti43

ответ

1

Имейте в виду, что обычные целые Python не имеют фиксированную разрядность: они столь же большой, как они должны быть. Это может раздражать, когда вы хотите преобразовать целые числа со знаком в битовые строки. Я рекомендую вам придерживаться того, что вы сейчас делаете: конвертирование блоки по 4 байта в целое число без знака, используя

n = struct.unpack('>I', read_bytes)[0] 

, а затем, используя либо format(n, '032b') или '{0:032b}'.format(n) преобразовать, что в битовую строку, если вы хотите напечатать биты ,

Чтобы получить доступ или изменить биты в целом числе, вы не должны возиться с преобразованием строки, вместо этого вы должны использовать битовые операторы языка Python, &, |, ^, <<, >>, ~. Например, (n >> 7) & 1 дает вам бит 7 из n.

Для получения подробной информации об этих операторах см. Unary arithmetic and bitwise operations и следующие разделы в документах Python.

+0

Так что же там? То, что я получаю от структуры, это «, (2370044120,)» для числа. Могу я просто передать это прямо в формат? Кроме того, как работают побитовые операторы python? >> Правильно ли сдвиг? Что делает & 1? Могут ли побитовые операторы работать над тем, что было возвращено из struct? – Jacob

+0

Извините, @Jacob, я забыл, что 'struct.unpack' всегда возвращает кортеж. Я исправил свой код так, что 'n' теперь является целым числом Python. И гарантировано, что это будет 32-значный номер без знака по спецификации формата «> I». –

+0

@Jacob: Да, '>>' - это правый сдвиг, '&' побитовое И, поэтому 'c = a & b' выполняет операцию И по соответствующим битам целых чисел' a' и 'b', помещая результаты в соответствующие биты 'c'. Следовательно, 'n & 1' оценивает младший значащий бит' n'. Побитовые операторы Python работают так же, как на C и многих других языках (кроме того, что целые числа Python не имеют фиксированной ширины бита); Я понял, что вы будете знакомы с побитовыми операторами, если вы делаете дизассемблер. :) –

0

Таким образом вы можете получить доступ к каждому отдельному биту в файле.

"".join(format(i, "08b") for i in byte_string) 

Например:

>>> "".join(format(i, "08b") for i in b"\x23\x54a") 
'001000110101010001100001' 
+0

'bin' не дает вам никакого контроля над длиной результирующей строки, и она добавляет' '0b'', который вы обычно хотите срезать, как это делает ваш код. Функция или метод 'format' превосходят оба значения. Например, 'format (n, '032b')' –

+0

Я видел это в других вопросах. Единственная причина, по которой я не решаюсь ее использовать, - я не знаю, как это работает. Таким образом, объединение добавляет все в него к пустой строке. bin (i) преобразует число в двоичный, и тогда [2:] избавится от префикса 0b? я чувствую, что это достаточно прямо, но почему для i в b "\ x23 \ x53a" рядом с ним? Что делает цикл for рядом с функцией bin? какова петля? Каждый байт? – Jacob

+0

@ PM2Ring Спасибо. Я изменил его на '08b', так как каждый байт имеет 8 бит, вам не нужно каждый раз конвертировать 4 байта в int. – Bharel