如何简化/压缩代码(如果可能)?

时间:2016-10-20 21:43:23

标签: c assembly

我想用c和汇编程序代码向你展示我的程序。我也有一些问题。

这是c

中的一段代码
#include <stdio.h>
void podaj_znak(int tab[], int n);
int main()
{
    int tab[7] = {4, 5, 6, 2, -80, 0, 56};
    printf("Przed: ");
    for (int i = 0; i < 7; i++)
        printf("%d ", tab[i]);
    printf("\n");
    podaj_znak(tab, 7);
    printf("Po: %d %d %d %d %d %d %d", tab[0], tab[1], tab[2], tab[3], tab[4], tab[5], tab[6]);
    printf("\n");
    return 0;
}

和asm就在这里

.686
.model flat
public _podaj_znak
.code
_podaj_znak PROC

push ebp
mov ebp, esp
mov edx, [ebp+8]
mov ecx, [ebp+12]
ptl:
mov eax, [edx]
cmp eax, 0
jl minus
ja plus
mov ebx, 0
mov [edx], ebx
jmp dalej
minus: mov ebx, -1
mov [edx], ebx
jmp dalej
plus: mov ebx, 1
mov [edx], ebx
jmp dalej

dalej: add edx, 4
sub ecx, 1
jnz ptl
pop ebp
ret
_podaj_znak ENDP
END

我的问题是,如何简化/压缩代码?

编辑:发布程序的功能以及我喜欢的内容。这只是我训练和习惯组装。程序就像你从-inf到inf得到数字,当实际数字等于0时,它保持不变,当它小于0时,它被-1替换,当数字大于0,它被替换为1.事情是,我想以某种方式优化汇编程序代码,但我不知道是否甚至可以压缩它。

3 个答案:

答案 0 :(得分:1)

不太适合这个论坛,但仍然:

对于C代码,我创建了一个PrintTab函数,它接受制表符并计算并打印表格。然后在podaj_znak调用之前和之后调用它。

对于asm代码:

  1. 请添加评论。我知道这可能只是一个班级项目,但仍然习惯了。
  2. 为什么将[edx]移动到eax而不仅仅是cmp [edx],0?
  3. 如果性能很重要,也许可以跳过prolog / epilog并使用&#39; fastcall&#39;召集会议。
  4. 为什么重复&#34; mov [edx],ebx&#34;对于每个案例?把它移到dalej。
  5. 作为一个&#39;诀窍&#39;您可以尝试检查-1,但随后使用setnz处理其他2个案例。

答案 1 :(得分:1)

nasm语法,可能需要为其他asm进行微妙的修复,我的解决方案:

; converts values in tab into [-1, 0, 1] as sgn()
; arguments: two on stack(int tab[], int n)
; modified registers: esi, edi, eax, ebx
; "no branch" version (except loop itself)
_podaj_znak:
    mov   esi,[esp+4]   ; tab ptr
    mov   eax,[esp+8]   ; count
    xor   ebx,ebx
    lea   edi,[esi+eax*4] ; tab.end() ptr
sgn_loop:
    lodsd               ; eax = [ds:esi], esi += 4
    ; change eax to [-1, 0, 1] by sgn(eax)
    test  eax,eax
    setnz bl
    sar   eax,31
    or    eax,ebx
    ; overwrite original value with sgn() result
    cmp   esi,edi       ; test if end of tab was reached
    mov   [esi-4],eax
    jb    sgn_loop
    ret

然后为了好奇心谷歌搜索互联网(只是循环部分不同),3指令版本(我是4):

    ...
; modifies also edx in this variant
sgn_loop:
    lodsd               ; eax = [ds:esi], esi += 4
    ; set edx to [-1, 0, 1] by sgn(eax)
    cdq
    cmp   edx,eax
    adc   edx,ebx
    ; overwrite original value with sgn() result
    cmp   esi,edi
    mov   [esi-4],edx
    jb    sgn_loop
    ret

这两种变体都是无分支的,因此它们应该具有优于任何分支变体的性能(但我不打算对其进行分析)。

答案 2 :(得分:0)

可以通过仅调用一次mov [edx], ebx来优化程序集,如下所示:

ptl:
mov eax, [edx]
cmp eax, 0
jl minus
ja plus
mov ebx, 0            ; only set to 0
jmp dalej
minus: mov ebx, -1    ; only set to -1
jmp dalej
plus: mov ebx, 1      ; only set to 1
jmp dalej

dalej: mov [edx], ebx ; update the array[edx]
add edx, 4
sub ecx, 1
jnz ptl