我怎样才能更有效地编写这段代码?

How can I write this code more efficient?

所以对我来说,考试中的一个问题是使用至少 1 行更少的命令来提高这组代码的效率。 我不知道该怎么做 it.The 此代码的目标是获取第一个数字的右 4 位、数组中第二个数字的左位(其地址位于 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 而不是输入。但这是单独发生的,因为如果数组中有一个输入,函数就会结束,0 是替换第二个半字节或两个半字节的东西,但我确实需要确保 al 是 0。 如果这就是她的意思,我会感到非常尴尬和倾斜,因为我可能无法在我们的 class 中学习我明年想学习的主题: ) : ) : ) ) 我应该很容易就能看到它,所以这对我来说真的很糟糕...

那就试试这个:

        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 条指令。

The goal of this code is to get the 4 right bits of the first number,the left bits from the second number from the array (which its address is located in si) and then to merge those 8 bits- and to put the result in a 8 bit register. 0dh is the ASCII of enter,I need to make sure that enter isn't one of the chars that user had input,if it does 0 should replace it.

该任务并未确切说明组合应该是什么样子,因此只需将它们放在任何寄存器中就足够了。

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

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

ROR ax, 4 会将 AX 的低四位循环移动到位 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 条指令。

The expected result is using 1 command, that will swap 2 commands in the current code.

shr dl, 4指令之前的and dl, 11110000b指令是多余的。右移本身会丢掉低 4 位。

我想提请您注意几件事。

  • 半字节的组合方式

    get the 4 right bits of the first number, the 4 left bits of the second number and then merge those 8 bits

    呈现这种位组合的逻辑方法是将右边的 4 位即低半字节保留在结果的低半字节中,并将左边的 4 位即高半字节保留在结果的高半字节中.您的代码不会那样做,其他答案也不会。也许是因为他们想模仿你写的东西。

    如果第一个数字在 AL 中,第二个数字在 AH 中,则 and ax, 0F00Fh 将屏蔽不需要的位,而 or al, ah 将保留组合AL

  • 13怎么换成0

    0Dh is the ASCII of enter. I need to make sure that enter isn't one of the chars that user had input. If it does 0 should replace it.

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

如果这是一个one-time计算

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

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

总是 return 在 AL 中生成一个结果并且 SI 指向剩余字符或终止字符 return。

Again:
    mov     ax, [si]
    cmp     al, 13      ; If 1st byte is 13, then next byte is just garbage!
    je      CR1         ; ... so no further interpretation needed
    and     al, 0Fh
    inc     si
    cmp     ah, 13      ; If 2nd byte is 13, then result is based on 1st byte
    je      CR2         ; ... and that kind-of zero-replacement
    and     ah, 0F0h
    inc     si
    or      al, ah

    ...

    jmp     Again

CR1:
    xor     al, al
CR2:
    ...