Hello World
I continue to translate some of code from GCC inline assembler to Visual C++ inline assembler.
I have this C++ function:
void IoOutputDword(unsigned short address, unsigned int value)
{
__asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (address));
}
and I try it in Visual C++:
void IoOutputDword(unsigned short address, unsigned int value)
{
__asm
{
out address, eax;
}
}
But I have this log:
error C2415: improper operand type
Could you help me please?
THX
hi, nonosto!
instructions in, ins, out, outs, cli, sti, int, into, iret are the privileged instructions in windows that can only be executed in kernel space (ring 0), so you can't use them in normal Windows programs
(https://wasm.in/styles/smiles_s/yes3.gif)
It is a syntax error. Acceptable variations are: https://c9x.me/x86/html/file_module_x86_id_222.html
This will compile:
__asm
{
mov dx, address
out dx, eax;
}
Of course, it does not execute in user mode, but that is not the compilation issue.
hi, aw27!
if "address" is constant then "OUT imm8, EAX" is correct instruction, although I will not argue, since I do not write on C/ะก++
hi Mikl__!
Cdecl, parameters passed on the stack, caller cleans the stack. The function can be translated to:
IoOutputDword proc
push ebp
mov ebp, esp
mov eax, dword ptr [ebp+12]
mov dx, word ptr[ebp+8]
out dx, eax
pop ebp
ret
IoOutputDword endp
So, there is still something missing to make it work (in kernel mode): mov eax, dword ptr [ebp+12]
aw27, thank you very much!
THX all. One question why add mov instruction? In original code dont used.
It is gcc inline __asm__ specifics.
This part '"a" (value)' means place the value in eax.
You can check that with gdb or even better build in Windows under Cygwin and debug with Windbg or Olly, both are more friendly than gdb.
Insert __asm ("int $3"); before the other instruction to make it stop.
For 32-bit is better the 32-bit distribution of Cygwin, although it is possible as well to cross compile under 64-bit Cygwin, but is a bit tricky (like everything in the Unix World).
It's so hard...for example I have other function:
void disableInterrupts(void) {
__asm__ __volatile__("cli");
return;
}
void enableInterrupts(void) {
__asm__ __volatile__("sti");
return;
}
void flushCache(void) {
__asm__ __volatile__("wbinvd");
return;
}
And I translate like this:
void disableInterrupts(void)
{
__asm
{
cli
}
return;
}
void enableInterrupts(void)
{
__asm
{
sti
}
return;
}
void flushCache(void)
{
__asm
{
wbinvd
}
return;
}
I have no error but with what you said I have a doubt return same result. What do you think?
Look good, but all will crash in user mode, as you know.
THX very much. I work ina very special and very old hardware. The code/exe is by default in kernel mode.
I am sorry to abuse but I have this function I dont succes to translate..... :icon_redface:
the first:
void wrmsr(uint32_t msr, uint32_t high, uint32_t low)
{
__asm__ __volatile__ ("wrmsr"
:
:"a"(low), "c"(msr), "d"(high));
return;
}
and I try this from a web source (It's seems crazy...):
void wrmsr(uint32_t msr, uint32_t high, uint32_t low)
{
__asm
{ push ecx
push edx
push eax
mov ecx,msr
mov low,eax
mov high,edx
mov ecx, msr
wrmsr
pop eax
pop edx
pop ecx
}
return;
}
For the next my big problem are last line:
void disableCache(void) {
uint32_t mask = (1 << 30) | (1 << 29); // CD | NW
__asm__ __volatile__ ("movl %%cr0,%%eax\n"
"orl %%ecx,%%eax\n"
"movl %%eax,%%cr0"
:
:"c"(mask)
:"eax","memory");
return;
}
and I try this:
void disableCache(void)
{
uint32_t mask = (1 << 30) | (1 << 29); // CD | NW
__asm
{
mov eax, cr0
or eax, ecx
mov cr0, eax
mov ecx, mask
eax,memory
}
return;
}
exactly this line is a problem for me:
:"c"(mask)
:"eax","memory");
Could help me ?
The first one is wrong and you don't need to push volatile registers, they are fair play.
void wrmsr(uint32_t msr, uint32_t high, uint32_t low)
{
__asm
{
mov eax, low
mov ecx, msr
mov edx, high
wrmsr
}
return;
}
The second one is wrong too. Don't bother with "memory", it is a clobber argument - a special instruction to the gcc compiler to let it know there is data coming from memory (mask in this case) - Visual Studio can figure that out.
void disableCache(void)
{
uint32_t mask = (1 << 30) | (1 << 29);
__asm
{
mov ecx,mask
mov eax,cr0
or eax,ecx
mov cr0,eax
}
return;
}
This can be simplified to:
void disableCache(void)
{
__asm
{
mov eax, cr0
or eax, (1 << 30) | (1 << 29)
mov cr0, eax
}
return;
}
Thank you very much.
for:
void wrmsr(uint32_t msr, uint32_t high, uint32_t low)
{
__asm
{
mov eax, low
mov ecx, msr
mov edx, high
wrmsr
}
return;
}
I have this compiler error:
error C2400: inline assembler syntax error in 'second operand'; found 'newline'
error C2400: inline assembler syntax error in 'second operand'; found 'newline'
I dont know how to fix it.
Thanks to you I translate this code witout compil error:
from:
void enableCache(void) {
uint32_t mask = ~((1 << 30) | (1 << 29)); // CD | NW
__asm__ __volatile__ ("movl %%cr0,%%eax\n"
"andl %%ecx,%%eax\n"
"movl %%eax,%%cr0"
:
:"c"(mask)
:"eax","memory");
return;
}
to
void enableCache(void)
{
uint32_t mask = ~((1 << 30) | (1 << 29)); // CD | NW
__asm
{
mov ecx,mask
mov eax,cr0
and eax,ecx
mov cr0,eax
}
return;
}
and from:
void flushTlb(void) {
__asm__ __volatile__("movl %%cr3, %%eax\n"
"movl %%eax, %%cr3"
:
:
:"eax","memory");
return;
}
to
void flushTlb(void)
{
__asm
{
mov eax, cr3
mov cr3, eax
}
return;
}
Please could you confirm me no error please?
low and high are reserved words, not names for variables, change them.
And I think you got enough info to walk on your own. :t
thx you very much :t