Page 1 of 1
NASM 64 Bit Not Liking My Variable
Posted: Thu Jan 24, 2008 9:59 am
by AJ
Hi,
I'm trying to write a simple test-tick counter isr in NASM, and for some reason, it's not compiling. The sample is as follows:
Code: Select all
[BITS 64]
[global tickcount_isr]
tickcount_isr:
push rax
mov rax, [__tickcount]
inc rax
mov [__tickcount], rax
pop rax
iretq
__tickcount dq 0
...and the error message is 'relocation truncated to fit R_X86_64_32 against .text'. If I declare the variable in my C code instead, the error just changes to 'fit R_X86_64_32 against .bss', as you might expect.
The error appears twice - once for each time I move to/from rax and occurs whether or not I specify a qword move, or stick align 64 at the top of the source. I am compiling to elf64 and have lots of other .asm source which compiles nicely (although, come to think of it, nothing which attempts moving a variable's value to a 64 bit register).
Can anyone see what am I missing out?
Cheers,
Adam
Posted: Thu Jan 24, 2008 11:05 am
by Brynet-Inc
The follow assembles successfully with yasm, perhaps it'll work for you?
Code: Select all
[BITS 64]
[global tickcount_isr]
[global __tickcount]
;[extern __tickcount]
[section .text]
tickcount_isr:
push rax
mov rax, [__tickcount]
inc rax
mov [__tickcount], rax
pop rax
iretq
[section .data]
__tickcount dq 0
Hope this helps
EDIT: Use the elf64 object format, so
nasm -f elf64 or
yasm -f elf64.
Posted: Thu Jan 24, 2008 11:22 am
by AJ
Nope:
Code: Select all
source//arch/x86_64/interrupt/irq/tickcount.asm:(.text+0x5): relocation truncate
d to fit: R_X86_64_32 against `.data'
source//arch/x86_64/interrupt/irq/tickcount.asm:(.text+0x10): relocation truncat
ed to fit: R_X86_64_32 against `.data'
make: [bin/x86_64/kernel.sys] Error 1 (ignored)
cp: cannot stat `bin/x86_64/*.sys': No such file or directory
make: [install] Error 1 (ignored)
Copy and pasted error text after doing a copy and paste of your code

. NASM version reports v2.00. Thanks for trying!
Adam
Posted: Thu Jan 24, 2008 11:39 am
by Brynet-Inc
I accidentally trimmed the iretq instruction above, if that makes any difference..
The code pasted above
does assemble successfully with yasm-6.1 and nasm-2.01.. what you're looking at is a GNU gcc/ld error.
Why don't you write the code in GNU assembler btw?
EDIT: Perhaps you should recompile everything with gcc
-mcmodel=medium or
-mcmodel=kernel ?
Posted: Thu Jan 24, 2008 1:55 pm
by AJ
Brynet-Inc wrote:The code pasted above does assemble successfully with yasm-6.1 and nasm-2.01.. what you're looking at is a GNU gcc/ld error.
Thanks - I'd blindly assumed it was an NASM error because my C++ modules were working fine. Oh - and it looks like although I'm using NASM 2, it's 2.00 which is a RC, so I'll upgrade and see if that makes a difference
Why don't you write the code in GNU assembler btw?
Point taken. I'm afraid it's for no better reason than "That's what I've always done". I'll look in to GNU assembler and definitely make the switch if it solves the problem.
EDIT: Perhaps you should recompile everything with gcc -mcmodel=medium or -mcmodel=kernel ?
I've never used these flags before, but when I have my main machine again tomorrow, I'll look up their full effects and play with adding one or other of them.
Thanks for the advice,
Adam
Posted: Thu Jan 24, 2008 8:11 pm
by SpooK
AJ wrote:Oh - and it looks like although I'm using NASM 2, it's 2.00 which is a RC, so I'll upgrade and see if that makes a difference
NASM 2.00
is NASM 2.00. If it follows with RC
X, where
X is the release candidate number, then it is as such.
Brynet-Inc wrote:
The code pasted above does assemble successfully with yasm-6.1 and nasm-2.01.. what you're looking at is a GNU gcc/ld error.
That should have been apparent from the original error message, but the error
may be in how the variable is being addressed in NASM itself.
If he is able to assemble using "[BITS 64]", then there is no question that it is the 64-bit version of the object file format that he is using.
As for the code, first question is... why not use the following???
Code: Select all
[BITS 64]
[global tickcount_isr]
tickcount_isr:
inc QWORD[__tickcount]
iretq
__tickcount dq 0
Second is, are you linking things correctly against 64-bit versions of your C code?
Have you tried using explicit operand/address sizes, like the following???
Code: Select all
[BITS 64]
[global tickcount_isr]
tickcount_isr:
push rax
mov rax, [QWORD __tickcount]
inc rax
mov [QWORD __tickcount], rax
pop rax
iretq
__tickcount dq 0
The above code enforces 64-bit address sizes and may help you to draw closer to the real issue.
HtH

Posted: Fri Jan 25, 2008 2:45 am
by AJ
SpooK wrote:NASM 2.00 is NASM 2.00. If it follows with RC X, where X is the release candidate number, then it is as such.
Sorry, I meant "as opposed to 2.01, which Brynet was using.
As for the code, first question is... why not use the following???
Because that gave the same error message originally, which is why I moved over to using RAX.
Second is, are you linking things correctly against 64-bit versions of your C code?
Yes - I'm using a custom 64 bit toolchain which works nicely for everything else.
Have you tried using explicit operand/address sizes, like the following???
...
The above code enforces 64-bit address sizes and may help you to draw closer to the real issue.
Wow - that worked! I've never put QWORD
inside the brackets before, but I did that and the link error went away. I had certainly tried it with QWORD
outside the brackets. I guess the difference is that one ensures a 64 bit pointer, whereas the other just refers to a 64 bit operand with a pointer of any size.
Thanks for the help,
Adam
Posted: Fri Jan 25, 2008 3:00 pm
by bewing
SpooK wrote:
As for the code, first question is... why not use the following???
I know this isn't AJ's reason, but the reason *I* sometimes mov to a reg, do an INC, mov back -- is so I can conveniently watch the value change in bochs, with just an "r" command.
Posted: Fri Jan 25, 2008 7:35 pm
by SpooK
AJ wrote:Wow - that worked! I've never put QWORD inside the brackets before, but I did that and the link error went away. I had certainly tried it with QWORD outside the brackets. I guess the difference is that one ensures a 64 bit pointer, whereas the other just refers to a 64 bit operand with a pointer of any size.
Precisely, except that non-explicit operations refer to the default size, in which tends to be instruction specific but mostly seems to revolve around 32-bit even in Long Mode
AJ wrote:
Thanks for the help,
Adam
np.