2014-12-13 2 views
1

Я работаю над загадками «xchg rax, rax» (xchg.xorpd.net). Это загадки о сборке x86_64, где вы должны понимать, что делают кусочки кода. Это загадка номер 0x15:Понимание небольшого кода asm со странной константой

mov  rdx,0xffffffff80000000 
add  rax,rdx 
xor  rax,rdx 

Похоже, этот код предназначен для повышения ценности внутри бараков в некотором роде, хотя я не совсем понимаю, как это сделать. Я пытался дать некоторые входы и выходы, но мне еще не удалось понять, что делает этот код. Что это за номер 0xffffffff80000000? Может ли кто-нибудь указать мне правильное направление решения? Мне действительно интересно об этом.

+0

Без контекста (который xorpd не предоставляет), это трудно сказать. Тем не менее, если вы берете 32-битное число и устанавливаете самый старший бит, это дает вам -2,147,483,648. Представляя это значение с 64-битным номером, вы получаете FFFFFFFF80000000. И какое значение это может иметь? Не знаю. Единственное, что я вижу, это действительно странный способ превратить 64-битные числа (положительные и отрицательные) в 32-битные числа. FWIW. –

ответ

1

Я не уверен, что подразумевается, что «усиление» означает, что верхняя половина rax равна нулю, это знак-расширяет eax в rax.

Во-первых, обратите внимание, что добавление 0x80000000, а затем xoring с 0x80000000 ничего не сделало бы eax. Они оба инвертируют самый старший бит, и четное количество инверсий отменяется.

Но это 64 бит, поэтому что-то происходит: добавление может нести в нижний бит верхней половины.

Чтобы сделать это проще, давайте представим, что они написали это:

mov edx, 0x80000000 
add rax, rdx 
xor rax, rdx 
mov rdx, 0xffffffff00000000 
add rax, rdx 
xor rax, rdx 

Теперь первые две команды входа продлить до 33 бит, помещая копию знака eax в младший бит верхней половины от rax. Таким образом, верхняя половина равна либо 0, либо 1, в зависимости от знака eax.

Последние две строки теперь очень похожи на обычный -x = ~(x - 1), но применяются только к верхней половине, превращая это 1 во все.

И эти шаги могут быть объединены, что дает исходный код.

В качестве альтернативы вы можете думать об этом как о том, что не разрезаете rax пополам, но разрезаете его «чуть ниже половины», поэтому сделка с отрицанием применяется к 33-битовому числу, начинающемуся с наивысшего бита eax.

+0

Прохладный, Расширение знака! Это то, что делает CDQE. Спасибо :) – dedthecool

+0

@dedthecool хорошо, 'cdqe' по-прежнему подписывается, если верхняя половина не равна нулю, в то время как это будет просто идти вперед и сделать странный результат. – harold