Как я могу написать этот код более эффективным? - PullRequest
3 голосов
/ 21 июня 2019

Итак, одна из проблем, с которыми я столкнулся на экзамене, состоит в том, чтобы сделать эту группу кода более эффективной с помощью как минимум на 1 строку меньше команды. И я не знал, как это сделать. Цель этого кода - получить 4 правых бита первого числа, левые биты второго числа из массива (адрес которого находится в si), а затем объедините эти 8 битов и поместите результат в 8-битный регистр. 0dh - это ASCII для ввода, мне нужно убедиться, что ввод не является одним из символов, которые вводил пользователь, если его значение 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. Если это то, что она имела в виду, я так смущен и склонен, потому что я не смогу найти предмет, который хочу изучать в следующем году в нашем классе.):):):):): Я должен был видеть это довольно легко, так что это очень плохо для меня ...

Ответы [ 3 ]

3 голосов
/ 23 июня 2019

Ожидаемый результат - использование 1 команды, которая заменит 2 команды в текущем коде.

Инструкция and dl, 11110000b перед инструкцией shr dl, 4 является избыточной.Сдвиг вправо сам по себе выбрасывает младшие 4 бита.

Есть пара вещей, на которые я хотел бы обратить ваше внимание.

  • Как комбинируются кусочки

    получить4 правых бита первого числа, 4 левых бита второго числа, а затем объединить эти 8 битов

    Логический способ представить эту комбинацию битов состоит в том, чтобы сохранить эти 4 правых бита на уровне низкого уровняклев в низком куске результата, и сохранить эти 4 левых бита, как высокий клев в верхнем куске результата.Ваш код не делает это так, как и другие ответы.Возможно, потому что они хотят подражать тому, что вы написали.

    Если 1-е число в AL, а 2-е в AH, тогда and ax, 0F00Fh замаскирует нежелательные биты и or al, ahоставит комбинацию в AL

  • Как 13 заменяется на 0

    0Dh - ASCII ввода.Мне нужно убедиться, что ввод не является одним из символов, введенных пользователем.Если значение равно 0, его следует заменить.

    Я думаю, что вы, возможно, неверно истолковали это "... 0 должно заменить его".
    Возможно, это DOS, и ввод был прерван на введите , и поэтому к введенным символам добавляется возврат каретки (13).Ваши учителя предупреждают о том, что значение 13 не может стать частью результата.Вы заменяете его на ноль в расчете , но не в памяти .

Если это однократный расчет

Возвращение результата в 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 либо на оставшиеся символы, либо на возврат завершающей каретки.

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:
    ...
3 голосов
/ 21 июня 2019

Попробуйте это тогда:

        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 голос
/ 22 июня 2019

Цель этого кода - получить 4 правильных бита первого числа, левые биты второго числа из массива (адрес которого находится в si), а затем объединить эти 8 битов и поместить результат в 8-битном регистре. 0dh - это ASCII для ввода, мне нужно убедиться, что ввод не является одним из символов, введенных пользователем, если он равен 0, его следует заменить.

Задача не говорит точно, как должна выглядеть комбинация, поэтому достаточно просто объединить их в любом регистре.

mov ax, [si] загружает AL с 1-м номером и AH с 2-м номером.

4 правых бита 1-го числа находятся в низком клочке (биты с 3 по 0).
4 левых бита 2-го числа находятся в верхнем клочке (биты с 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 инструкций.

...