2

I'm working on an X32 object file, which uses 32-bit Integers, Longs and Pointers. I'm building the object file like so:

nasm -f elfx32 rdrand.S -DX32 -o rdrand-x32.o

rdrand.S is multi-platofrm (X86, X32 and X64). Within the X86 block, 64-bit registers are available. So I am trying to (other code omitted to demonstrate the core problem):

%ifdef X32
  %define  buffer    rdi    ;; x32-abi (http://sites.google.com/site/x32abi/documents)
  %define  size      rsi

  rdrand   rax              ;; generate a 64-bit random value
  mov      [buffer], rax    ;; save it to caller's buffer
%else
  %define  buffer    ...

  rdrand   eax              ;; generate a 32-bit random value
  mov      [buffer], eax    ;; save it to caller's buffer
%endif

However, it appears NASM is not issuing the REX prefix on the instruction, so its resulting in:

line 100: error: no instruction for this cpu level
line 101: error: no instruction for this cpu level

I know rdrand rax will work, so its a matter of getting NASM to issue the REX prefix. (I'm not sure about mov [buffer], rax, but I'll get to that once I figure out the REX issue).

How do I tell NASM to issue the wide version of instruction?


I'm using Debian's version of NASM:

$ nasm -v
NASM version 2.11.05 compiled on Sep  9 2014

However, I'm not in an X32 enabled kernel at the moment.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • My nasm version 2.10.01 correctly emits the rex prefix and has no problem with this code. Also tested with 2.11.08 that works fine, too. – Jester Nov 10 '15 at 13:57
  • @Jester - I added the version information to the question. I double checked the results. What flags are you using for the assembler? – jww Nov 10 '15 at 14:18
  • I used your command line. Just tested with debian 2.11.05 works too. And I am not in X32 either, although I don't think that matters. I did define `buffer` to get it to assemble. – Jester Nov 10 '15 at 14:43

1 Answers1

1
%ifdef X32
  rdrand   rax              ;; generate a 64-bit random value
  mov      [buffer], rax    ;; save it to caller's buffer
  ...
%endif

Here's what I had to do (it takes more time to search for NASM's way of doing things than to issue it by hand):

            ;; X32 can use the full register, issue the REX prefix
%ifdef X32
    DB 48h
%endif
            ;; RDRAND is not available prior to Clang 3.2. Just emit
            ;;   the byte codes using DB. This is `rdrand eax`.
    DB 0Fh, 0C7h, 0F0h

And then to move the bits from rax:

%ifdef X32
    mov        [buffer+4], eax    ;; We can only move 4 at a time
    DB         048h               ;; Combined, these result in 
    shr        eax, 32            ;;   `shr rax, 32`
%endif

    mov        [buffer], eax
    add        buffer, 8          ;; No need for Intel Core 2 slow word workarounds,
    sub        bsize, 8           ;;   like faster adds using `lea buffer,[buffer+8]`
jww
  • 97,681
  • 90
  • 411
  • 885