注意:此答案对应于原始问题。
我也是组装新手,所以我可以看到你来自哪里。话虽如此,您发布的人为代码似乎存在不少问题。
操作数的顺序重要吗?如果是,为什么?
有两种不同风格的人类可读助记符用于表示 CPU 指令代码:AT&T 和 Intel。虽然 Intel 和 AT&T 语法中操作数的显示顺序不同,但内存中指令代码字节的顺序是恒定的。
英特尔语法:
08048074 <main>:
8048074: 55 push ebp
8048075: 89 e5 mov ebp,esp
8048077: b8 00 00 00 00 mov eax,0x0
804807c: 5d pop ebp
804807d: c3 ret
AT&T 语法:
08048074 <main>:
8048074: 55 push %ebp
8048075: 89 e5 mov %esp,%ebp
8048077: b8 00 00 00 00 mov $0x0,%eax
804807c: 5d pop %ebp
804807d: c3 ret
的(小端)字节序列89 e5表示为mov ebp,esp在Intel语法和mov %esp,%ebp在AT&T的语法。尽管操作数的助记表示彼此相反,但它们表示相同的字节序列。操作码助记符的顺序很重要,因为它由用于表示指令代码的语法决定。
代码
运行每一步代码后,结果会发生什么变化?
除了最后一行之外,问题中发布的每一行代码都至少包含一个非法操作数,因此只有该行可以运行。
假设使用 AT&T 语法。
0x2000: cs cs cs
%cs是段寄存器,作为寄存器,必须以%符号为前缀。这里有3个操作数,都是同一个寄存器,没有指令。这是非法的。我不确定你预想的会发生在这里。
0x2001: xor x20,(eax)
x20是非法操作数。常量是立即数操作数,必须以$符号为前缀,所以这个操作数应该是$0x20。%eax是一个寄存器,因此%需要前缀。(eax)应该是(%eax).
0x2002: and x20,%ah
0x2003: or x20, %dh
0x2004: dec (ebi)
ebi看起来它应该是一个寄存器。你是说%edi还是%ebx?无论哪种方式,它都缺少%前缀
0x2005: dec %si
- 该
dec指令将其操作数的内容减一。所以存储的值%si会递减。
修复了,代码看起来像这样:
xor $0x20, (%eax)
and $0x20, %ah
or $0x20, %dh
dec (%edi)
dec %si
你如何从这个汇编代码构造一些等效的代码(例如 c++)?
假设更正后的代码实际上是正确的,具有足够理解力的人可以简单地查看这个片段并用高级语言创建一个大致等效的语句或语句序列。对于凡人来说,有称为反编译器的工具。
资源
Jonathan Bartlett 的“从头开始编程”和 Richard Blum 的“专业汇编语言”是非常好的 IMO。更具技术性的资源是System V Application Binary Interface Intel386 Architecture Processor Supplement,它揭示了处理器和虚拟内存的一些奥秘。SO 的 x86 wiki列出了许多资源。当然,还有英特尔手册。