NASM - The Netwide Assembler
NASM Forum => Using NASM => Topic started by: nobody 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
-
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
-
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.
-
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 (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