Author Topic: Using 64-Bit register-commands with NASM!?  (Read 18248 times)

nobody

  • Guest
Using 64-Bit register-commands with NASM!?
« on: August 02, 2009, 04:24:21 PM »
With my 64-Bit-System I should be able to use the x-registers (for example rax, rbx,rcx and rdx and also r8 to r15) but it doesn't work. I know in the gas output of my gdb-debugger it is used and obviously no problem. But if I try it in Nasm, it doesn't know this regs. The same happens with the SSE media 128-Bit-instructions xmm0 to xmm7.

My Celeron should know this regs. Or am I wrong? Does anyone know something about these "new" regs?

Best
Michel

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Using 64-Bit register-commands with NASM!?
« Reply #1 on: August 02, 2009, 05:54:04 PM »
Hi Michel,

Can you give us an example of what you're doing that doesn't work? What's "nasm -v" have to say? We recently had a bug report that Nasm was mis-reporting its version. The guy swore that a recently installed version of Nasm was "the only version on his system". Turned out, 0.98.39 was lurking in a directory that was being found before the new version. No doubt, Nasm does still have bugs in it, but I think they're a little subtler than not knowing 64-bit registers... I hope...

Best,
Frank

nobody

  • Guest
Re: Using 64-Bit register-commands with NASM!?
« Reply #2 on: August 06, 2009, 04:43:44 PM »
Hello Frank,

at last I,ve got time now for a reply:

I'm working with NASM version 0.98.39 compiled on Sep 21 2007

Here's my assembler code. It's only a simple translation from a C-Syscall to NASM. (The using of the regs is without any context) But first of all the C routine. It's only a ececve()-function to change a few vars in the environment:

/* execve.c */
#include
#include

int main (void) {
    int j;
    char filename[]={"/usr/bin/printenv"};
    char *args[] = {"printenv", NULL};
    char *env[] =  {
       "SHELL=/bin/bash",
       "LOGNAME=a_username",
       "OSTYPE=L1NuX", NULL
    };
    int value;
    value=execve(filename, args, env);
    if(value==-1)
      printf("\n\nObviously a mistake.\n\n");
    printf("\n\nThis point is never reached!?\n\n");
    return value;
}

Now the assembler tranlation which also works fine:

section .data

filename db '/usr/bin/printenv',0
argvek   db 'printenv',0
envek    db 'SHELL=/bin/bash',00Ah
         db 'LOGNAME=a_Username',00Ah
         db 'OSTYPE=L1N!!!???',0

msg db 00Ah,'If this is printed '
    db      'call to exec failed ,',00Ah
    db      'even if there is no error message!',00Ah,00Ah
len equ $-msg   

msgf db 00Ah,'Obviously a mistake. Returned with -1!',00Ah,00Ah
lenf equ $-msgf   

section .text
  global _start

_start:

;;;;;;;;;;;;;;;;;;;;; BEGINN MAIN PROGRAMM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HERE IS THE TEST ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   mov rax,1 ; Three lines only to test the regs
   mov r8,1
   mov xmm0,1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

xor eax,eax
   mov ebx,filename

push eax
   push argvek
   mov ecx,esp

push eax
   push envek
   mov edx,esp   

mov al,11
   int 0x80

mov eax,4              ; syscall write
   mov ebx,1              ; 1 = stdout
   mov ecx,msg          ; Show no error message
   mov edx,len
   int 0x80              

cmp al,-1
   jnz jumpit
   mov eax,4              ; syscall write
   mov ebx,1              ; 1 = stdout
   mov ecx,msgf         ; show error message
   mov edx,lenf
   int 0x80              

jumpit:   

mov eax, 1             ; End of programm, call to exit
   mov ebx, 0
   int 0x80

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

I also think, NASM should be able to handle the three lines above
> mov rax,1
> mov r8,1
> mov xmm0,1
But perhaps I need a spezial compiler switch? Or something for the linker?

(nasm -f elf execve.asm)

michel@linux-ms64:~/sysprog/jwclinux> make PROGLIST='exec2v0 exec2v0.asm'
exec2v0.asm:43: error: symbol `rax' undefined
exec2v0.asm:44: error: symbol `r8' undefined
exec2v0.asm:45: error: invalid combination of opcode and operands
ld -s -o execve execve.o -m elf_i386

So what can I do? As I said, gas is working without any problems if I use the huge regs and my 64 Bit-system also should know them.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Using 64-Bit register-commands with NASM!?
« Reply #3 on: August 06, 2009, 09:33:31 PM »
Well, first you'll need a newer version of Nasm. 0.98.39 doesn't know 64-bit code. It does know xmm registers, but an xmm register isn't a valid operand to "mov". I'm not sure there *is* a way to move an immediate into xmm0 - although I'm not very familiar with those instructions.

You can get the very latest snapshot of Nasm from:

http://www.nasm.us

Or 2.07, available here, should work.

Then, you'd want to use an output format that knows 64-bit instructions - "-f bin" with "bits 64", or "-f elf64" (what you'd want, I think), or "-f win64" or "-f macho64". Then you'd want to stop telling ld you want 32-bit code. Then (first, actually) you'd want to completely change your code to be compatible with 64-bit Linux: the sys_call numbers are different, the parameters go in different registers, and you want the syscall instruction instead of int 80h (int 80h *may* still work, but I wouldn't count on it).

I wish it were as simple as putting "r" in front of the register names, but it isn't. 64-bit systems have thrown asm programmers a real curve-ball, IMHO. Even "just call printf" is different between Windows64 and Linux64, I understand!!! I haven't got 64-bit hardware to experiment on, and I'm not sure I'm looking forward to it. Good luck!

Best,
Frank