Вы немного наивно ожидаете, что это за строка.
msg: db "Hello, World!", 0
Она собирается в машинный код как 14 байтов (каждый символ в кодировке ASCII равен одному байту (существуют разные кодировки с разными характеристиками, ноemu8086 основан на ASCII) и еще один для конечного нуля.
a: db 0
Он собран как один байт нулевого значения.
Затем ваш код запускается и внутри _make_str
он будетскопируйте 14 байтов с адреса msg
по адресу a
. Но адрес a+1
равен start
, поэтому 13 символов перезаписывают ваш машинный код для самого кода, переходя через call _make_str
и следуя mov a,di
. Затем в ret
код возвращается по адресу, где должен был быть mov a,di
, но в строке уже есть байт 64
, поэтому сообщается неизвестный код операции.
Встроенный emu8086-в отладчике, так что используйте пошаговые инструкции и представление памяти, чтобы увидеть, как скомпилированы строки и что делает ваш код.
И в задницеВ embler переменных нет, эти имена перед db/dw/dd/...
являются «символами», и они похожи на закладки в памяти компьютера, содержащие адрес первого байта этого значения.
Если вам нужно 20 байтовпамять для строк длиной не более 19 символов, затем вам нужно выделить / зарезервировать 20 байт памяти, память не будет автоматически увеличиваться или перенаправить содержимое, чтобы освободить место для неожиданных данных.
Что, если я не знаю, какой длины может быть строка, как мне инициализировать переменную переменной длины?
Вы не используете данные неизвестной длины.Либо вы знаете, какой длины могут быть данные, либо вы должны указать максимум (у языков высокого уровня тоже есть ограничения, если вы будете достаточно настойчивы, вы легко нарушите понятие «неограниченности»).
В зависимости от того, какого типа этот максимум, подход может отличаться.
Например, если вы читаете имя пользователя, вы можете сказать, что максимум составляет 80 байтов, и резервируйте 80 байтов в области данных, и этонапример, пользователь с более длинным именем либо вылетит из вашего приложения, либо, если вы правильно его кодировали, он сможет ввести только 79 или 80 символов (в зависимости от того, нужен ли вам нулевой терминатор или нет, внутри массива из 80 байтов).
Если вы читаете небольшой текст, такой как описание предмета магазина, вы точно не знаете максимум, но вы уверены, что он либо в пределах тысяч, либо что-то ужасно неправильно, тогда вы можете динамически резервировать место в стеке, напримерsub sp,<length_of_text>
и сохраните текст в области стека.
Если вы читаете длинные данные, как двоичный редактор 2 + GВ файлах B у вас должен быть какой-то массив, описывающий, какие куски файла у вас в данный момент находятся в памяти, и динамически меняются и выгружаются, используя всю доступную память, которую ОС предлагает в качестве кеша («выделение памяти»), но еслиЕсли у вас закончилась куча, современная ОС увеличит ее за счет использования виртуальной памяти, хранящейся на диске (swap).Но все же лучше избегать таких ситуаций за счет лучшего алгоритма и дизайна приложения.
Также в emu8086 применяются все другие ограничения 16-битного реального режима x86, т.е. в вашем примере, подобном COM, весь ваш код + данные + стекдолжен вписываться в один сегмент размером 64 КБ (начиная со смещения 0x100, даже не полностью 64 КБ), если только ваш код не проверит DOS на наличие дополнительных доступных сегментов и не использует их больше (после загрузки файла COM в обычном DOS в качестве первого приложения, которое вы обычно500–580 КБ свободной памяти после вашего текущего сегмента).
Жить в 16-битном мире и спрашивать о «не знаю размера» - это дополнительная боль, в 16-битном мире вы должны были знать размеры впереди,и планируйте их, иначе вы очень быстро столкнетесь с проблемами.
РЕДАКТИРОВАТЬ: на самом деле ... вы, вероятно, сталкиваетесь с другой ошибкой, или трудно сказать, какая из них.
mov si,msg
mov di, a
Эти наборы si
и di
регистрируются с двухбайтовыми (16-битными) значениями из памяти по адресам msg
и a
.Это синтаксис MASM, где для доступа к памяти не требуется []
.
Чтобы получить адрес первого байта, вам нужно mov si, OFFSET msg
или lea si,[msg]
... так что теперь я даже не уверен, какую память и где вы перезаписываете, так как вы используете данные символов в качестве указателя памяти, но, очевидно, вы перезаписываетечто-то жизненно важное.
Используйте отладчик emu8086, чтобы увидеть, что именно происходит.
(после того, как вы исправите свой код для правильной загрузки адресов, вы нажмете на перезапись кода, как я его описал)в ответ)