最近我开始学习NASM,我想更深入地了解编译器,虚拟机和计算机通常如何工作的理论。我编写了一个小而简单的NASM程序,只是为了观察它在用NASM编译器构建之后创建的二进制代码。
ASM代码在这里:
section .data
c: db 420
section .text
global _start:
_start:
mov ecx, 1337
mov eax, eax
mov eax, ebx
mov eax, ecx
mov eax, edx
mov eax, ebp
mov eax, esp
mov ebx, eax
mov ebx, ebx
mov ebx, ecx
mov ebx, edx
mov ebx, ebp
mov ebx, esp
mov ecx, eax
mov ecx, ebx
mov ecx, ecx
mov ecx, edx
mov ecx, ebp
mov ecx, esp
mov edx, eax
mov edx, ebx
mov edx, ecx
mov edx, edx
mov edx, ebp
mov edx, esp
; exit
mov eax, 1
mov ebx, 2
int 80h
所以基本上,我只是将每个寄存器移到其他寄存器中。我知道输出会超载' mov'命令使得带寄存器的mov看起来与带有寄存器和常量的mov看起来不同。上面的程序的objdump显然也非常简单:
./program: file format elf64-x86-64
Disassembly of section .text:
00000000004000b0 <.text>:
4000b0: b9 39 05 00 00 mov $0x539,%ecx
4000b5: 89 c0 mov %eax,%eax
4000b7: 89 d8 mov %ebx,%eax
4000b9: 89 c8 mov %ecx,%eax
4000bb: 89 d0 mov %edx,%eax
4000bd: 89 e8 mov %ebp,%eax
4000bf: 89 e0 mov %esp,%eax
4000c1: 89 c3 mov %eax,%ebx
4000c3: 89 db mov %ebx,%ebx
4000c5: 89 cb mov %ecx,%ebx
4000c7: 89 d3 mov %edx,%ebx
4000c9: 89 eb mov %ebp,%ebx
4000cb: 89 e3 mov %esp,%ebx
4000cd: 89 c1 mov %eax,%ecx
4000cf: 89 d9 mov %ebx,%ecx
4000d1: 89 c9 mov %ecx,%ecx
4000d3: 89 d1 mov %edx,%ecx
4000d5: 89 e9 mov %ebp,%ecx
4000d7: 89 e1 mov %esp,%ecx
4000d9: 89 c2 mov %eax,%edx
4000db: 89 da mov %ebx,%edx
4000dd: 89 ca mov %ecx,%edx
4000df: 89 d2 mov %edx,%edx
4000e1: 89 ea mov %ebp,%edx
4000e3: 89 e2 mov %esp,%edx
4000e5: b8 01 00 00 00 mov $0x1,%eax
4000ea: bb 02 00 00 00 mov $0x2,%ebx
4000ef: cd 80 int $0x80
我们可以看到&#34; 0x4000b5&#34;上的89指令 - &#34; 0x4000e3&#34;表示将寄存器移入其他寄存器。但让我感到困惑的是,指令行上的第二个字节并不是我想要的。我怎么解释这个?我对#34;重载&#34;是否有问题?一部分?
谢谢大家的时间,请原谅我的坏英语。我每次都尽力改善它! :)
答案 0 :(得分:5)
您知道您不需要对此进行逆向工程,因为官方手册中有详细记录,对吧? :)参见表2-2。 Intel®64和IA-32架构软件开发人员手册第2卷(2A,2B和2C)中带有ModR / M字节的32位寻址表
请注意,x86寄存器未按您期望的顺序编号。无论出于何种原因,订单为:eax
,ecx
,edx
,ebx
,esp
,ebp
,esi
,edi
。
在第二个字节(称为 modr / m )中,位#0-2和#3-5用于编码寄存器操作数。这在十六进制中并不是很明显,而是以八进制表示。一些例子:
211 300 mov %eax,%eax ; move from register #0 to #0
211 330 mov %ebx,%eax ; move from register #3 to #0
211 313 mov %ecx,%ebx ; move from register #1 to #3