Question: In IA-32 assembly language, can IDTR, GDTR or LDTR be modified/'loaded' without the LIDT, LGDT and LLDT instructions?

Also, is there a complete list of instructions that can be used to modify other registers? I need to know which instructions could be used to modify CR3, and which instructions could be used to modify ECX.

I am new to IA-32 assembly. I am aware of MOV, ADD, SUB, etc., however it would need to be a complete list and I believe there are probably a whole lot of instructions which could potentially be used to modify these registers.

Thanks! :)

Edit: The reason I want to know is because I am considering whether monitoring an instruction trace (using hardware debugging) of executed instructions is a feasible method of detecting - in an external 'integrity monitoring' machine - any malicious rootkits which alter the addresses in these registers to perform what is known as an Address Translation Redirection Attack (ATRA). Therefore, I am trying to determine whether it is possible to determine a complete list of potential malicious instruction sequences modifying each of these registers.

Answer: 
The IDTR, GDTR or LDTR can be modified by:

* LIDT, LGDT and LLDT instructions
* entering system management mode, modifying the values in the "state save" area, then leaving system management mode to cause the modified values to be loaded
* using hardware virtualisation extensions, where host is able to modify the virtual IDTR, GDTR or LDTR used by guest

Note that this list does not include keeping the IDTR, GDTR or LDTR the same and modifying the data they point to (the IDT, GDT or LDT).

CR3 can be changed by:

* `mov cr3` instruction
* hardware task switch
* code running in system management mode
* hardware virtualisation extensions (host modifies guest)

ECX can be changed by:

* a few hundred different instructions (too many to list)
* hardware task switch
* code running in system management mode
* hardware virtualisation extensions (host modifies guest)

Note that hardware task switching is almost never used and is also no longer supported in long mode; and system management mode is normally completely unusable for software (including software running at CPL=0) and it's only really possible for the system's firmware to use it.
Regarding `IDTR`, `GDTR`, and `LDTR`, the [Intel System Programming Guide](http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-system-programming-manual-325384.pdf) has the answers :

Section 2.4.1, "Global Descriptor Table Register" (`GDTR`) :

> 
> The `LGDT` and `SGDT` instructions load and store the `GDTR` register,
>  respectively.
> 
> 
> 

Section 2.4.2, "Local Descriptor Table Register" (`LDTR`) :

> 
> The `LLDT` and `SLDT` instructions load and store the segment selector
>  part of the `LDTR` register, respectively. The segment that contains the
>  `LDT` must have a segment descriptor in the `GDT`. When the `LLDT`
>  instruction loads a segment selector in the `LDTR`: the base address,
>  limit, and descriptor attributes from the `LDT` descriptor are auto-
>  matically loaded in the `LDTR`. When a task switch occurs, the `LDTR` is
>  automatically loaded with the segment selector and descriptor for the
>  `LDT` for the new task. The contents of the `LDTR` are not automatically
>  saved prior to writing the new `LDT` information into the register.
> 
> 
> 

So, there are only two instructions used for modifying the table, but task switching in the processor (though it's not used by any of the mainstream operating systems anymore, so whether you should worry about this depends on what you're actually doing) can cause the contents of this register to change.

Section 2.4.3, "`IDTR` Interrupt Descriptor Table Register" :

> 
> The `LIDT` and `SIDT` instructions load and store the `IDTR` register,
>  respectively.
> 
> 
> 

Regarding `ECX`, however, there is no one clear answer. Since it was used as a "count" register back in the days of real mode, it might be modified by some loop-related instructions implicitly. Off the top of my head :

* `LOOP` (and its derivatives), which decrements `ECX` and jumps if it's not zero. However, you shouldn't really see this instruction a lot in new code, as it's mostly a leftover from CISC days and as such its use is discouraged when emitting code for today's CPUs. This is due to relatively long time (compared to `test` + jump) it takes to decode it.
* `REP` (and its derivatives), which repeats a given instruction as long as `ECX` is not zero.
* `CPUID`, which uses all the registers to return CPU identification information.

I'm sure there's some more. I'd be surprised if such a list exists, though it would certainly be useful sometimes.