2015-10-14 3 views
2

Я немного ржавый на своем MASM, поэтому я действительно не помню, что делать здесь (если что-то вообще нужно делать). У меня есть процедура MASM (X86), которая выглядит следующим образом. Он имеет две локальные переменные, принимая до 5 байт Общее:Пролог «add esp, 0FFFFFFF8h»

MSC_ASM_GenerateBlock PROC buffer:DWORD,bsize:DWORD,safety:DWORD 
    LOCAL val:DWORD, rc:BYTE ;; local variables 
    MWSIZE EQU 4    ;; machine word size 

    .WHILE bsize >= MWSIZE && safety > 0 
    ;; RDRAND is not available prior to VS2012. Just emit 
    ;; the byte codes using DB. This is `rdrand eax`. 
    DB 0Fh, 0C7h, 0F0h 
    setc rc 
    ... 
    .ENDW 
    ... 
MSC_ASM_GenerateBlock ENDP 

Когда я проверяю разборку, я вижу:

> dumpbin.exe /DISASM rdrand-x86.obj 
Dump of file rdrand-x86.obj 

_MSC_ASM_GenerateBlock: 
    00000000: 55     push  ebp 
    00000001: 8B EC    mov   ebp,esp 
    00000003: 83 C4 F8   add   esp,0FFFFFFF8h 
    00000006: EB 1D    jmp   00000025 
    00000008: 0F C7 F0   rdrand  eax 
    0000000B: 0F 92 45 FB  setb  byte ptr [ebp-5] 
    0000000F: 80 7D FB 00  cmp   byte ptr [ebp-5],0 
    ... 

я считаю add esp, 0FFFFFFF8h это еще один способ сказать sub esp, 08h.

Как указал Джошуа, разница между add esp и sub esp - это флаги после операции. Смущение ассемблера или выбор инструкций могут быть основаны на том факте, что ассемблер не видит контекст RDRAND. Скорее, он видит только jmp на основе CY, и ассемблер считает, что флаги не в хорошем состоянии.

Почему MASM генерирует неинтуитивный add, который зависит от целых целых чисел без знака? И что еще более важно, все в порядке?


Я выполнил порт маршрутизации на MASM64/ML64, используя более широкие машинные слова. Он производит тот же код (размер по модулю машинного слова):

Dump of file rdrand-x64.obj 

MSC_ASM_GenerateBlock: 
    0000000000000000: 55     push  rbp 
    0000000000000001: 48 8B EC   mov   rbp,rsp 
    0000000000000004: 48 83 C4 F0  add   rsp,0FFFFFFFFFFFFFFF0h 
    0000000000000008: EB 1D    jmp   0000000000000037 
    0000000000000010: 48 0F C7 F0  rdrand  rax 
    000000000000001D: 0F 92 45 F7  setb  byte ptr [rbp-9] 
    0000000000000024: 80 7D F7 00  cmp   byte ptr [rbp-9],0 
    ... 

ответ

3

Нечетный компилятор. Очень странно.

add esp, 0FFFFFFF8h 

точно так же, как

sub esp, 8h 

за исключением того, устанавливает биты флага по-разному. Это нормально, и да, это зависит от целого числа без знака. Не проблема, потому что сборка по своей сути не переносима. Если вы хотите знать, почему вам придется попросить Microsoft, и они, вероятно, уже не знают.

+0

* "... кроме того, что он устанавливает бит бит по-разному" * - возможно, это все. Хотя 'RDRAND' устанавливает флаги, компилятор не может сказать, потому что он нацелен на' cl.exe' и 'ml.exe', поставляемые с VS2005, VS2008 и VS2010 (ни один из них не может испускать' RDRAND'). Все компилятор и ассемблер видят/понимают переход, основанный на 'CY', без контекста' RDRAND'. – jww

+1

Но это не он. Вы не проверяете бит флага после изменения esp. – Joshua

+0

Хороший вопрос ... Но, как вы сказали, странно ... Его почему это вызвало мой интерес. – jww

0

Я понятия не имею, почему MASM подумает, что это хорошая идея, но неподписанное переполнение будет работать (так что это безопасно), и еще более смутно это безопасная замена, чтобы сделать даже на 64-битном процессоре, потому что 32-разрядный операнд будет обнулять высокие 32 бита регистра! См. this для пояснения.

Кроме того, поскольку обе инструкции имеют длину 3 байта, там нет никакой неэффективности.

+0

Ну, кроме 64-битного режима, высокие 32 бита RSP могут не быть 0. –

+0

Они будут после 32-битной инструкции! – dave

+0

Это означает, что это не безопасно в 64-битном режиме. –