tags:

views:

41

answers:

2

I am writing an assembly function to be called from C that will call the sidt machine instruction with a memory address passed to the C function. From my analysis of the code produced by MSVC10, I have constructed the following code (YASM syntax):

SECTION    .data
SECTION    .text
GLOBAL _sidtLoad
_sidtLoad:

push        ebp  
mov         ebp,esp  
sub         esp,0C0h  
push        ebx  
push        esi  
push        edi  
lea         edi,[ebp-0C0h]  
mov         ecx,30h  
mov         eax,0CCCCCCCCh  

sidt [ebp+8]

pop         edi  
pop         esi  
pop         ebx  
add         esp,0C0h  
cmp         ebp,esp    
mov         esp,ebp  
pop         ebp  
ret  

Here is the C function signature:

void sidtLoad (void* mem);

As far as I can see everything should work, I have even checked the memory address passed to the function and have seen that it matches the address stored at [ebp+8] (the bytes are reversed, which I presume is a result of endianness and should be handled by the machine). I have tried other arguments for the sidt instruction, such as [ebp+12], [ebp+4], [ebp-8] etc but no luck.

P.S I am writing this in an external assembly module in order to get around the lack of inline assembly when targeting x64 using MSVC10. However, this particular assembly function/program is being run as x86, just so I can get to grips with the whole process.

P.P.S I am not using the __sidt intrinsic as the Windows Driver Kit (WDK) doesn't seem to support it. Or at least I can't get it to work with it!

+1  A: 

compile:

int sidLoad_fake(void * mem) {
    return (int)mem;
}

to assembly, and then look at where it pulls the value from to put in the return register.

I think that the first few arguments on x86_64 are passed in registers.

nategoose
+2  A: 

Your code will write the IDT into the memory address ebp+8, which is not what you want. Instead, you need something like:

mov eax, [ebp+8]
sidt [eax]
interjay
Works like a charm, thanking you kindly.
Gareth Foster