2016-12-17 45 views
-2

我最近開始學習從Windows移植到Linux。我一直在翻譯從英特爾語法的程序到AT & T語法也將它從x32轉換爲x64。而且,由於我足夠新的彙編程序,尤其是在移植時遇到了一些麻煩。只需提及:我故意不使用.intel_syntax指令。從Windows移植到Linux。彙編器命令翻譯

所以我就用stucked翻譯這些命令:

RTLWriteIntegerBuffer: TIMES 3 DB 0x90,0x8D,0x40,0x00 

依次爲:

LEA EDI,[OFFSET RTLWriteIntegerBuffer+ECX-1] 

還有一句:

LEA EBX,[EDX+'0'] 

還有一個:

ReadCharInited: DB 0 
CMP BYTE PTR ReadCharInited,0 

另一個問題是:AT & T語法與Intel語法之間是否存在1:1映射?或者是否存在AT & T不支持的特定英特爾命令?

也許有人知道這樣的功能:

HEAP_NO_SERIALIZE=1 
HEAP_GENERATE_EXCEPTIONS=4 
HEAP_ZERO_MEMORY=8 
... 
INVOKE HeapAlloc,EAX,HEAP_GENERATE_EXCEPTIONS+HEAP_ZERO_MEMORY+HEAP_CREATE_ALIGN_16,4194332 

這是一個很可能是Borland的Turbo彙編程序特定的方式來調用kernel32.dllHeapAlloc,但我不知道。 是否可以翻譯成fallocate系統調用?

在此先感謝

+0

您可以使用'.rept'或輸入它來代替'times'。對於其他人閱讀有關at&t內存參考語法。 'fallocate'與'HeapAlloc'完全不同。 – Jester

+0

