2012-12-14 13 views
6

मुझे कोई समस्या है। मेरे पास निम्नलिखित x86 डेल्फी कोड है जो एएसएम में लिखा गया है। मुझे इसे AMD64 पर पोर्ट करने की आवश्यकता है?पोर्टिंग असेंबलर x86 सीपीयू आईडी कोड AMD64

type 
TCPUID = array[1..4] of Longint; 

function GetCID : TCPUID; assembler; register; 
asm 
    push ebx 
    push edi 
    mov edi, eax 
    mov eax, 1 
    dw $A20F 
    stosd 
    mov eax, ebx 
    stosd 
    mov eax, ecx 
    stosd 
    mov eax, edx 
    stosd 
    pop edi 
    pop ebx 
end; 

मैंने कभी भी असेंबली में प्रोग्राम नहीं किया है, क्या किसी को पता है कि बंदरगाह क्या होगा या मैं इसे बदलने के बारे में कैसे जाऊंगा।

+0

प्रश्न क्या है? भाषा के लिए आपको इसे बंद करने की आवश्यकता है? –

+0

@ Fermat2357 डेल्फी x64 asm –

+4

यह एक अच्छा सवाल IMHO है। यह "बहुत स्थानीय" नहीं है। मौजूदा कोड को बनाए रखते समय अन्य डेल्फी उपयोगकर्ताओं को एक ही समस्या का सामना करना पड़ सकता है। –

उत्तर

10

की तरह होना चाहिए मैं Win64 कोडांतरक गुरु नहीं हूँ, लेकिन अगले अनुवाद मुझे (64-बिट मुक्त पास्कल पर परीक्षण) के लिए काम किया:

program project1; 

{$mode delphi} 
{$asmmode intel} 

type 
TCPUID = array[1..4] of Longint; 

function GetCID: TCPUID; 
asm 
    push rbx 
    push rdi 
    mov rdi, rcx 
    mov eax, 1 
    cpuid 
    mov [rdi],eax 
    add rdi,4 
    mov [rdi],ebx 
    add rdi,4 
    mov [rdi],ecx 
    add rdi,4 
    mov [rdi],edx 
    pop rdi 
    pop rbx 
end; 

var ID: TCPUID; 

begin 
    ID:= GetCID; 
    Writeln(ID[1], '-', ID[2], '-', ID[3], '-', ID[4]); 
    Readln; 
end. 
+0

धन्यवाद! यह कोड ठीक काम करता है – Maxim

+1

बीटीडब्ल्यू: $ मोड डेल्फी लगभग 1.9.8 या 1.9.10 के बाद से $ asmmode इंटेल का तात्पर्य है –

-1

मैंने कभी भी CPUID के साथ काम नहीं किया है, इसलिए मुझे यह नहीं पता कि यह क्या करता है। लेकिन सामान्य ज्ञान और विकिपीडिया से (यदि उन स्रोतों पर्याप्त होगा) मेरी सलाह कर रहे हैं:

कोशिश
1) को हटाने के लिए "कोडांतरक," कीवर्ड - अप्रचलित
1.1) वैकल्पिक रूप से "रजिस्टर" हटाएं; - यह डिफ़ॉल्ट रूप से है और नो-पैरामीटर फ़ंक्शन के लिए बहुत कम मूल्य है। विकिपीडिया भी बताता है कि Win64 में इसका कोई प्रभाव नहीं है।

2) यदि संभव हो तो इसे procedure GetCID (out data: TCPUID); के रूप में दोहराएं। यदि फ़ंक्शन की आवश्यकता है - तो मैंने पास्कल में inline रैपर बनाया - बस परिभाषा को सरल और स्पष्ट रखने के लिए। यह लेखक के लिए एक अच्छी सलाह है - स्वचालित चीजों को सरल रखने और पास्कल को सिंटैक्स-चीनी स्वचालन छोड़ने के लिए, खासकर जब आपके पास कोई अनुभव नहीं है और कोई आसान चाल आपको भ्रमित नहीं कर सकती है और आपको टूटी हुई कोड टाइप कर सकती है। केआईएसएस सिद्धांत।

3) पुश ईबीएक्स/पॉप ईबीएक्स
3.1) मुझे लगता है कि पुश एडी/पॉपएडी को भी हटाया जाना चाहिए। लेकिन सुरक्षित पक्ष पर होना करने के लिए - मैं push rdi और pop rdi

लेख नहीं बताता है कि कुछ रजिस्टरों को बचाया या संरक्षित किया जाना चाहिए करने के लिए उन्हें बदल था: http://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions
न ही है कि आवश्यकता http://docwiki.embarcadero.com/RADStudio/XE3/en/Assembly_Procedures_and_Functions

4 में बताया जाता है) mov edi, eax ->mov rdi, rcx
4.1) आप अतिरिक्त सुरक्षा उपाय के रूप में इसके बाद cld कमांड जोड़ सकते हैं। लेकिन यह अति सतर्क और अनावश्यक होना चाहिए।

