Application & Screen 這二個"全域變數"似乎是物件的指標 ( 积分: 100 )

  • 主题发起人 主题发起人 turbo5010
  • 开始时间 开始时间
T

turbo5010

Unregistered / Unconfirmed
GUEST, unregistred user!
如果查看Delphi編輯的組合語言畫面,會發現提取 Application &amp
Screen 這二個變數的指令和自訂變數的指令不一樣,提取Application和Seceen這二個變數必須多一次間接定址.
Object Pascal :
Application.Title := 'Test!!!!!';

Assembly :
mov eax,[$00461f90]
間接定址
mov eax,[eax]
比一般的物件參考多了這個步驟
mov edx,$0045fedc
直接定址,指向常數 'Test!!!!!'
call TApplication.SetTitle

一般的物件參考其組合語言如下:
Object Pascal :
Form1.Caption := 'Test!!!!!';

Assevbly :
mov edx,$0045fedc ;直接定址,指向常數 'Test!!!!!'
mov eax,[Form1] ;取得Form1物件址址
call TControl.SetText

一般都知道Delphi的物件變數其實是物件指標,但Application和Screen卻是物件指標的指標,查過Controls.pas 的 procedure InitControls
Application 和 Screen這二個物件的建構和一般的物件建構並沒什麼不同,但Delphi卻如此儲存Application和Screen. 由它們的組合語言看來,這二個變數是物件指標的指標,但我們在程式中卻可把它們當成一般的物件來使用,Delphi卻會幫我們自動轉換.難道這又是Delphi的 [Compile Magic];

問題:
1.為什麼這二個變數是這麼的不一樣? 還是我自己弄錯了.
 
如果查看Delphi編輯的組合語言畫面,會發現提取 Application &amp
Screen 這二個變數的指令和自訂變數的指令不一樣,提取Application和Seceen這二個變數必須多一次間接定址.
Object Pascal :
Application.Title := 'Test!!!!!';

Assembly :
mov eax,[$00461f90]
間接定址
mov eax,[eax]
比一般的物件參考多了這個步驟
mov edx,$0045fedc
直接定址,指向常數 'Test!!!!!'
call TApplication.SetTitle

一般的物件參考其組合語言如下:
Object Pascal :
Form1.Caption := 'Test!!!!!';

Assevbly :
mov edx,$0045fedc ;直接定址,指向常數 'Test!!!!!'
mov eax,[Form1] ;取得Form1物件址址
call TControl.SetText

一般都知道Delphi的物件變數其實是物件指標,但Application和Screen卻是物件指標的指標,查過Controls.pas 的 procedure InitControls
Application 和 Screen這二個物件的建構和一般的物件建構並沒什麼不同,但Delphi卻如此儲存Application和Screen. 由它們的組合語言看來,這二個變數是物件指標的指標,但我們在程式中卻可把它們當成一般的物件來使用,Delphi卻會幫我們自動轉換.難道這又是Delphi的 [Compile Magic];

問題:
1.為什麼這二個變數是這麼的不一樣? 還是我自己弄錯了.
 
不是什么[Compile Magic];
mov eax,[eax] ;
这一步是必须的,

mov eax,[Form1] 等价于
mov eax Form1;
mov eax [eax];
 
mov eax,[Form1]
絶不等於
mov eax Form1;
mov eax [eax]

可以看 Hex Code 得知.

您可自訂兩個變數 myApplication 和 myScreen
var myApplication : Tapplication;
myScreen : TScreen;
再觀察這存取這兩變數的 匯編, 在提取這兩變數時, 絶不用經兩次的 Mov 指令.
只要一次的 Mov 指令即可達成, 就只有 Application 和 Screen 這兩個系統全域變數需經兩次的 mov 才能提取.
 
应该是与单元引用有关的,毕竟在编译器编译的时候,不同的单元之间的引用(特别是不同单元中全局变量的引用),编译器会插入一个临时的变量,如果你在Form1单元中引用Form2全局变量(假设你的工程包含Form1和Form2两个窗体单元),你在form1单元的一个事件中写这样的代码:
Unit2.Form2.Caption:='Hello';
你会看到类似的汇编代码。
不知道这样解释你满意否??!!
给分了^_^
而你的那段代码实际上是引用Forms单元的Application对象的,与上面是一样的道理!
Forms.Application.Title:='';
 
kkkchenA 謝謝你,果如你所說,是不同 Unit才會如此.
 
后退
顶部