1

According to this link What are the sizes of tword, oword and yword operands? we can store a number using this convention: 16 bytes (128 bit): oword, DO, RESO, DDQ, RESDQ

I tried the following:

section .data
   number do 2538

Unfortunately the following error returns:

Integer supplied to a DT, DO or DY instruction

I don't understand why it doesn't work

Community
  • 1
  • 1
Davide
  • 1,931
  • 2
  • 19
  • 39
  • Those directives are for floating point data, not integers. See: http://www.nasm.us/doc/nasmdoc3.html#section-3.4.6 – Paul R Nov 20 '16 at 15:02
  • @PaulR Thanks. There is a command with which I can insert a very large integer number (up to 2^128-1) in a memory allocation? Or a strategy? – Davide Nov 20 '16 at 15:13
  • If you read the link I sent you above then you should see that you can use `DQ` for a 64 bit constant, so just use two of those for 128 bits perhaps ? Also it may just be that you are using an old version of NASM - apparently newer versions support 128 bit constants using `oword` or `DO`. – Paul R Nov 20 '16 at 15:31
  • @PaulR Already thought at that. The problem is that I've to provide a library with wich I've to make an addition from two 128 bits numbers stored in memory. The description is the following: "Numbers are written in memory (on 16 bytes) using the "little endian" convention. Create a procedure where the address of two long numbers are in RDI respectively RSI. The result is written in the long number at address in RDI" How you can see, I can't use two different place in memory to store only one number – Davide Nov 20 '16 at 15:42
  • Of course you can: just define two 64 bit constants, the first one contains the LS 64 bits and the second one contains the MS 64 bits - the end result will be the same as if you had defined a single 128 bit constant. Or upgrade to a newer/better assembler, whichever is easier. – Paul R Nov 20 '16 at 15:44
  • LS and MS stay for major string and lower string? To the procedure I've to pass the address in memory (one single address). With your situation the number is stored in two constants. Furthermore 2^128-1 Can't be splitted in two parts (one of the two sides is always greater than 2^64-1). Already tried at this. – Davide Nov 20 '16 at 16:02
  • LS = least significant, MS = most significant. You need to understand how data is stored in memory - this is really basic stuff, and you won't get very far with programming if you don't take the time to learn the basics. For example, `db 0x34,0x12` is exactly the same as `dw 0x1234` (on little endian architectures like x86). – Paul R Nov 20 '16 at 16:04
  • Believe me. I'm a computer scientist in a an engineer school and I know how data are stored in memory eheh :) It's normal after 10 hours I don't thought at least significant and most significant. An exemple: I've the 5734 number, in binary is 1011001100110. In MS variable I've to put 1011001 and in LS 100110? I can use a mask right? – Davide Nov 20 '16 at 16:15
  • See the example I gave above for db and dw - then use exactly the same approach to generate a 128 bit value from two 64 bit values using `dq`. – Paul R Nov 20 '16 at 16:19
  • See answer below if it's still not clear from the comments above. – Paul R Nov 20 '16 at 16:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/128575/discussion-between-davide-and-paul-r). – Davide Nov 20 '16 at 17:01

2 Answers2

3

If your assembler does not support 128 bit integer constants with do then you can achieve the same thing with dq by splitting the constant into two 64 bit halves, e.g.

section .data
    number do 0x000102030405060708090a0b0c0d0e0f

could be implemented as

section .data
    number dq 0x08090a0b0c0d0e0f,0x0001020304050607
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • Thanks. If somebody else has this problem you can also achieve this task, doing the following: `SECTION .bss number: resb 16 ;or number: reso 1` And then: `mov qword[number], 0x08090a0b0c0d0e0f mov qword[number+8], 0x0001020304050607` – Davide Nov 20 '16 at 16:47
2

Unless some other code needs it in memory, it's cheaper to generate on the fly a vector with all 128 bits set to 1 = 0xFF... repeating = 2^128-1:

pcmpeqw  xmm0, xmm0      ; xmm0 = 0xFF... repeating

;You can store to memory if you want, e.g. to set a bitmap to all-ones.
movups   [rdx], xmm0

See also What are the best instruction sequences to generate vector constants on the fly?


For the use-case you described in comments, there's no reason to mess with static data in .data or .rodata, or static storage in .bss. Just make space on the stack and pass pointers to that.

call_something_by_ref:
    sub      rsp, 24
    pcmpeqw  xmm0, xmm0      ; xmm0 = 0xFF... repeating
    mov      rdi, rsp
    movaps   [rdi], xmm0     ; one byte shorter than  movaps [rsp], xmm0
    lea      rsi, [rdi+8]
    call     some_function
    add      rsp, 24
    ret

Notice that this code has no immediate constants larger than 8 bits (for data or addresses), and it only touches memory that's already hot in cache (the bottom of the stack). And yes, store-forwarding does work from wide vector stores to integer loads when some_function dereferences RDI and RSI separately.

Community
  • 1
  • 1
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847