Вопрос

Я написал функцию ASM в Delphi 7, но это преобразует мой код на что-то еще:

function f(x: Cardinal): Cardinal; register;
label err;
asm
  not eax
  mov edx,eax
  shr edx, 1
  and eax, edx
  bsf ecx, eax
  jz  err
  mov eax, 1
  shl eax, cl
  mov edx, eax
  add edx, edx
  or  eax, edx
  ret
  err:
  xor eax, eax
end;

// compiled version
f:
  push ebx       // !!!
  not eax
  mov edx,eax
  shr edx, 1
  and eax, edx
  bsf ecx, eax
  jz  +$0e
  mov eax, 1
  shl eax, cl
  mov edx, eax
  add edx, edx
  or  eax, edx
  ret
  err:
  xor eax, eax
  mov eax, ebx   // !!!
  pop ebx        // !!!
  ret

// the almost equivalent without asm
function f(x: Cardinal): Cardinal;
var
  c: Cardinal;
begin
  x := not x;
  x := x and x shr 1;
  if x <> 0 then
  begin
    c := bsf(x); // bitscanforward
    x := 1 shl c;
    Result := x or (x shl 1)
  end
  else
    Result := 0;
end;

Почему это генерирует push ebx а также pop ebx? И почему это делает mov eax, ebx?

Похоже, что он генерирует часть частичной стеки из-за mov eax, ebx.

Этот простой тест генерирует mov eax, edx Но не генерирует этот стек кадра:

function asmtest(x: Cardinal): Cardinal; register;
label err;
asm
  not eax
  and eax, 1
  jz  err
  ret
  err:
  xor eax, eax
end;

// compiled
asmtest:
  not eax
  and eax, $01
  jz +$01
  ret
  xor eax, eax
  mov eax, edx  // !!!
  ret

Кажется, что это есть что делать с label err. Отказ Если я удалю, что я не получаю mov eax, * часть.

Почему это происходит?


Сделал сообщение об ошибке на Качество центральное.

Это было полезно?

Решение

Практический совет: не используйте ключевое слово метки в коде ASM, используйте @@ - префиксные этикетки:

function f(x: Cardinal): Cardinal; register;
asm
  not eax
  mov edx,eax
  shr edx, 1
  and eax, edx
  bsf ecx, eax
  jz  @@err
  mov eax, 1
  shl eax, cl
  mov edx, eax
  add edx, edx
  or  eax, edx
  ret
@@err:
  xor eax, eax
end;

Обновленный:

Я не нашел отчет об ошибках в Басменская область. Отказ Это похоже на ошибку, но я уже много лет использовал басмен и никогда не думал использовать такое ключевое слово этикетки. На самом деле я никогда не использовал ключевое слово Label в Delphi. :)

Другие советы

Ну ... Вернитесь тогда, в Delphi-Manual, он использовал что-то о компиляторе-оптимизации и Thealike-Crazyness:


Компилятор генерирует штаб-кадры только для вложенных процедур, для процедур, имеющих локальные переменные и для подпрограмм со стеком-параметрами.

Автоматическая сгенерированная инициализация и финаризацияCode для процедуры включает в себя:

PUSH    EBP              ; If Locals <> 0 or Params <> 0
MOV     EBP,ESP          ; If Locals <> 0 or Params <> 0
SUB     ESP,Locals       ; If Locals <> 0
    ...
MOV     ESP,EBP          ; If Locals <> 0
POP     EBP              ; If Locals <> 0 or Params <> 0
RET     Params           ; Always

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

Locals - это размер локальных переменных, параметры размером параметров. Если оба местных жителя, а также на словах NULL не будут сгенерированы INIT-код, и финарирующий код содержит только вторжение.


Может быть, что есть что-то делать с ним все ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top