сборка x86 rcl al, 1 не очищает флаг переноса, когда al равно нулю - PullRequest
1 голос
/ 01 октября 2019

Заголовок суммирует его.

Если флаг переноса был установлен ранее, когда инструкция rcl вызывается, а al равен нулю, то старший бит (0) не переносится в перенос.

Следующие коды демонстрируют:

mov al,0
stc
setc byte ptr [before]
rcl al,1 ; rotate left one bit through carry flag (multiply by 2 once)
setc byte ptr [after]

Таким образом, вывод:

before = 01
after = 01

Флаг переноса не очищен, как ожидалось. Читая руководство Intel:

The shift arithmetic left (SAL) and shift logical left (SHL) instructions perform the same operation; they shift the
bits in the destination operand to the left (toward more significant bit locations). For each shift count, the most
significant bit of the destination operand is shifted into the CF flag, and the least significant bit is cleared (see
Figure 7-7 in the Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1).

Мне кажется, что если исходное значение равно нулю, то ничего не делается, и это не правильно!

1 Ответ

0 голосов
/ 03 октября 2019

Очевидной причиной моих проблем (а их было три) было то, что оптимизатор C вырезал код, потому что не знал, что код сборки оказал какое-либо влияние на определенные переменные.

(Мои примеры кода относятся кЭмулятор процессора 6809/6309)

Я кратко изложу три вопроса.

  1. Кажется, что инструкция по сборке rcl НЕ устанавливает флаг переноса.

    (Задокументировано в этом посте)

  2. Код сборки будет работать в 100-1000 раз медленнее, когда код C был скомпилирован с оптимизацией.

    (Пример невозможен)

  3. Для того, чтобы код вообще работал, необходимо замаскировать определенный код.

Следующий код:

static void(*JmpVec1[256])(void) = { ... };
...
unsigned char memByte = MemRead8(PC_REG++);
JmpVec1[memByte](); // Execute instruction pointed to by byte @ PC_REG
CycleCounter += instcycl1[memByte]; // Add instruction cycles

Будет работать только в том случае, если будет использован следующий код:

static void(*JmpVec1[256])(void) = { ... };
...
unsigned char memByte = MemRead8(PC_REG++);
if (memByte == 0x34) // Just doesn't like instruction 0x34 Pushs register_list
{
    JmpVec1[memByte](); // Execute instruction pointed to by PC_REG
}
else
{
    JmpVec1[memByte](); // Execute instruction pointed to by PC_REG
}
CycleCounter += instcycl1[memByte]; // Add instruction cycles

Поскольку код C не имеет представления о том, что выполняет какая-либо из эмулированных инструкций 437 или какие последствия имеют эти инструкции, почему он выбрал инструкцию 0x34, чтобы прекратить работузагадка.

Что решило проблему и позволило мне удалить обфусцированный код и позволило снова включить оптимизацию C, сделало переменную CycleCounter (int) volatile.

Исправлены все мои проблемы !!!

Эта проблема была еще более усугублена, поскольку в vscode нет поддержки разборки, что делает отладку процедур сборки чрезвычайно трудной.

Если кто-то использует хорошую IDE C / Assembly в Linux, оставьте комментарий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...