【问题标题】:Assembly language optimizer汇编语言优化器
【发布时间】:2016-09-27 22:59:27
【问题描述】:

当您编译 c++ 或任何其他编译语言时,会有一个优化器以更有效的方式运行和重写一些代码。由于您不编译程序集或 arm 程序集,就像您使用编译语言一样,是否有优化器正在运行,或者计算机是否运行您输入的内容?

【问题讨论】:

  • 通常在 ASM 中编程时,您希望确保二进制输出与您编写的完全一致。使用一些伪指令可能会有点棘手,可以节省一些输入,例如在固定字 RISC CPU 上加载立即常量,汇编器本身会计算出如何拆分/组合加载指令以获得最终常量。但通常不希望对机器代码进行任何意外修改,因此优化器将毫无意义。

标签: assembly compilation arm


【解决方案1】:

考虑用nasm -f elf64 -Oo组装这个sn-p没有优化

    section .rodata
  Prompt:   db  'Prompting Text', 0

        section .text
        global  _start    

  _start:   xor     rax, rax
            mov     rsi, Prompt
            jmp     Done
            nop
            nop
            nop
            nop
    Done:   xor     rdi, rdi
            mov     eax, 60
            syscall

生成的目标代码是这样的;

000  4831C0            xor rax,rax
003  48BE000000000000  mov rsi,0x0
         -0000
00D  E904000000        jmp qword 0x16
012  90                nop
013  90                nop
014  90                nop
015  90                nop
016  4831FF            xor rdi,rdi
019  B83C0             mov eax,0x3c
01E  0F05              syscall
020

使用默认优化 nasm -f elf64 组装,唯一发生的事情是汇编器发现跳转在 128 个字节内,因此将其更改为短,从而节省 3 个字节。

00  4831C0            xor rax,rax
03  48BE000000000000  mov rsi,0x0
         -0000
0D  EB04              jmp short 0x13
0F  90                nop
10  90                nop
11  90                nop
12  90                nop
13  4831FF            xor rdi,rdi
16  B83C000000        mov eax,0x3c
1B  0F05              syscall
1D 

在不设置汇编选项的情况下修改源代码以强制优化

        section .rodata
  Prompt:   db  'Prompting Text', 0

        section .text
        global  _start     

  _start:   xor     eax, eax
            mov     esi, Prompt
            jmp     short Done
            nop
            nop
            nop
            nop
    Done:   xor     edi, edi
            mov     eax, 60
            syscall

结果是;

00  31C0              xor eax,eax
02  BE00000000        mov esi,0x0
07  EB04              jmp short 0xd
09  90                nop
0A  90                nop
0B  90                nop
0C  90                nop
0D  31FF              xor edi,edi
0F  B83C000000        mov eax,0x3c
14  0F05              syscall
16  

这对于不同的汇编程序是不同的,但我的观点是正如@Ped7g 已经指出的那样,最好了解指令集,这样你编写的内容和目标代码之间就有直接的关联。

如果您不知道很多指令符号扩展到 64 位,这就是为什么 xor eax, eax 产生与 xor rax, rax 相同的结果但节省 1 个字节的原因。

【讨论】:

  • 始终写入 32 位寄存器 zero-extends into the full 64-bit register。 (即将高 32 位归零)。如果你想要 32->64 符号扩展,你必须使用指令,例如MOVSXD r64, r/m32.
  • 一些汇编器也将mov rax, 1234 (7 bytes: REX + opcode + modRM + imm32) 优化成mov eax, 1234 (5 bytes: opcode + imm32),但有些则没有。我忘记了它是否只是针对 MOV,或者是否有些人也会为您优化xor rax,rax
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 2011-07-11
  • 1970-01-01
  • 2017-10-25
相关资源
最近更新 更多