#casting #x86 #x86-64 #sse #mov
#Кастинг #x86 #x86-64 #sse #mov
Вопрос:
Вот моя цель: я хочу сгенерировать случайное число в сборке x86_64 с учетом начала и остановки. Вот моя идея сделать это на псевдо-Python:
def rand_bounded(start, stop):
return (start / stop) * rand32()
Таким образом rdrand eax
, я могу получить случайное 32-разрядное число в eax
регистре. Затем я могу start
перейти xmm0
и разделить xmm0
со вторым аргументом в стеке. Это должно меня start / stop
понять. Затем я должен иметь возможность умножить случайное 32-разрядное число на это; давайте назовем это A
. cvtss2si
похоже, правильная инструкция для округления A до ближайшего целого числа, основываясь на его описании здесь .
Моя проблема возникает при фактической попытке написать это. Каждый раз, когда я запускаю свой код (Clang, macOS), я получаю код выхода, равный нулю, что означает, что результат вычисляется неправильно (я перемещаю результат туда, где находится код выхода, rdi
, ниже). Я предполагаю, что это связано с каким-то смешиванием 64-разрядных и 32-разрядных чисел, но кроме этого я понятия не имею, что вызывает сбой. Кто-нибудь, разбирающийся в сборке x86_64, знает, что я делаю неправильно?
.global _main
.data
float_storage:
.int 0
.text
rand_bounded:
push rbp
mov rbp, rsp
movss xmm0, [rbp 16]
divss xmm0, [rbp 24] # xmm0 = start / stop
rdrand eax
mov [float_storage rip], eax # float_storage = rand()
movss xmm1, [float_storage rip]
mulss xmm0, xmm1 # xmm0 *= float_storage
cvtss2si eax, xmm0 # use movd?
mov rsp, rbp
pop rbp
ret
_main:
push 10 # stop
push 5 # start
call rand_bounded
add rsp, 8
mov rdi, rax
mov rax, 0x2000001
syscall
Комментарии:
1.
push 10
иpush 5
помещайте целочисленные значения в стек, но затем вы обрабатываете их как значения с плавающей запятой одинарной точности. Кроме того, системный вызов exit вернет только значение от 0 до 255.2. @MichaelPetch Для вашего первого пункта, как мне преобразовать целочисленные значения стека в значения с плавающей запятой с одинарной точностью? Что касается вашего второго пункта, я согласен с тем, что системный вызов exit выполняет это, поскольку мое ожидаемое случайное число составляет всего от 5 до 10.
3. Просто наблюдение. Как (start / stop)*random32bitnumber дает значение между start и stop?
4. Мне любопытно. Являются ли начальные и конечные целочисленные значения и возвращаются ли значения целыми числами или вы действительно хотите вернуть число с плавающей запятой между 2 числами с плавающей запятой? Если это все целые числа, то здесь нет необходимости в числах с плавающей запятой. Вы могли бы использовать целочисленную
div
инструкцию, которая вернет остаток (по модулю). Чтобы получить целое число в диапазоне из 2 целых чисел (start и stop), вы могли бы сделатьstart (rand32 mod (stop-start))
. Конечно, будет смещение по модулю, но это другая проблема.5. @MichaelPetch Спасибо, ваш метод сработал!