你真的需要AT&T語法嗎?將氣體的'.intel_syntax noprefix'(與MASM非常相似)還是NASM語法不會更容易?那麼你只需要改變系統調用/ ABI,而不是每個指令。 (請參閱http://stackoverflow.com/tags/x86/info以獲取彙編程序手冊的鏈接) –

+2

手動設置錯誤非常容易,因此我建議使用MASM進行彙編,然後使用'objdump -drwC'進行反彙編,然後移植指令和意見反彙編。我認爲objdump可以選擇更接近爲彙編程序輸入做好準備,或者使用Agner Fog的objconv反彙編程序,它可以使輸出再次組裝。 –

回答

4

當談到「AT & T語法」與「Intel語法」時,它通常僅指代指令助記符與操作數排序和格式之間的差異。

因此,舉例來說,這是在& T語法的指令:

movl $1, (%esi) 

,這是使用Intel語法相同的指令:

mov DWORD PTR [esi], 1 

對於Intel語法的每一條指令表示的,該指令的AT & T語法中有相同的表示。

由於沒有AT & T彙編程序,並且不再有英特爾彙編程序,指令(除指令外的所有內容)都是另一回事。 GNU彙編器(GAS)支持T和Intel語法,但僅支持其自己的指令,它們是AT彙編程序使用的指令的擴展。微軟的MASM只支持英特爾語法,但也僅支持自己的指令,這是原英特爾彙編程序的擴展。從一個彙編指令到另一個彙編指令並不總是等價的。在某些情況下,他們使用不同的目標文件格式的事實可能會阻止在不同的彙編程序中使用不同的目標文件格式來實現指令功能的任何方式。 (甚至相同的彙編使用不同的格式,可以與GNU彙編程序的情況下)

作爲一個例子,這裏的一些GAS指令:

.rept 3 
.byte 0x90, 0x8D, 0x40, 0x00 
.endr 

這裏是相當於MASM指令:

REPT 3 
DB 90h, 8Dh, 40h, 00h 
ENDM 

但目前還沒有MASM相當於以下GAS指令,因爲它是專門針對ELF對象格式,MASM不支持:

.protected foo 

在另一方面沒有直接等同於以下MASM指令,因爲GAS不支持任何複雜的高級語言指令:

INVOKE HeapAlloc,EAX,HEAP_GENERATE_EXCEPTIONS+HEAP_ZERO_MEMORY+HEAP_CREATE_ALIGN_16,4194332 

要移植前ELF特定指令你必須重新設計應用程序以處理Windows如何處理共享庫。要移植後面的MASM專用指令,您必須創建自己的宏來完成確定如何正確傳遞所有參數的工作,或者只需手動輸出此次調用所需的所有彙編指令Linux x86-64 ABI。 (你還必須找到一個合適的Linux函數來調用並傳遞一組不同的參數,但這與翻譯指令本身是分開的。)

某些彙編器試圖與其他彙編器兼容;例如Borland的TASM試圖與MASM兼容,儘管它是MASM的老版本。因此,TASM(在其默認MASM模式下)的工作原理通常在MASM中工作,反之亦然。但是,許多彙編程序基本上都使用它們自己的x86彙編語言版本。

例如,您在帖子中顯示的代碼似乎使用兩種不同的彙編語言版本,不能由任何單個彙編程序彙編。您的第一行代碼使用TIMES指令,但此指令僅由NASM支持,它不使用AT語法,也不使用Intel語法。它有自己的指令語法,但它與英特爾語法沒有區別。它也有自己的不兼容的指令集,不是基於任何特定的指令,就像你展示的TIMES指令。

代碼的其餘部分顯示爲MASM語法。除第三行之外,它不會與NASM正確組裝(第一行也不會與MASM正確組裝)。我不知道是否會與TASM組裝,因爲在MASM 6中添加了INVOKE指令。

請注意,考慮到代碼的性質,用匯編語言編寫代碼可能沒有任何好處,您可能會最好將其轉換爲C,C++或其他您熟悉的語言。

+1

我想再次建議使用Linux系統調用的端口到C而不是AT&T x86-64 asm,然後再加上討論指令。 (我注意到TIMES vs. INVOKE的事情,但不確定TIMES只是NASM)。 –

2

我不是很熟悉Windows,但讓我儘量幫你啦。

RTLWriteIntegerBuffer: TIMES 3 DB 0x90,0x8D,0x40,0x00 

DB指令轉化爲.byte在UNIX彙編,TIMES氣體支持(如.rept),但我建議,以避免它,因爲它是無法移植到其他UNIX彙編。所以這個片段成爲

RTLWriteIntegerBuffer: 
    .byte 0x90,0x8d,0x40,0x00 
    .byte 0x90,0x8d,0x40,0x00 
    .byte 0x90,0x8d,0x40,0x00 
LEA EDI,[OFFSET RTLWriteIntegerBuffer+ECX-1] 

形式[disp+base+index*scale]的英特爾式的內存操作數成爲AT & T語法disp(base,index,scale)。如果indexscale都爲空,則可以改爲寫disp(base),否則只需省略缺失的寄存器(但保留逗號)。您的指令變爲

lea RTLWriteIntegerBuffer-1(%ecx),%edi 

請注意交換的操作數。在AT & T語法中,除一些浮點指令外,所有雙參數操作碼都交換了操作數。

LEA EBX,[EDX+'0'] 

類似地,這一個變成

lea '0'(%edx),%ebx 
ReadCharInited: DB 0 
CMP BYTE PTR ReadCharInited,0 

這一個變成

ReadCharInited: .byte 0 
    cmpb $0,ReadCharInited 

請注意後綴b,表示這是一個字節指令。其他後綴包括:w用於l四字(僅AMD64)雙字(長)和q。立即數以前綴$爲前綴,內存操作數前綴不加。

另一個問題是:AT & T語法與Intel語法之間是否存在1:1映射?或者是否有AT & T中不支持的特定英特爾命令?

有關說明,通常有。一種解決這個問題的方法是用英特爾語法編寫指令,然後將其轉儲爲AT & T語法(使用objdump -d),反之亦然(使用objdump -d -Mintel)。

對於僞指令(例如TIMESDB),由於UNIX彙編器在概念上不同於例如MASM。

INVOKE HeapAlloc,EAX,HEAP_GENERATE_EXCEPTIONS+HEAP_ZERO_MEMORY+HEAP_CREATE_ALIGN_16,4194332 

代替此功能,您可能希望只使用好老calloc從C標準庫。雖然沒有HeapDestroy或類似的,你需要的,如果你想要這個功能來寫自己的分配器

push $4194332 
push $1 
call calloc 
add $8,%esp 

注意:如果你打算對libc的鏈接像這樣的東西應該工作。

+1

在Windows中,'calloc'和'malloc'構建在HeapAlloc之上,而'free'構建在HeapFree之上,使用由C運行時庫管理的私有堆。 ('HeapFree'與'HeapAlloc'相反;'HeapDestroy'與HeapCreate'相反。)所以,只需在* nix中調用'calloc'和'free'。 –

2

AT & T語法與Intel語法之間是否存在1:1映射?或者是否有AT & T中不支持的特定英特爾命令?

這兩種語法都可以表示每個x86指令的每種形式。任何有效的x86機器代碼都可以反彙編爲T,MASM或NASM語法。

雖然有一些差異,所以映射助記符不完全是1:1。例如,在AT & T語法中,您必須使用movabs $0x123456789abcd, %rax來獲取使用64位立即數的編碼。

在NASM語法中,彙編程序根據常量自動選擇mov r64, imm64編碼與mov r/m32, imm32mov r/m64, sign-extended-imm32編碼。所以mov rax, 1可能會彙編到一個5字節的mov r32, imm32或7字節的mov r/m64, imm32(這就是爲什麼你應該總是寫mov eax, 1,以確保你得到更小的編碼)。但是mov rax, 0x123456789abcd將總是組裝成10字節的mov r64, imm64表單,而不必使用不同的助記符。

請參閱Intel's insn set ref for MOV。 (標記wiki中的其他鏈接)。

這個archive.org.org的副本x86-64.org的what's new in x86-64也涵蓋了movabs與mov助記符問題以及其他內容。

+0

我確實想爲OP添加這個特定的子問題,AT&T與Intel映射基本上是1:1(因爲x86機器代碼是x86機器代碼,仍然是相同的)。但是當他正在做32b→64b轉換時,他可能會遇到在64b模式下不再有效的特定32b指令,所以在他的情況下,由於32-> 64位轉換,1:1映射可能會被破壞。 – Ped7g