Rubixninja314
Rubixninja314

Reputation: 37

BTS gives "invalid combination", but only when addressing memory

If I assemble this using nasm -felf64 test.asm, I get the error:

; syntax: nasm
default rel
global main
 
section .text
main:
        call init
        ; do stuff
        ret
 
init:
        lock bts [initted], 0 ; <-- error: invalid combination of opcode and operands
        jc .continue
        ret
 
    .continue:
        ; do stuff
        ret
 
section .data
        initted db 0

Using lea gives the same result:

...
        lea rax, [initted]
        lock bts [rax], 0 ; <-- same error
        jc .continue
...

This also happens with any combination lock or default rel.

The only thing that assembles is changing it to bts rax, 0. Obviously this program doesn't have any threads, but the full one will and if multiple threads try to run init simultaneously it would definitely break.

I've looked it over several times, there's probably something stupid I missed, but I have no idea what it is.

Upvotes: 0

Views: 149

Answers (1)

Nate Eldredge
Nate Eldredge

Reputation: 58132

bts has no 8-bit form, see https://www.felixcloutier.com/x86/bts, so you can't use it on a byte variable.

If you change initted to a dw / dd / dq, you can use bts, but you have to specify the operand size, e.g. lock bts dword [initted], 0.

(I suppose that bts with a bit offset of 0 shouldn't modify anything except the low byte of its operand. So lock bts word [initted], 0 could in principle be used on initted db 0 if you can be sure it isn't on the last byte of a page, which you can guarantee by putting align 2 before it. Unless you're desperate for memory savings, it's better just to make initted larger.)

Upvotes: 2

Related Questions