Есть ли когда-нибудь ситуация, когда ASM просто недостаточно низкоуровневая? В конце концов, сборщик все еще должен быть собран. Кто-нибудь когда-либо писал программу в двоичном формате? Мне просто интересно, есть ли когда-нибудь теоретическая причина, почему это может быть практичным или даже если это возможно на современных компьютерах.
Будет ли когда-нибудь причина писать код в чистом двоичном формате?
Ответ 1
Историческая причина.. Вы запускаете машину, на которой требуется, чтобы ее загрузочный код включался на передней панели. (И да, это было сделано. Регулярно в первых двух поколениях машин.)
Не-то, что вы искали, по современной причине:. Когда вы пишете ассемблер, вам нужно выяснить этот процесс.
Ответ 2
В 1997 году я делал это на калькуляторах TI-83, когда я учился в школе и не имел доступа к кабелю связи.
Обычно в это время вы просто пишете программу сборки, используйте TASM для ее сборки, а затем передаете ее в калькулятор через соединительный кабель. Но если мне было скучно и я хотел собрать что-то маленькое, я запомнил достаточно байтовых инструкций, чтобы иметь возможность вводить их для определенных вещей.
Боковое примечание Конечно, это было весело, если в программе была ошибка, потому что она могла легко повредить всю память калькулятора. Таким образом, вам придется удерживать кнопку ON и/или удалять батареи AAA и надеяться, что этого было достаточно для восстановления calc (без каких-либо программ, которые были в памяти). В противном случае для жесткого reset вам придется использовать отвертку, чтобы вывинтить специальную резервную батарею. Хорошие времена...
Ответ 3
Вы получили это, если нет [dis] ассемблера. Я был в ситуации взлома прошивки, где я потратил достаточно времени, глядя на необработанные потоки команд PowerPC, чтобы иметь возможность распознавать и вручную собирать несколько видов инструкций. (Я закончил перенос дизассемблера: http://homepage.mac.com/potswa/source/DisDave.sit, если вы можете установить его.)
Некоторые ISA намного проще других. RISC следуют простым форматам и легко ориентируются, потому что инструкции обычно имеют одинаковую длину и соответствуют границам слов. x86-64, с другой стороны, заполнен кодировками переменной длины и префиксными кодами.
В проектах FPGA или когда задействована пользовательская схема, очень часто приходится разрабатывать какой-то поток команд и вручную кодировать его в двоичном формате.
Ответ 4
Когда вы взламываете двоичные форматы вручную, Учебное пособие по вихрям по созданию Really Teensy ELF Executables для Linux.
Ответ 5
Генерация динамического кода:
Если у вас есть очень простая проблема для решения, и производительность важна, часто бывает полезно анализировать проблемное пространство и генерировать специализированную функцию "на лету" для решения проблемы.
Один практический пример: высокопроизводительная математика с разреженными матрицами.
Это часто связано с умножением массивов чисел на тысячи и миллионы раз. Поскольку множество матричных элементов может быть нулевым или одно, вы можете сэкономить значительное количество времени, если вы удалите все тривиальные умножения.
Для этого небольшой генератор кода может анализировать матрицы и генерировать машинный код для арифметики матрицы "на лету". Как это может быть от использования библиотеки JIT (или встроенной функции языка) до очень простых схем.
Для случая разреженных матричных умножений вы можете получить отличную производительность, просто склеивая предварительно построенные фрагменты кода для разных случаев вместе. Это можно сделать в 50 строках C-кода.
Ответ 6
Когда я тренировался во время моих военно-морских дней (примерно в 1986 году), у нас есть компьютер, на котором нам было дано узнать об устранении неполадок электроники, а не программировании устранения неполадок, которое было запрограммировано путем ввода двоичной информации в переднюю часть компьютера, и мы должны были проинформировать инструктора о том, что они сломали в машине на основе результатов, а также об устранении неполадок оборудования. Насколько я знаю, все еще может быть одна из этих машин.
Мне хотелось бы найти исходный код для этого, я на самом деле написал симулятор машины и компиляцию для языка для машины. Удивительно, сколько работы вы могли бы сделать с 1024 байтами памяти!:)
Ответ 7
- используя недокументированные коды операций (все еще на нескольких современных процессорах!) это не так давно на процессорах на базе 6502.
- при мигании программы в домашние схемы с микроконтроллером. Микроконтроллеры полезны для всех видов вещей в наши дни.
Ответ 8
Помню, что Woz написал первый машинный язык Apple BASIC (Apple I? Apple II?). Перед тем, как у них были устройства хранения, вам нужно было ввести шестнадцатеричные коды на мониторе.
Ответ 9
Даже если вы обнаружите, что пропустите ассемблер и перейдете непосредственно к машинным кодам, вы не будете использовать двоичный код, но вместо этого шестнадцатеричный.
В школе мне пришлось исправлять код в памяти с помощью отладчика без использования ассемблера. Несмотря на то, что это развлечение, это навык практически без ценности вне отладки встроенных систем.
Кроме того, учтите, что мнемоника кода операции, используемая в сборке, должна иметь соответствие 1:1 с фактическими кодами операций (таким образом, термин "мнемоника" ), поэтому вы не сможете ничего сделать, избивая машинный код вручную, чтобы вы не удалось сделать в сборке. Роль ассемблера заключается в том, чтобы преобразовать мнемонику в коды операций (также определить, какая версия конкретной инструкции должна использоваться - непосредственные или косвенные MOV, например), метки для адресов и подобные задачи.
Хорошо знать, что происходит внутри ассемблера, но это почти никогда не придет, если вы не ищете ошибку в ассемблере, взломали встроенный гаджет или MacGyvering ваш выход из действительно, действительно странной ситуации.
Ответ 10
В пост-апокалипсическом мире, где все клавиатуры и мониторы были уничтожены, и единственный способ запрограммировать тетрис на ваш компьютер - это переключение на вашу переднюю панель, да.
Но серьезно, почему кто-то захочет это сделать?
Изменить: очевидно, есть люди, которые разрабатывают процессоры, которые должны программировать в двоичном формате, пока они не смогут получить ассемблер, работающий на своих процессорах, но они представляют собой очень небольшую группу людей.
Ответ 11
У меня не было ассемблера для моего восьмибитного Atari, поэтому я написал машинный код напрямую. Чтобы запустить код с BASIC, вы либо записываете код как десятичные байты данных, либо как строку. (Да, вы могли бы написать код в строке, единственный код символа из 256, который вы не могли ввести, был 155 - код для возврата. К счастью, инструкция с машинным кодом 6502 с этим значением не была такой, проблема, когда ветвь оказалась на 101 байт назад (-101 = 155).)
Я все еще помню общую часть кода для запуска таймера:
104 (pla)
169, 7 (lda #7)
162, 6 (ldx #6)
160, 10 (ldy #10)
76, 92, 228 (jmp 0xE45C)
В последние годы я участвовал в некоторых соревнованиях по оптимизации размеров. Несмотря на то, что большая часть кода является сборкой, вы все равно должны точно знать, какие команды производит ассемблер, чтобы вы знали, сколько байтов они есть. Кроме того, иногда вы используете трюки, такие как использование некоторых байтов как в качестве данных, так и в виде кода или наличие некоторых байтов в разных инструкциях в зависимости от того, вводите ли вы первый байт или введите в середине инструкции. Затем вы пишете инструкции в виде байтов данных в середине кода сборки.
Ответ 12
Несколько раз вам полезно работать с исходным машинным кодом, а не только с ассемблером. Например, рассмотрите отправку двоичного файла по электронной почте, но с программой электронной почты, которая не знает, как декодировать вложения. В свое время несколько человек писали небольшие программы, которые могли бы декодировать остальную часть вложения, но все в программе было печатным символом. Итак, вы расшифруете ваше вложение, вы сохраните тело письма как whatever.com
, а затем выполните его. Он расшифровывает вложение и записывает двоичный файл, который вы могли бы выполнить.
В другом примере, много лет назад, на Fidonet, была довольно простая задача: написать программу, которая просто выводит число, которое увеличивается каждый раз, когда оно запускается, но (часть, из-за которой она была сложной), ей не разрешалось использовать какие-либо внешние файлы или другое хранилище для выполнения задания. Чтобы это не стало слишком скучным, это было также полем для кодового гольфа, хотя измеренный размер был исполняемым байтом, а не исходным кодом. Довольно много записей в этой проблеме использовали самомодифицирующийся код, который сильно зависел от того, как были закодированы инструкции и т.д.
Ищем секунду, я вижу, у меня все еще есть исходный код для одной из моих попыток:
.model tiny,c
.286
.code
.startup
main proc
mov si,offset count
inc byte ptr [si]
mov al, [si]
mov bx,4090h
shr al, 4
call convert
lodsb
and al,0fh
mov byte ptr end_convert, 08bh
convert:
add al,bl
daa
adc al,bh
daa
int 29h
end_convert:
ret
db 0d6h
; mov dx, si
mov ah,3ch
xor cx, cx
int 21h
xchg bx, ax
mov dx,offset main
mov cx,offset the_end - offset main
int 21h
ret
main endp
count:
db 0
name:
db 'c.com', 0
the_end:
end
Мне лучше уйти сейчас, прежде чем я буду отвечать за то, что у кого-то есть апоплексические припадки (надеюсь, что я не слишком поздно...)
Ответ 13
Раньше не редкость переходить от двоичного к ассемблеру, чтобы понять дамп.
Но не использовать ассемблер? Я не могу думать ни о какой причине. Ассемблер уже программирует голый металл. Преимущество заключается в том, чтобы использовать ярлыки, такие как "добавить" для фактической (двоичной) инструкции. и др.
Ответ 14
Ну, вы можете использовать hex для программирования некоторых базовых инструкций загрузки в ОЗУ или ПЗУ вместо использования ассемблера, если бы вы были разработчиком чипов. Я сделал это для softcore, который я написал.
Реально, после того, как вы это сделали, следующим шагом будет написать базовый ассемблер в Perl или что-то еще.
Ответ 15
Если вы создаете интерпретатор. Возможно, у вас есть переводчик, но не парсер. Вы можете проверить интерпретатор, написав программу, которая будет интерпретироваться в чистом двоичном формате.
Ответ 16
Обильный ритуал для нового члена команды.
Ответ 17
Действительно классный пример - это знаменитый полиглот, который является действительным файлом DOS.COM, среди прочего, потому что ASCII в его исходном коде удваивается как двоичные инструкции x86! http://ideology.com.au/polyglot/polyglot.txt
Более скучные примеры...
Многие процессоры реализуют инструкции ISA как последовательности более примитивных микроинструментов (в основном сборники сигналов управления данными), которые являются "микрокодированными" в ПЗУ микрокода.
Для достаточно простого процессора вы можете писать микрокод непосредственно в двоичном формате, а не собирать его с мнемонического языка. Или, если вы обратное проектирование процессора, вы можете не знать его набор микро-инструкций и просто должны угадать формат микро-инструкций... в этом случае вы, вероятно, также работаете в двоичном формате. В любом случае это более низкий уровень, чем язык ассемблера.
Иногда код для старых процессоров, таких как 6502, использовал недокументированные инструкции, которые не имели официальной мнемоники, поэтому вам приходилось писать двоичные значения, а не инструкции по сборке.
Ответ 18
Для проекта колледжа мне пришлось разработать упрощенный микроконтроллер в VHDL (язык описания аппаратного обеспечения). Чтобы проверить его, я написал очень простую программу в двоичном формате, потому что это был самый удобный способ передачи программы в моделируемый микроконтроллер.