2016-10-24 3 views
4

У меня скоро будет сборка, и во время подготовки я заметил что-то странное.
повторял while ZF = 0, и я был преподан, что repe должен повторять, в то время как CX не равен нулю, а ZF = 1.
Я провел некоторые испытания и обнаружил, что до movsb, rep, repe и repne инструкции работают одинаково.
Какое объяснение?Зачем делать повторы и повторять то же самое до movsb?

редактировать: вот код:

.model small 
    .data 
    A db ' This  is a test ' 
    N db 27 
    .stack 10h 
    .code 
    mov ax,@data 
    mov ds,ax 
    mov es,ax 
    cld 
    mov al,' ' 
    mov cl,N 
    xor ch,ch 
    mov di,offset A 
    next: repe scasb 
    jcxz cont  ; jump if cx=0 
    dec di 
    inc cx 
    xchg si,di  ; swap between si and di 
    push cx 
    push di 
    repe movsb 
    pop di 
    pop cx 
    repne scasb 
    mov si,di 
    jmp next 
    cont: .exit 
    end 
+0

Можете ли вы показать код, который проявляет это явление? Обратите внимание, что 'repeat' и' repne' не зависят от начального состояния 'zf', так как' zf' сразу устанавливается первой итерацией. – fuz

+0

Я понимаю это, но ** movsb ** не влияет на флаг нуля. – user7064593

ответ

2

В коде машины есть только два разных префиксных байта.

  • 0xF3 называют РЭП при использовании с MOVS/LODS/КСН/INS/OUTS (инструкции, которые не влияют на флаги)
  • 0xF3 называется REPE или REPZ при использовании с CMPS/SCAS
  • 0xF2 называется REPNE или REPNZ при использовании с CMPS/SCAS и не документируется для других инструкций.

от Intel insn reference manual REP entry только документы F3 REP для MOVS, а не префикс F2. Поздравляем, вы нашли недокументированную кодировку для REP MOVSB, по крайней мере, на любом CPU, на котором вы протестировали это. :)

См. Также this appendix of the NASM manual, который включает в себя другие недокументированные коды операций, но не это F2 A4 REPNE MOVSB. (связанный с wiki) .


Обычно префиксы, которые не влияют на команду, игнорируются, так что я ожидал бы REPNE MOVSB ​​бежать идентично только MOVSB. например TZCNT кодируется как REP BSF, а на процессорах, которые не поддерживают BMI1, он просто выполняется как BSF. (Выполнение того же, за исключением случаев, когда источник равен нулю.)

Аналогичным образом REP RET является обычным приемом для ввода прокладки to work around a limitation of AMD K8/K10 branch predictors и работает так же, как RET.

Но Intel предостерегает, что это поведение не гарантируется, поскольку новые инструкции могут использовать кодировку, которая использовалась для другой команды с игнорируемым префиксом. например LZCNT (закодированный как REP BSR) создает противоположный результат для BSR, поэтому старый код, включающий REP BSR, по какой-то причине перестанет работать с новыми процессорами.

+0

Благодарим вас за ответ. Я не писал этот код, я думаю, что это просто ошибка в TASM и в старом тесте. Вероятно, я должен попросить учителя о том, чтобы получить соответствующий ответ для моего теста – user7064593

+0

@ user7064593: О, я вижу «rep lodsb» в коде, который вы опубликовали. Да, это похоже на ошибку в коде. Однако я не считаю это ошибкой в ​​TASM. REPE всегда будет собираться на 'F3'. На языке ассемблера я не ожидал бы сообщения об ошибке, хотя это может быть хорошей идеей для ассемблера. (Вы всегда можете получить требуемый машинный код с директивой «DB» для сборки байтов непосредственно в выходной файл, поэтому, если ассемблер сделает больше проверок и отклонит недокументированные комбинации префикса и инструкции, в худшем случае заставит кого-то закодировать некоторые вещи вручную) –

+0

@ user7064593: Я не пытался понять код, так как это не было вопросом, но, возможно, он пытается использовать 'repeat movsb' в качестве условной нагрузки? (например, 'cmove al, [si]', но также проверяя, что CX! = 0). Если это так, это обречено на провал, если проверка ZF имеет значение. :/Принимая во внимание все настройки push/pop и xchg, повтор lodsb, вероятно, даже не самый эффективный способ сделать это, даже если он сделал проверку ZF.) –

3

rep и repe имеют одинаковый опкод; rep действителен для инструкций INS, OUTS, MOVS, LODS и STOS; repe/repne действителен для инструкций CMPS и SCAS (которые влияют на флаг нуля).

Поскольку их коды операций одинаковы, repe - это то же самое, что и rep; технически вы не можете использовать repne перед инструкциями MOVS, хотя кажется, что процессор просто обрабатывает его так же, как rep (по крайней мере, на процессоре, который вы пытались).

TL; repne movsb - недопустимая/недокументированная инструкция, и все ставки отключены. Вы не должны полагаться на это. repe movsb технически недействителен, но ваш ассемблер кодирует его точно как rep movsb.

Source.

+1

Большое спасибо за ответ. Я не писал этот код, этот код из старого теста, и задача заключалась в том, чтобы понять, что делает код и каково будет значение переменной A после запуска кода. – user7064593

Смежные вопросы