如何理解" (手动解释)用NASM for Linux编写的一个小二进制可执行文件

时间:2017-03-03 01:06:00

标签: assembly nasm executable binary-data

最近我开始学习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;是否有问题?一部分?

谢谢大家的时间,请原谅我的坏英语。我每次都尽力改善它! :)

1 个答案:

答案 0 :(得分:5)

您知道您不需要对此进行逆向工程,因为官方手册中有详细记录,对吧? :)参见表2-2。 Intel®64和IA-32架构软件开发人员手册第2卷(2A,2B和2C)中带有ModR / M字节的32位寻址表指令集参考,AZ

请注意,x86寄存器未按您期望的顺序编号。无论出于何种原因,订单为:eaxecxedxebxespebpesiedi

在第二个字节(称为 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