Question

With the following code, I attempt to "store" the lower two bytes of ebx in the two higher bytes, then use the lower order bx as a temporary variable for accessing an offset into "pool". Finally, I restore the original value (it only used the lower two bytes originally) by right shifting the data over.

rol ebx, 16

mov bl, dl
;(other operations involving bx)    
mov [pool+bx], dword esi

shr ebx, 16

This assembles just fine with nasm, however I get the error

relocation truncated to fit: R_386_16 against `.data'

when linking. Any advice on how to bypass this error? Simply using another register isn't an option, as literally every register save esp and the segment registers are being used.

Edit: I assume someone will ask, so I'm using 32 Bit assembly

Was it helpful?

Solution

Because you used bx in the effective address, the assembler thought you wanted a 16 bit address and hence generated 16 bit relocation that the linker was unhappy with. It probably wouldn't work in 32 bit mode anyway, since your variable is unlikely to be in the bottom 64k of the address space.

If you don't have any free registers maybe you can use the stack:

push ebx
mov bl, dl
;(other operations involving bx)
movzx ebx, bx
mov [pool+ebx], esi
pop ebx

You said only low 16 bits of ebx were used. If that's the case for edx as well, you can save dx in the top 16 bits of ebx, such as:

shl ebx, 16
mov bx, dx
;(other operations involving dx)
movzx edx, dx
mov [pool+edx], esi
mov dx, bx
shr ebx, 16

No, you can't save arbitrary values in segment registers.

OTHER TIPS

Truncate bx with and movzx ebx,bx then use it as the index to the table mov [pool+ebx],esi :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top