2010-03-07 62 views
5

我寫的彙編函數在Delphi 7,但其轉換我的代碼到別的東西:Delphi標籤和asm怪異?

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 ebxpop 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, *部分。

爲什麼會發生這種情況?


發出了一個關於Quality Central的錯誤報告。

+0

請報告此作爲http://qc.embarcadero.com/wc/qcmain.aspx – 2010-03-08 00:02:57

+0

@Jeroen一定的錯誤。沒有問題... – Egon 2010-03-08 07:55:16

+0

您在這裏問了幾個「爲什麼」的問題,但沒有人回答您接受的答覆。看起來你真的只是想知道如何跳到Delphi彙編器中的新指令,而不考慮你自己嘗試失敗的原因。這是否準確? – 2010-03-08 09:01:08

回答

7

實際的建議是:不要使用標籤關鍵詞的彙編代碼,使用@@ - 前綴標籤:

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; 

更新

我還沒有發現的bug報告在Basm area。它看起來像一個錯誤,但我已經使用BASM很多年了,從來沒有想過如何使用標籤關鍵字。事實上,我從來沒有在Delphi中使用過標籤關鍵字。 :)

+0

哇,修復了它... – 2010-03-07 09:36:11

+0

任何想法爲什麼'label'生成'mov eax,*'thingy ...這是一個錯誤嗎?或者只是一些奇怪的行爲? – Egon 2010-03-07 09:38:57

+0

而不是@@ MyLabel,同樣@MyLabel(帶有一個「@」)在asm..end塊中沒有問題。 – PhiS 2010-03-08 07:30:49

1

嗯......那時,德爾福手冊中,它曾經談談編譯器優化和thealike-crazyness:


,編譯器僅用於嵌套例程產生Stackframes,爲有局部變量和例程與棧參數的例程

自動生成Initialization-和Finalizationcode的例程包括:

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,但不會在事後完成。

當地人是局部變量的大小,參數大小參數。如果Local和Params都是Null,則不會生成Init-Code,Finalizationcode只包含RET-Intruction。


也許已經得到的東西,用它做一切......