I want to separate the upper and lower half of a 64 bit integer and put them into two registers.
Asked
Active
Viewed 2,272 times
-4
-
This is a duplicate many times over, but `uint32_t lower = bignum & 0xffffffff, upper = bignum >> 32;` – David C. Rankin Feb 14 '20 at 06:38
-
Does this answer your question? [How to store a 64 bit integer in two 32 bit integers and convert back again](https://stackoverflow.com/questions/2810280/how-to-store-a-64-bit-integer-in-two-32-bit-integers-and-convert-back-again) or [How to combine two 32-bit integers into one 64-bit integer?](https://stackoverflow.com/questions/2768890/how-to-combine-two-32-bit-integers-into-one-64-bit-integer) – David C. Rankin Feb 14 '20 at 06:40
-
I know that you have to shift the bits in C, but I can only shift it in registers in assembly, and the registers can only hold 32 bits, so I am not sure how I can get the lower 32 bits. – mangos5 Feb 14 '20 at 06:55
-
3What assembler/hardware are you using. If you have only 32-bit registers and a 64-bit number - it is already split between two registers. Is this for ARM or x86? See [Storing a 64 bit decimal in two 32 bit registers (ASSEMBLY - NASM](https://stackoverflow.com/questions/47241503/storing-a-64-bit-decimal-in-two-32-bit-registers-assembly-nasm) and [Accessing and Modifying Upper Bits in x86 and x64 Registers](http://dsasmblr.com/accessing-and-modifying-upper-half-of-registers/) – David C. Rankin Feb 14 '20 at 06:57
-
Look at C compiler output for a function that takes a uint64_t arg and returns the high or low half. – Peter Cordes Feb 14 '20 at 07:08
-
Here is Peter's other answer I was looking for [How do I atomically move a 64bit value in x86 ASM?](https://stackoverflow.com/questions/48046591/how-do-i-atomically-move-a-64bit-value-in-x86-asm) – David C. Rankin Feb 14 '20 at 07:15
-
I am using the intel assembly – mangos5 Feb 14 '20 at 17:53
1 Answers
2
Your question is really not clear. You should at least state whether you are using x86 or x64, and whether the source is in a register or in memory.
From a variable in memory
; .u64 --> EDI:ESI
.u64 DQ 0x0123456789ABCDEF
MOV ESI, [.u64]
MOV EDI, [.u64 + 4]
x64, from a register
; RBX --> EDI:ESI
MOV ESI, EBX
MOV RDI, RBX
SHR RDI, 32
x86, from a pair of registers
; 64-bit numbers are stored in register pairs, usually EDX:EAX
; EDX:EAX --> EDI:ESI
MOV EDI, EDX
MOV ESI, EAX

W. Chang
- 494
- 3
- 10
-
Your last example is copying EDX:EAX to ESI:EDI not EDI:ESI. (i.e. it swaps high/low halves, like a rotate by 32). – Peter Cordes Feb 15 '20 at 07:24
-
Also note that your x86-64 example doesn't need to `mov esi, ebx`, you can just comment that the low half is available in `ebx`. With BMI2, you can `rorx rdi, rbx, 32` to get the high half into EDI if you don't need it zero-extended to 64-bit either. – Peter Cordes Feb 15 '20 at 07:26
-
@Peter Cordes Thanks for pointing out the careless mistake. I made the correction. For your second comment, it really depends on whether `ESI` will be modified or not. If so, the whole `RBX` will be destroyed. – W. Chang Feb 15 '20 at 07:39
-
1Right, you extract the high half *first*, then you can use EBX for the low half. But yeah, if you need the halves zero-extended, you do need mov. You could `mov esi, ebx` / `shr rbx, 32` to turn RBX into EBX:ESI if you don't need to preserve the original RBX. – Peter Cordes Feb 15 '20 at 07:54