准确理解汇编语言如何提高效率

时间:2014-10-12 21:42:38

标签: c assembly x86

我已经生成了两个汇编文件 - 一个是优化的,另一个不是。通过优化生成的汇编语言代码应该比其他汇编语言代码更有效。我对如何实现效率更感兴趣。据我所知,在非优化版本中,总是必须对寄存器%rbp进行偏移调用才能找到地址。在优化版本中,地址存储在寄存器中,因此您不必依赖并调用%rbp来查找它们。

我说错了吗?如果是这样,那么优化版本是否会不会有利?谢谢你的时间。

这是一个从42 GIF转换为CYMK的函数。

void rgb2cmyk(int r, int g, int b, int ret[]) {
int c = 255 - r;
int m = 255 - g;
int y = 255 - b;
int k = (c < m) ? (c < y ? c : y) : (m < y ? m : y);
c -= k; m -= k; y -= k;
ret[0] = c; ret[1] = m; ret[2] = y; ret[3] = k;
}

这是尚未优化的汇编语言代码。注意我已经使用;;做了笔记;在代码中。

No Opt:

   .section   __TEXT,__text,regular,pure_instructions
   .globl   _rgb2cmyk
   .align   4, 0x90
_rgb2cmyk: ## @rgb2cmyk
   .cfi_startproc
## BB#0:
   pushq   %rbp
Ltmp2:
   .cfi_def_cfa_offset 16
Ltmp3:
   .cfi_offset %rbp, -16
   movq   %rsp, %rbp
Ltmp4:
   .cfi_def_cfa_register %rbp
   ;;initializing variable c, m, y
   movl   $255, %eax
   movl   %edi, -4(%rbp)
   movl   %esi, -8(%rbp)
   movl   %edx, -12(%rbp)
   movq   %rcx, -24(%rbp)
   movl   %eax, %edx
   subl   -4(%rbp), %edx
   movl   %edx, -28(%rbp)
   movl   %eax, %edx
   subl   -8(%rbp), %edx
   movl   %edx, -32(%rbp)
   subl   -12(%rbp), %eax
   movl   %eax, -36(%rbp)

   movl   -28(%rbp), %eax
   ;;compare
   cmpl   -32(%rbp), %eax
   jge   LBB0_5
## BB#1:
   movl   -28(%rbp), %eax
   cmpl   -36(%rbp), %eax
   jge   LBB0_3
## BB#2:
   movl   -28(%rbp), %eax
   movl   %eax, -44(%rbp) ## 4-byte Spill
   jmp   LBB0_4
LBB0_3:
   movl   -36(%rbp), %eax
   movl   %eax, -44(%rbp) ## 4-byte Spill
LBB0_4:
   movl   -44(%rbp), %eax ## 4-byte Reload
   movl   %eax, -48(%rbp) ## 4-byte Spill
   jmp   LBB0_9
LBB0_5:
   movl   -32(%rbp), %eax
   cmpl   -36(%rbp), %eax
   jge   LBB0_7
## BB#6:
   movl   -32(%rbp), %eax
   movl   %eax, -52(%rbp) ## 4-byte Spill
   jmp   LBB0_8
LBB0_7:
   movl   -36(%rbp), %eax
   movl   %eax, -52(%rbp) ## 4-byte Spill
LBB0_8:
   movl   -52(%rbp), %eax ## 4-byte Reload
   movl   %eax, -48(%rbp) ## 4-byte Spill
LBB0_9:
   movl   -48(%rbp), %eax ## 4-byte Reload
   movl   %eax, -40(%rbp)
   movl   -40(%rbp), %eax
   movl   -28(%rbp), %ecx
   subl   %eax, %ecx
   movl   %ecx, -28(%rbp)
   movl   -40(%rbp), %eax
   movl   -32(%rbp), %ecx
   subl   %eax, %ecx
   movl   %ecx, -32(%rbp)
   movl   -40(%rbp), %eax
   movl   -36(%rbp), %ecx
   subl   %eax, %ecx
   movl   %ecx, -36(%rbp)
   movl   -28(%rbp), %eax
   movq   -24(%rbp), %rdx
   movl   %eax, (%rdx)
   movl   -32(%rbp), %eax
   movq   -24(%rbp), %rdx
   movl   %eax, 4(%rdx)
   movl   -36(%rbp), %eax
   movq   -24(%rbp), %rdx
   movl   %eax, 8(%rdx)
   movl   -40(%rbp), %eax
   movq   -24(%rbp), %rdx
   movl   %eax, 12(%rdx)
   popq   %rbp
   retq
   .cfi_endproc


.subsections_via_symbols

优化:

   .section   __TEXT,__text,regular,pure_instructions
   .globl   _rgb2cmyk
   .align   4, 0x90
_rgb2cmyk: ## @rgb2cmyk
   .cfi_startproc
## BB#0:
   pushq   %rbp
Ltmp2:
   .cfi_def_cfa_offset 16
Ltmp3:
   .cfi_offset %rbp, -16
   movq   %rsp, %rbp
Ltmp4:
   .cfi_def_cfa_register %rbp
   movl   $255, %r8d
   movl   $255, %eax
   subl   %edi, %eax
   movl   $255, %edi
   subl   %esi, %edi
   subl   %edx, %r8d
   cmpl   %edi, %eax ##;; compare m and c
   jge   LBB0_2
## BB#1: ;; c < m
   cmpl   %r8d, %eax ## compare y and c
   movl   %r8d, %edx
   cmovlel   %eax, %edx
   jmp   LBB0_3
LBB0_2: ##;; c >= m
   cmpl   %r8d, %edi ## compare y and m
   movl   %r8d, %edx
   cmovlel   %edi, %edx
LBB0_3:
   subl   %edx, %eax
   subl   %edx, %edi
   subl   %edx, %r8d
   movl   %eax, (%rcx)
   movl   %edi, 4(%rcx)
   movl   %r8d, 8(%rcx)
   movl   %edx, 12(%rcx)
   popq   %rbp
   retq
   .cfi_endproc


.subsections_via_symbols

1 个答案:

答案 0 :(得分:1)

是。优化版本通过在寄存器中存储中间值而不是一遍又一遍地重新加载它们来执行更少的存储器读取操作。

您使用call错误。这是一个技术术语,意味着在堆栈上推送返回地址并分支到新位置以获取指令。你的意思是简单地使用寄存器。

你能想到更长,更慢的代码“更好”的原因吗?

相关问题