我有一個 Delphi Firemonkey EXIF 實作,我在例程中使用它來加載影像檔案。我正在嘗試確定影像是否已旋轉,因此我可以在顯示影像之前更正影像的方向。該例程部分呼叫匯編代碼,該代碼執行 BSWAP 以確定影像檔案中的頭資訊所在的位置。這是代碼的一部分:
type
TMarker = packed record
Marker : Word; //Section marker
Len : Word; //Length Section
Indefin : Array [0..4] of Char; //Indefiner - "Exif" 00, "JFIF" 00 and ets
Pad : Char; //0x00
end;
TIFDHeader = packed record
pad : Byte; //00h
ByteOrder : Word; //II (4D4D) or MM
i42 : Word; //2A00 (magic number from the 'Hitchhikers Guide'
Offset : Cardinal; //0th offset IFD
Count : Word; // number of IFD entries
end;
function SwapLong(Value: Cardinal): Cardinal;
asm bswap eax end;
procedure TExif.ReadFromFile(const FileName: string);
var
j: TMarker;
ifd: TIFDHeader;
off0: Cardinal; //Null Exif Offset
SOI: Word; //2 bytes SOI marker. FF D8 (Start Of Image)
f: File;
begin
if not FileExists(FileName) then exit;
Init;
System.FileMode:=0; //Read Only open
AssignFile(f,FileName);
reset(f,1);
BlockRead(f,SOI,2);
if SOI=$D8FF then begin //Is this Jpeg
BlockRead(f,j,9);
if j.Marker=$E0FF then begin //JFIF Marker Found
Seek(f,20); //Skip JFIF Header
BlockRead(f,j,9);
end;
//Search Exif start marker;
if j.Marker<>$E1FF then begin
i:=0;
repeat
BlockRead(f,SOI,2); //Read bytes.
inc(i);
until (EOF(f) or (i>1000) or (SOI=$E1FF));
//If we find maker
if SOI=$E1FF then begin
Seek(f,FilePos(f)-2); //return Back on 2 bytes
BlockRead(f,j,9); //read Exif header
end;
end;
if j.Marker=$E1FF then begin //If we found Exif Section. j.Indefin='Exif'.
FValid:=True;
off0:=FilePos(f) 1; //0'th offset Exif header
BlockRead(f,ifd,11); //Read IDF Header
FSwap := ifd.ByteOrder=$4D4D; // II or MM - if MM we have to swap
if FSwap then begin
ifd.Offset := SwapLong(ifd.Offset);
ifd.Count := Swap(ifd.Count);
end;
if ifd.Offset <> 8 then begin
Seek(f, FilePos(f) abs(ifd.Offset)-8);
end;
當應用程式是為 32 位 Windows 構建時,這作業正常,但在 64 位 Windows 下的 SwapLong 呼叫失敗。我不知道關于匯編語言的第一件事,所以我正在尋找如何在構建 64 位版本的程式時處理相同的功能。請注意,在兩個版本中,傳遞給 SwapLong 函式的 idf.OffSet 值都是 134217728(80000000 美元)。在 32 位版本中,SwapLong 回傳值 8,但 64 位版本回傳值 2694969615,因為輸入似乎相同。
我需要 64 位版本才能作業,因為我希望使用相同的代碼定位 64 位 MAC OSX。任何幫助將不勝感激。
uj5u.com熱心網友回復:
問題存在是因為行內程式集假定第一個引數以及回傳值使用 register eax,這對于 32 位模式下的 Delphi 是正確的(盡管沒有記錄或保證)。
但是,64 位模式使用不同的呼叫約定,其中第一個引數在rcx,回傳值使用rax. 所以在這里你得到隨機未初始化的垃圾作為回傳值,它恰好在那個暫存器中(交換了它的位元組),因為它從未明確設定。
最好的、可移植的解決方案是在沒有行內匯編的純 Delphi 中實作位元組交換:
function SwapLong(Value: Cardinal): Cardinal;
begin
Result := Swap(Value shr 16) or (Cardinal(Swap(Value and $FFFF)) shl 16);
end;
這使用了幾十年前的Swap函式,該函式交換值的低 2 個位元組。這本身不再有多大用處,但可以使用兩次(連同一些位移和掩碼)來縮短交換 32 位值的所有 4 個位元組的代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/326204.html
標籤:德尔福 集会 x86-64 火猴 delphi-10.4-悉尼
上一篇:如何用zsh從命令列打開最近的SublimeText?
下一篇:如何在C#中呼叫x64匯編程式
