Сборка 8086, почему более поздняя инструкция не изменяет предыдущую после выполнения - PullRequest
0 голосов
/ 08 ноября 2018

Я новичок в ассемблере и пытаюсь выяснить этот код:

072A:100 mov word ptr [0107], 4567
072A:106 mov ax, 1234
072A:109 add ax, dx

Я понимаю, что первая инструкция помещает два байта со значениями 67 45 по адресу 072A:107. В итоге AX = 4567.

Я не понимаю, почему более новая инструкция mov ax, 1234 не меняет значение по адресу 072A: 107 предыдущей инструкции mov word ptr [0107], почему дамп не изменился?.

Заранее спасибо.

1 Ответ

0 голосов
/ 08 ноября 2018

Когда вы смотрите на эту разборку (перед выполнением первой инструкции), память уже загружена машинным кодом (я предполагаю, что это файл DOS COM, поэтому cs=ds=ss=0x72A и первый mov будут самостоятельно изменить второй mov).

Итак, содержимое памяти уже (средняя часть - это байты машинного кода в шестнадцатеричном формате):

072A:100 C70607016745   (mov word ptr [0107], 4567) <- cs:ip points here
072A:106 B83412         (mov ax, 1234)
072A:109 01D0           (add ax, dx)

После выполнения первой инструкции (C7 06 07 01 67 45 - ЦП считывает 6 байтов и декодирует как инструкция mov [..],..), содержимое памяти изменится на:

072A:100 C70607016745   (mov word ptr [0107], 4567)
072A:106 B86745         (mov ax, 4567)  <- cs:ip points here
072A:109 01D0           (add ax, dx)

Если вы сейчас разберете машинный код, вы увидите вторую инструкцию как "mov ax, 4567" уже ... ЦП не знает, что исходный код сказал mov ax, 1234 и как вы можете видеть из машинный код в памяти, восстановить его невозможно, в памяти нет значения 1234h.

Также, когда вы перезагружаете код из исполняемого файла, он снова будет mov ax, 1234, потому что это то, что хранится в двоичном файле после этапа сборки перед его выполнением.

Машинный код не создается во время выполнения из исходного кода, ассемблер производит двоичный машинный код во время сборки, поэтому нет ничего, что бы «восстанавливало» эту вторую инструкцию до mov ax,1234 (источник и ассемблер не имеют отношения во время выполнения) .

Если это будет какой-то интерпретируемый язык, подготавливающий каждую инструкцию непосредственно перед выполнением, собирающий из источника, то первая инструкция должна будет модифицировать источник, чтобы вызвать самомодификацию во «время интерпретации», но большинство интерпретаторов не позволяйте никакого простого способа изменить интерпретируемый в настоящее время источник.

И даже игрушечные / симуляторы, предназначенные для обучения сборке (MARS / SPIM, или 8-битный симулятор ассемблера ), работают во время выполнения с двоичным машинным кодом, а не с исходным кодом (хотя они могут или может не позволить самомодификации распространяться на симуляцию, некоторые симуляторы могут игнорировать ее и защищать оригинальный машинный код от модификации по каким-либо странным причинам).

предупреждение для новичков в сборке: хотя самодоминация кода поначалу может показаться крутой (по крайней мере, для меня), это настоятельно не рекомендуется: 1) вы не можете использовать его по умолчанию в современных SW (если вы не используете довольно много) длины, чтобы включить его) 2) это сильно ухудшает производительность современных процессоров, потому что, когда современный процессор x86 обнаруживает запись на 107h, он уже извлек + декодировал + спекулятивно выполнил несколько инструкций вниз по линии, поэтому он должен выбросить все это " Будущее "превратится в мусорное ведро, очистит внутренние кэши и начнёт заново, что означает, что команда типа mov ax,1234, которая могла быть выполнена за один цикл или даже вместе с какой-то другой инструкцией, может вместо этого занять более 100 циклов. 3) это позволяет трудно находить ошибки, если вы недостаточно опытны, чтобы угадать все последствия такого кода.

Так что важно понять концепцию и то, что происходит, но не используйте ее, если вы не занимаетесь чем-то дополнительным / специализированным, например, 256B вступлением, и это экономит вам два байта, тогда это действительно.

...