Home > Mobile >  What is the correct syntax for AMD monitorx instruction?
What is the correct syntax for AMD monitorx instruction?

Time:02-24

Ryzen supports the monitorx instructions, as indicated by the cpuid flag. Unfortunately the visual studio masm assembler doesn't seem to like these instructions, and there is very little documentation online for how to use them.

The following code (which is very based on AMD's own documentation) reports the error A2070 "invalid instruction operands:

push rbx
mov eax, 5844h
mov ecx, 0
mov edx, 0
monitorx eax, ecx, edx
pop rbx
ret

I understand that this code isn't very useful, but it shouldn't be throwing build time errors, so what's the deal?

CodePudding user response:

The problem is that eax, ecx, and edx are 32 bit registers, but it was being assembled in 64 bit mode. Because the first operand is pointer size, it must be 64 bits. The following code will work on 64 bit programs:

push rbx
mov eax, 5844h
mov ecx, 0
mov edx, 0
monitorx rax, rcx, rdx
pop rbx
ret

CodePudding user response:

In machine code, the operands are implicit. In assembly syntax, plain monitorx works for most assemblers. The operands can be specified to document the instruction, or in some assemblers to specify an override to the address-size.

AMD's manual explicitly says that ECX and EDX are 32-bit operands. (They say there are no hints or extensions defined, so ECX must be 0 else #GP, and EDX is ignored by current CPUs.)

For the address operand, they document it as rAX, which I think means it can be EAX or RAX. In the pseudocode example, they use MONITORX EAX, ECX, EDX, but the 32-bit EAX means that's a 32-bit-mode example.

This is in their vol.3 manual, Nov. 2021 rev 3.33, the latest linked from https://developer.amd.com/resources/developer-guides-manuals/.


NASM 2.15.05 (support added for monitorx in version 2.12.01)

The operand list can be specified or omitted. If specified, the first operand must be EAX or RAX, and the next two must be ECX and EDX. (It's an error to specify RCX or RDX).

But NASM doesn't infer 32-bit address-size in 64-bit mode from using EAX.
Segment overrides can be specified with NASM prefixes.
Example listing from nasm -l/dev/stdout -felf64 foo.asm:

     1 00000000 0F01FA             monitorx
     2 00000003 0F01FA             monitorx rax, ecx, edx
     3 00000006 0F01FA             monitorx eax, ecx, edx       ; address-size override not inferred from EAX

     4 00000009 670F01FA           a32 monitorx                 ; address-size prefix, NASM style
     5 0000000D 640F01FA           fs monitorx rax, ecx, edx    ; segment override works, too

ndisasm -b64 disassembles it as just monitorx, fs monitorx, or a32 monitorx without listing the implicit operands. GNU Binutils objdump is the same in -Mintel syntax mode, but lists operands in AT&T mode. (Backwards, with %rax or

  • Related