简体   繁体   中英

How can I write this code more efficient?

So one of the problems that were in the exam for me is to make this group of code more efficient with at least 1 line less command. And I didn't know how to do it.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.(The array is an array of characters) This is the code:

I thought maybe she just meant to get the line that doesn't effect the returned value to outside of the function but she told me that that's not what she meant so its wrong.

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

The excepted result is using 1 command,that will swap 2 commands in the current code. Edit: Honestly I don't know why did I use this line: mov[byte ptr si],0 I don't need it,I need to put 0 instead of enter if there is enter. But this is happening alone because the function ends if there is an enter in the array,and 0 is what replacing the second nibble or both of the nibbles but I did need to make sure al is 0. If this is what she meant im so embarrassed and tilted because I might not be able to get to the subject I want to learn next year in our class.): ): ): ): ): I should have been able to see it pretty easily so that's really bad for me...

Try this then:

        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

This implementation uses 11 instructions instead of the 15 instruction of your implementation, saving 4 instructions.

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

The and dl, 11110000b instruction before the shr dl, 4 instruction is redundant. The shift right will by itself throw out the low 4 bits.

There are a couple of things that I would like to draw your attention to.

  • How the nibbles are combined

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

    The logical way to present this combination of bits would be to keep those 4 right bits aka low nibble in the low nibble of the result, and to keep those 4 left bits aka high nibble in the high nibble of the result. Your code doesn't do it that way and neither do the other answers. Perhaps because they want to mimic what you've written.

    If the 1st number is in AL and the 2nd number is in AH then and ax, 0F00Fh will mask away the unwanted bits and or al, ah will leave the combination in AL

  • How 13 is replaced by 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.

    I think that you could be misinterpreting this "...0 should replace it."
    Probably this is DOS and input was terminated with enter , and so a carriage return (13) was appended to the inputted characters. What your teachers warns about is that the value 13 cannot become part of the result. You replace it with zero in the calculation but not in memory .

If this is a one-time calculation

Returning a result in AL and keeping SI put.

    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

If this has to be repeated for all characters in the string

Always returning a result in AL and having SI point at either the remaining characters or the terminating carriage 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:
    ...

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.

The task doesn't say exactly what the combo should look like, so just bringing them together in any register should suffice.

mov ax, [si] loads AL with the 1st number and AH with the 2nd number.

The 4 right bits of the 1st number are in the low nibble (bits 3 to 0).
The 4 left bits of the 2nd number are in the high nibble (bits 7 to 4).

ROR ax, 4 will rotate the low nibble of AX into bits 15-12, and shift the high nibble of AX down into bits 11-8. Now AH holds the combination of bits.

 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

This has but 9 instructions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM