任何方法可以阻止此汇编代码中的代码重复

时间:2015-01-04 06:41:29

标签: assembly x86

我刚刚开始学习x86架构的汇编语言。我正在做一些基于条件分支的练习。目前,就代码分支而言,我已经介绍了 JMP JZ JNZ 指令。这是练习的link。第5点说如果输入为0,则程序会搞砸。这是公平的,因为dec eax会导致eax注册保留0xffffffff。我需要解决这个问题。这是我想出的 - 添加一个伪指令add eax, 0h只是为了检查这是否导致zero-flag被设置,如果设置跳转到代码中的某个位置,它会打印出所需的值并退出程序。

start:
    ; The program begins here:

    call    read_hex
    add     eax, 0h; my code
    jz      lb2; my code
    mov     ecx,1

lb1:
    add     ecx,ecx
    dec     eax
    jnz     lb1

    mov     eax,ecx
    jmp     lb3

lb2:
    inc     eax
    call    print_eax
    ; Exit the process:
    push    0
    call    [ExitProcess]

lb3:
    call    print_eax
    ; Exit the process:
    push    0
    call    [ExitProcess]

令我感到不舒服的是我在lb2lb3中有重复的代码,我不确定是否有任何解决方法。

2 个答案:

答案 0 :(得分:2)

start:
    ; The program begins here:

    call    read_hex
    add     eax, 0h; my code
    jz      lb2; my code
    mov     ecx,1

lb1:
    add     ecx,ecx
    dec     eax
    jnz     lb1

    mov     eax,ecx
    jmp     lb3

lb2:
    inc     eax

lb3:
    call    print_eax
    ; Exit the process:
    push    0
    call    [ExitProcess]

答案 1 :(得分:1)

如果您想一次(使用add same,same)循环将左移一位,简化对count = 0情况的处理,只需跳过移位循环到{{ 1}}指令,可让您删除mov

jmp lb3是根据EAX是否为零来设置ZF的最佳方法。 (不是test eax,eax

add eax,0

有关处理在底部具有分支的循环的更多信息,请参见Why are loops always compiled into "do...while" style (tail jump)?,即使在循环可能需要运行0次的情况下。

在您的情况下,EAX = 0情况下对EAX的数据依赖没有好处。 (start: ; The program begins here: call read_hex mov ecx,1 test eax, eax jz no_shift shift_loop: ; like shl ecx, eax without wrapping the shift count add ecx,ecx dec eax jnz shift_loop no_shift: mov eax,ecx call print_eax ; Exit the process: push 0 call [ExitProcess] )。在这种情况下,这抵消了分支预测+投机执行的某些好处;使用inc eax使EAX = 1意味着分支之后的代码可以在EAX的旧值还没有准备好供分支实际检查预测之前使用EAX。 (如果预测正确)。


您根本不需要为此进行任何分支。 x86的移位指令使创建mov eax, ecx非常容易。

1 << n

这比使用可变计数start: ; The program begins here: call read_hex xor edx, edx ; edx = 0 bts edx, eax ; edx |= 1<<eax mov eax, edx call print_eax push 0 call [ExitProcess] (在Sandybridge系列上为3 oups)更有效,但是在包装移位计数方面具有完全相同的语义:

shl

如果您确实需要大的输入以将位完全移出并保持零,则可以为此分支,或者可以考虑使用SSE2或MMX整数移位,它们确实使移位计数饱和而不是将其包装。 (即mov ecx, eax mov eax, 1 shl eax, cl