我如何才能更高效地编写此代码?

时间:2019-06-21 11:03:37

标签: assembly x86-16 simplify

所以对我而言,考试中的问题之一是使用至少少一行的命令来提高这组代码的效率。 我不知道该怎么做。此代码的目标是从数组(其地址位于si中)获取第二个数字的第四个右位,然后从第二个数字获取左个位。合并这8位-并将结果放入8位寄存器中。 0dh是enter的ASCII码,我需要确保enter不是用户输入的字符之一,如果输入为0,则应该替换它。(该数组是一个字符数组) 这是代码:

我以为也许她只是想把不影响返回值的行放到函数外部,但是她告诉我那不是她的意思,所以这是错误的。

cmp [byte ptr si],0Dh
je LessThan4
mov al,[si]
shl al,4;(a)-first nibble
inc si
cmp [byte ptr si],0Dh
je LessThan4
mov dl,[si]
and dl,240;11110000b
shr dl,4;(b)-second nibble 
or al,dl;al=ab merging the nibbles
inc si
jmp Normal
LessThan4:
mov[byte ptr si],0
Normal:
ret

例外结果是使用1条命令,它将在当前代码中交换2条命令。 编辑:老实说,我不知道为什么我使用此行:mov [byte ptr si],0 我不需要它,如果有回车,我需要输入0而不是回车。但这是单独发生的,因为如果数组中有一个enter函数就会结束,并且0是替换第二个半字节或两个半字节的内容,但是我确实需要确保al为0。 如果这是她的意思,我会感到尴尬和困惑,因为我可能无法在明年的课程中上到我想学的科目。):) :) :) :): 我应该能够很容易地看到它,所以这对我来说真的很糟糕...

3 个答案:

答案 0 :(得分:3)

然后尝试:

        lodsw                ; load ax from [si], then increment si twice
        cmp al, 0dh          ; was the first character a CR?
        jz enter1            ; if yes, abort
        cmp ah, 0dh          ; was the second character a CR?
        jz enter2            ; if yes, abort
        rol ax, 4            ; combine the digits in al and ah into al
        ret

enter1: dec si               ; return back to the first character
enter2: dec si               ; return back to the second character
        mov [byte ptr si], 0 ; terminate input with a NUL
        ret

此实现使用11条指令(而不是您的实现的15条指令)保存4条指令。

答案 1 :(得分:3)

  

预期结果是使用1条命令,它将在当前代码中交换2条命令。

and dl, 11110000b之前的shr dl, 4指令是多余的。右移本身将抛出低4位。

我想提醒您一些注意事项。

  • 半字节如何组合

      

    获取第一个数字的右4位,第二个数字的左4位,然后合并这8个位

    呈现这些位组合的逻辑方法是将这4个右位(也称为低半字节)保留在结果的低半字节中,并将这4个左位(即又称为高半字节)保留在结果的高半字节中。您的代码不会那样做,其他答案也不会。也许是因为他们想模仿您所写的内容。

    如果第一个数字在AL中,而第二个数字在AH中,则and ax, 0F00Fh将掩盖不需要的比特,而or al, ah将把组合保留在{{ 1}}

  • 如何用0代替13

      

    0Dh是enter的ASCII。我需要确保enter不是用户输入的字符之一。如果为0,则应将其替换。

    我认为您可能会误解此“ ... 0应该替换它。”
    可能是DOS,输入用 enter 终止,因此在输入的字符后附加了回车符(13)。您的老师警告的是,值13不能成为结果的一部分。您可以在计算中将其替换为零,而不是在内存中

如果这是一次性计算

AL中返回结果并保持放置AL

SI

如果必须对字符串中的所有字符重复此操作

始终在 mov ax, [si] cmp al, 13 jne L1 xor ax, ax ; Falling through shaves off an instruction L1: cmp ah, 13 jne L2 xor ah, ah L2: and ax, 0F00Fh or al, ah ret 中返回结果,并使AL指向其余字符或终止回车。

SI

答案 2 :(得分:1)

  

此代码的目标是从数组(其地址位于si中)中获取第一个数字的右4位,第二个数字的左位,然后合并这8位-结果存入8位寄存器。 0dh是enter的ASCII码,我需要确保enter不是用户输入的字符之一,如果输入为0,则应替换为该字符。

该任务并未确切说明该组合的外观,因此仅将它们组合到任何寄存器中就足够了。

mov ax, [si]加载AL的第一个数字,AH加载第二个数字。

第一个数字的右4位在低半字节(位3到0)中。
第二个数字的左4位在高半字节(第7至4位)中。

ROR ax, 4AX的低半字节旋转到15-12位,并将AX的高半字节向下移位到11-8位。现在AH保留了位的组合。

 mov ax, [si]
 cmp al, 13
 je  CR
 cmp ah, 13
 je  CR
 ror ax, 4            ; combine the digits in al and ah into al
 ret
CR:
 mov byte [si], 0
 ret

这里只有9条指令。