बाकी ही ऐसा लगता है के रूप में 64 86 मोड के रूप में CPUID के लिए एक ही सम्मेलन है होना चाहिए - http://en.wikipedia.org/wiki/CPUID#EAX.3D1:_Processor_Info_and_Feature_Bits

पर 64 मोड nof कोई mentio यह कुल मिलाकर यह

type 
TCPUID = packed array[1..4] of INT32; 

function GetCID : TCPUID; inline; 
begin 
    GetCID_Implementation(Result); 
end; 

procedure GetCID_Implementation (out buffer: TCPUID); 
asm 
    mov rdi, rcx // mov edi, eax 
    // RCX/EAX is Delphi/Windows pointer to 1st parameter 
    // RDI/EDI is CPU pointer to output buffer 

// cld - optionally, should not be needed 
// state of cld should be preserved by all other functions 

    xor eax, eax // shorter way for eax := 1 
    inc eax 

    dw $A20F  // call CPUID(eax==1), 
// output (according to wikipedia) is in eax,edx,ecx,ebx 32-bit registers 

    stosd   // *((INT32*)RDI)++ := eax 
    mov eax, ebx // xchg eax, ebx would be shorter,on that 
    stosd 
    mov eax, ecx // but Delphi XE2 is broken with xchg eax 
    stosd 
    mov eax, edx 
    stosd 
end; 
6

यहाँ दोनों x86 और x64 के लिए, मेरे संस्करण है:

function GetCPUID: TCPUID; 
asm 
{$IF Defined(CPUX86)} 
    push ebx 
    push edi 
    mov edi, eax 
    mov eax, 1 
    xor ecx,ecx 
    cpuid 
    mov [edi+$0], eax 
    mov [edi+$4], ebx 
    mov [edi+$8], ecx 
    mov [edi+$c], edx 
    pop edi 
    pop ebx 
{$ELSEIF Defined(CPUX64)} 
    mov r8, rbx 
    mov r9, rcx 
    mov eax, 1 
    cpuid 
    mov [r9+$0], eax 
    mov [r9+$4], ebx 
    mov [r9+$8], ecx 
    mov [r9+$c], edx 
    mov rbx, r8 
{$IFEND} 
end; 

x64 के बारे में अच्छी चीजों में से एक यह है कि बहुत सारे रजिस्ट्रार उपलब्ध हैं, जिनमें से कई अस्थिर हैं। तो हम उस स्क्रैच स्पेस का उपयोग कर सकते हैं और मुख्य मेमोरी को छूने से बच सकते हैं। जाहिर है, हमें परिणाम वापस करने के लिए मुख्य स्मृति को छूना है।

RBX is nonvolatile से हम इसके मूल्य को संरक्षित करते हैं। हमारे द्वारा संशोधित अन्य सभी रजिस्ट्रार अस्थिर हैं और इसलिए हमें उन्हें संरक्षित करने की आवश्यकता नहीं है। मैं इसे और सरल बनाने के किसी भी तरीके से नहीं सोच सकता।

यह आसानी से एक तर्क के रूप प्रदान किया जाने वाला CPUID के लिए इनपुट अनुमति देने के लिए बढ़ाया जा सकता है:

function GetCPUID(ID: Integer): TCPUID; 
asm 
{$IF Defined(CPUX86)} 
    push ebx 
    push edi 
    mov edi, edx 
    xor ecx,ecx 
    cpuid 
    mov [edi+$0], eax 
    mov [edi+$4], ebx 
    mov [edi+$8], ecx 
    mov [edi+$c], edx 
    pop edi 
    pop ebx 
{$ELSEIF Defined(CPUX64)} 
    mov r8, rbx 
    mov r9, rcx 
    mov eax, edx 
    cpuid 
    mov [r9+$0], eax 
    mov [r9+$4], ebx 
    mov [r9+$8], ecx 
    mov [r9+$c], edx 
    mov rbx, r8 
{$ELSE} 
    {$Message Fatal 'GetCPUID has not been implemented for this architecture.'} 
{$IFEND} 
end; 

यह 0 की एक उप-पत्ती मूल्य, ECX में पारित मान लिया गया है। दोबारा, यदि आप इसे पास करना चाहते हैं, तो यह काफी आसान है:

function GetCPUID(Leaf, Subleaf: Integer): TCPUID; 
asm 
{$IF Defined(CPUX86)} 
    push ebx 
    push edi 
    mov edi, ecx 
    mov ecx, edx 
    cpuid 
    mov [edi+$0], eax 
    mov [edi+$4], ebx 
    mov [edi+$8], ecx 
    mov [edi+$c], edx 
    pop edi 
    pop ebx 
{$ELSEIF Defined(CPUX64)} 
    mov r9,rcx 
    mov ecx,r8d 
    mov r8,rbx 
    mov eax,edx 
    cpuid 
    mov [r9+$0], eax 
    mov [r9+$4], ebx 
    mov [r9+$8], ecx 
    mov [r9+$c], edx 
    mov rbx, r8 
{$ELSE} 
    {$Message Fatal 'GetCPUID has not been implemented for this architecture.'} 
{$IFEND} 
end; 
संबंधित मुद्दे