Как я могу написать этот код более эффективно?

Так что одна из задач, стоявших передо мной на экзамене, — сделать эту группу кода более эффективной, по крайней мере, с командой на 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. Если это то, что она имела в виду, я так смущен и наклонен, потому что я, возможно, не смогу добраться до предмета, который я хочу изучить в следующем году в нашем классе.): ): ): ): ): я должен был быть в состоянии увидеть это довольно легко, так что это действительно плохо для меня ...


person The Niv    schedule 21.06.2019    source источник
comment
Я не совсем понимаю цель cmp [si], 0dh; je LessThan4. Как это согласуется с вопросом? Если вы просто хотите объединить кусочки, попробуйте mov ax, [word ptr si]; rol ax, 4. Это оставляет результат в al.   -  person fuz    schedule 21.06.2019
comment
@fuz, о, извини, я забыл упомянуть об этом. 0dh - это ASCII ввода, мне нужно убедиться, что ввод не является одним из символов, которые пользователь ввел (массив представляет собой массив символов)   -  person The Niv    schedule 21.06.2019
comment
Но что, если первое число 13?   -  person Raymond Chen    schedule 21.06.2019
comment
@TheNiv, в таком случае, каким должен быть результат?   -  person fuz    schedule 21.06.2019
comment
@RaymondChen Я забыл упомянуть, что если первое число равно 13, оно должно быть просто 0. Я понял свою ошибку - нужно было сделать xor al, al в начале кода.   -  person The Niv    schedule 21.06.2019
comment
Я хочу сказать, что неясно, есть ли у вас массив чисел или массив символов ASCII. Кажется, что вы иногда относитесь к нему как к числу, а иногда как к символу. (Тем не менее, я думаю, что ответ, который искал экзамен, состоял в том, чтобы удалить and dl,240.)   -  person Raymond Chen    schedule 21.06.2019
comment
@RaymondChen Спасибо. Когда я оглядываюсь назад, я должен был просто спросить себя, что я делаю в каждой строке, и я уверен, что мог бы легко это заметить. так, как мне было нужно.   -  person The Niv    schedule 21.06.2019
comment
@RaymondChen Да, и о массиве. Это массив символов. Но вы также можете рассматривать его как массив чисел, потому что в ассемблере каждый символ обрабатывается своим кодом ASCII, который является числом.   -  person The Niv    schedule 21.06.2019
comment
Верно, но необычно, чтобы что-то рассматривалось как число и как символ. Пользователи не думают, что мне нужно вводить символ, чей ASCII-код в шестнадцатеричном формате имеет старшие четыре бита, равные 5. Обычно вы конвертируете символ в число с помощью некоторого алгоритма, понятного человеку.   -  person Raymond Chen    schedule 22.06.2019
comment
Я голосую за то, чтобы закрыть этот вопрос как не относящийся к теме, потому что вопросы проверки кода не относятся к теме переполнения стека.   -  person Ross Ridge    schedule 22.06.2019


Ответы (3)


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

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

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

  • #P3# <блочная цитата> #P4# #P5# #P6#
  • #P7# <блочная цитата> #P8# #P9#

Если это разовый расчет

Возврат результата в 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:
    ...
person Sep Roland    schedule 23.06.2019
comment
Спасибо за объяснение, я ценю длинный ответ. Я понял некоторые из моментов, о которых вы упомянули, сразу после повторного чтения моего кода, таких как замена ввода и некоторые другие вещи. Ваш ответ очень ясен, так что еще раз спасибо, я кое-что узнал из этого, это точно. - person The Niv; 24.06.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 инструкции.

person fuz    schedule 21.06.2019
comment
Спасибо. Эх, я думаю, вращение просто исчезло из моей головы... на самом деле это не сложно. ): Я надеюсь, что все еще смогу попасть в класс, который хочу, потому что мне действительно нравится программировать больше, чем некоторым другим людям в моем классе, но я не преуспел в ассемблере, потому что это было для меня новым, я думаю. Я не хуже, но по сравнению со всем классом я мог бы быть в 60% лучших, так что idk. есть надежда. - person The Niv; 21.06.2019
comment
Ваш lodsw предполагает, что флаг направления снят. Вам может понадобиться инструкция cld, чтобы убедиться, что это так. - person 1201ProgramAlarm; 21.06.2019
comment
@TheNiv Честно говоря, я не ожидал, что студенты заметят, что rol можно использовать для этой цели. - person fuz; 21.06.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 инструкций.

person Fifoernik    schedule 22.06.2019
comment
Обратите внимание, что это перезаписывает неправильный байт, если al не CR, а ah. Это также оставляет SI с неправильным значением в конце. - person fuz; 22.06.2019
comment
@fuz Почему SI важно в конце. Во всяком случае, иметь его в начале имеет смысл. - person Fifoernik; 22.06.2019
comment
OP уделяет большое внимание надлежащему продвижению SI. Я не могу сказать, является ли это частью требований, поскольку OP не сказал, но я думаю, что это так. Тем не менее, ваш код также неверен в том, что он перезаписывает неправильный байт, если AL не CR, а AH. - person fuz; 22.06.2019