2016-12-17 53 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