AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Machine code functions: Bit Wizardry
Goto page Previous  1, 2, 3 ... 20, 21, 22, 23, 24  Next
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
ddk



Joined: 28 Dec 2009
Posts: 43

PostPosted: Wed Sep 01, 2010 7:15 pm    Post subject: Reply with quote

What the heck really? After reinstall of windows none of the machine code functions hasn't worked. I've fresh install of AHK + AHK_L and none of Bin2Hex / Hex2Bin functions presented on this topic haven't worked at all. It always returns empty. At the moment I have ANSI build of AHK_L (version 1.0.48.05.L56). Could my nLited XP be the issue? Have I removed something important library?
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1786

PostPosted: Fri Sep 03, 2010 2:35 pm    Post subject: Reply with quote

Sorry, am I being dumb, but why doesnt the following work?

Code:
double Test(double N1)
{
   double N2 = 3;
   return N1*N2;
}


Code:
MCode(r, "DD442404DC0D00000000C3")
E := DllCall(&r, "double", 2.0, "cdecl double")
MsgBox, %E%
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Fri Sep 03, 2010 4:30 pm    Post subject: Reply with quote

just guessing... Operations on doubles are often performed by calling system functions. Their addresses are filled in by the linker. The machine code does not contain the system function, nor its correct address.

If you want to operate on doubles, you often have to write assembler code.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1786

PostPosted: Sat Sep 04, 2010 1:23 pm    Post subject: Reply with quote

Laszlo wrote:
just guessing... Operations on doubles are often performed by calling system functions. Their addresses are filled in by the linker. The machine code does not contain the system function, nor its correct address.

If you want to operate on doubles, you often have to write assembler code.


Would you be able to show me an example? Ive tried and failed

I seem to be getting so many things that to me inexplicably do not work:

Code:
int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o;
   for (int y = 0; y < h; ++y)
   {
      for (int x = 0; x < w; ++x)
      {
         o = (4*x)+(Stride*y);
         Bitmap[3+o] = Bitmap[3+o]/2;
         Bitmap[2+o] = Bitmap[2+o];
         Bitmap[1+o] = Bitmap[1+o];
         Bitmap[o] = Bitmap[o];
      }
   }
   return 0;
}


The above code never reaches the end. Bitmap[3+o]/2 should cast it as an integer, so just to be sure, I did:

Code:
int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o, p;
   for (int y = 0; y < h; ++y)
   {
      for (int x = 0; x < w; ++x)
      {
         o = (4*x)+(Stride*y);
         p = Bitmap[3+o]/2;
         Bitmap[3+o] = p;
         Bitmap[2+o] = Bitmap[2+o];
         Bitmap[1+o] = Bitmap[1+o];
         Bitmap[o] = Bitmap[o];
      }
   }
   return p;
}


and it seems to do it correctly as it turns the opacity from 255 to 127....however, the code doesnt seem to actually do anything! The resulting bitmap is unchanged.

Its been giving me a real headache......youll notice that im doing Bitmap[o] = Bitmap[o];
so im assigning the blue value to itself....so i should be able to miss all of those lines out and just set opacity.....no such luck

This doesnt work:
Code:

int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o;
   for (int y = 0; y < h; ++y)
   {
      for (int x = 0; x < w; ++x)
      {
         o = (4*x)+(Stride*y);
         Bitmap[3+o] = 127;
      }
   }
   return 0;
}


and this does:

Code:
int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o;
   for (int y = 0; y < h; ++y)
   {
      for (int x = 0; x < w; ++x)
      {
         o = (4*x)+(Stride*y);
         Bitmap[3+o] = 127;
         Bitmap[2+o] = Bitmap[2+o];
         Bitmap[1+o] = Bitmap[1+o];
         Bitmap[o] = Bitmap[o];
      }
   }
   return 0;
}


if anyone can shed some light on this and also the double problem then I would be grateful to gain some of my sanity back
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Sat Sep 04, 2010 4:14 pm    Post subject: Reply with quote

I am not sure what you want to achieve with the C function, but the index calculation looks suspicious. I would try something like this:
Code:
int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o, x, y;
   for (y = 0; y < h; ++y)
   {
      for (x = 0; x < w; ++x)
      {
         o = 4*(x+Stride*w*y);
         Bitmap[3+o] /= 2;
      }
   }
   return 0;
}

You can test it in AHK with
Code:
MCode(HalfOpacity,"558bec578b7d1085ff7e2b8b550c0faf551433c9c1e20256837d0c007e128b"
. "45088b750c8d440103d02883c0044e75f803ca4f75e35e33c05f5dc3")

w := 3, h := 4
VarSetCapacity(BitMap,4*w*h,255)

dllcall(&HalfOpacity, "UInt",&BitMap, "Short",w, "Short",h, "Short",1, "CDECL Short")

SetFormat Integer, HEX
Loop %h% {
   i := A_Index-1
   Loop %w% {
      j := A_Index-1
      t .= NumGet(BitMap,(i*w+j)*4) . "`t"
   }
   t .= "`n"
}

MsgBox %t%

MCode(ByRef code, hex) {
   VarSetCapacity(code, StrLen(hex)//2)
   Loop % StrLen(hex)//2
      NumPut("0x" . SubStr(hex, 2*A_Index-1, 2), code, A_Index-1, "char")
}

You may need to swap the role of x and y in some places, make the C function "void", etc.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1786

PostPosted: Sat Sep 04, 2010 6:10 pm    Post subject: Reply with quote

Hey Laszlo

No the index calculations are definitely correct. You can see this in this example:

Gdip_PixelateBitmap.zip

Just run Gdip_PixelateBitmap.ahk and prepare to be amazed Wink

Code:
o = (4*x)+(Stride*y);


4 is for 32bpp (ARGB) and x is how many pixels along to move. Stride is the total width of a line of pixels including padding, so Stride*y will jump to the next row of pixels.

The above machine code for MCode_PixelateBitmap() is created from:

Code:
int Gdip_PixelateBitmap(unsigned char * Bitmap, int w, int h, int Stride, int Size)
{
   int sA, sR, sG, sB, rw, rh, o;

   if (Size > w || Size > h)
      Size = (w > h) ? h : w;
   
   for (int y1 = 0; y1 < h/Size; ++y1)
   {
      for (int x1 = 0; x1 < w/Size; ++x1)
      {
         sA = sR = sG = sB = 0;
         for (int y2 = 0; y2 < Size; ++y2)
         {
            for (int x2 = 0; x2 < Size; ++x2)
            {
               o = 4*(x2+x1*Size)+Stride*(y2+y1*Size);
               sA += Bitmap[3+o];
               sR += Bitmap[2+o];
               sG += Bitmap[1+o];
               sB += Bitmap[o];
            }
         }
         
         sA /= Size*Size;
         sR /= Size*Size;
         sG /= Size*Size;
         sB /= Size*Size;
         for (int y2 = 0; y2 < Size; ++y2)
         {
            for (int x2 = 0; x2 < Size; ++x2)
            {
               o = 4*(x2+x1*Size)+Stride*(y2+y1*Size);
               Bitmap[3+o] = sA;
               Bitmap[2+o] = sR;
               Bitmap[1+o] = sG;
               Bitmap[o] = sB;
            }
         }
      }
      
      if (w % Size != 0)
      {
         sA = sR = sG = sB = 0;
         for (int y2 = 0; y2 < Size; ++y2)
         {
            for (int x2 = 0; x2 < w % Size; ++x2)
            {
               o = 4*(x2+(w/Size)*Size)+Stride*(y2+y1*Size);
               sA += Bitmap[3+o];
               sR += Bitmap[2+o];
               sG += Bitmap[1+o];
               sB += Bitmap[o];
            }
         }
         
         sA /= (w % Size)*Size;
         sR /= (w % Size)*Size;
         sG /= (w % Size)*Size;
         sB /= (w % Size)*Size;
         for (int y2 = 0; y2 < Size; ++y2)
         {
            for (int x2 = 0; x2 < w % Size; ++x2)
            {
               o = 4*(x2+(w/Size)*Size)+Stride*(y2+y1*Size);
               Bitmap[3+o] = sA;
               Bitmap[2+o] = sR;
               Bitmap[1+o] = sG;
               Bitmap[o] = sB;
            }
         }
      }
   }

   for (int x1 = 0; x1 < w/Size; ++x1)
   {
      sA = sR = sG = sB = 0;
      for (int y2 = 0; y2 < h % Size; ++y2)
      {
         for (int x2 = 0; x2 < Size; ++x2)
         {
            o = 4*(x2+x1*Size)+Stride*(y2+(h/Size)*Size);
            sA += Bitmap[3+o];
            sR += Bitmap[2+o];
            sG += Bitmap[1+o];
            sB += Bitmap[o];
         }
      }
      
      sA /= Size*(h % Size);
      sR /= Size*(h % Size);
      sG /= Size*(h % Size);
      sB /= Size*(h % Size);
      for (int y2 = 0; y2 < h % Size; ++y2)
      {
         for (int x2 = 0; x2 < Size; ++x2)
         {
            o = 4*(x2+x1*Size)+Stride*(y2+(h/Size)*Size);
            Bitmap[3+o] = sA;
            Bitmap[2+o] = sR;
            Bitmap[1+o] = sG;
            Bitmap[o] = sB;
         }
      }
   }
   
   sA = sR = sG = sB = 0;
   for (int y2 = 0; y2 < h % Size; ++y2)
   {
      for (int x2 = 0; x2 < w % Size; ++x2)
      {
         o = 4*(x2+(w/Size)*Size)+Stride*(y2+(h/Size)*Size);
         sA += Bitmap[3+o];
         sR += Bitmap[2+o];
         sG += Bitmap[1+o];
         sB += Bitmap[o];
      }
   }
   
   sA /= (w % Size)*(h % Size);
   sR /= (w % Size)*(h % Size);
   sG /= (w % Size)*(h % Size);
   sB /= (w % Size)*(h % Size);
   for (int y2 = 0; y2 < h % Size; ++y2)
   {
      for (int x2 = 0; x2 < w % Size; ++x2)
      {
         o = 4*(x2+(w/Size)*Size)+Stride*(y2+(h/Size)*Size);
         Bitmap[3+o] = sA;
         Bitmap[2+o] = sR;
         Bitmap[1+o] = sG;
         Bitmap[o] = sB;
      }
   }
   return 0;
}


I will release this as the next Gdip tutorial (Gdip.ahk 1.38 is included in the zip)

So.....its so frustrating when some things just dont work and I have no idea why. there doesnt appear to be any reason for it Sad
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Sat Sep 04, 2010 7:16 pm    Post subject: Reply with quote

What exactly does not work? Could you post the dll call, too? My sample code works for me with VS'08 express.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1786

PostPosted: Sat Sep 04, 2010 7:53 pm    Post subject: Reply with quote

ok so here is the full code of a very simple test of what Im trying (obviously the function isnt just going to half the opacity of a bitmap, but ive simplified it down to that as that is whats failing)

Code:
int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o;
   for (int y = 0; y < h; ++y)
   {
      for (int x = 0; x < w; ++x)
      {
         o = (4*x)+(Stride*y);
         Bitmap[3+o] = Bitmap[3+o]/2;   //A
      }
   }
   return 0;
}


Bitmap[3+o] is A
Bitmap[2+o] is R
Bitmap[1+o] is G
Bitmap[3+o] is B

The project with above machine code is here:

http://www.autohotkey.net/~tic/HalfOpacity.zip

It will display the jpg on screen, but the machine code hasnt modified it all

however, this will work:

Code:
int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o;
   for (int y = 0; y < h; ++y)
   {
      for (int x = 0; x < w; ++x)
      {
         o = (4*x)+(Stride*y);
         Bitmap[3+o] = Bitmap[3+o]-127;   //A
         Bitmap[2+o] = Bitmap[2+o];      //R
         Bitmap[1+o] = Bitmap[1+o];      //G
         Bitmap[o] = Bitmap[o];         //B
      }
   }
   return 0;
}


This will also work:

Code:
int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o;
   for (int y = 0; y < h; ++y)
   {
      for (int x = 0; x < w; ++x)
      {
         o = (4*x)+(Stride*y);
         Bitmap[3+o] = Bitmap[3+o]-127;   //A
         Bitmap[2+o] = Bitmap[2+o];      //R
         Bitmap[1+o] = Bitmap[1+o];      //G
      }
   }
   return 0;
}


but this wont:

Code:
int HalfOpacity(unsigned char * Bitmap, int w, int h, int Stride)
{
   int o;
   for (int y = 0; y < h; ++y)
   {
      for (int x = 0; x < w; ++x)
      {
         o = (4*x)+(Stride*y);
         Bitmap[3+o] = Bitmap[3+o]-127;   //A
         Bitmap[2+o] = Bitmap[2+o];      //R
      }
   }
   return 0;
}


if you msgbox the return value then it gives no result, so its failed

Thanks for helping with this
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Sat Sep 04, 2010 8:23 pm    Post subject: Reply with quote

What AHK script do you use to call these? Try to strip it to the minimum, so the debugging could be easier.

In your large script you pass parameters as "int", but some C compilers use int as 16-bit integers. This is why I used in my AHK sample "short" parameters. Or use "long" in the C code...


Last edited by Laszlo on Sat Sep 04, 2010 8:27 pm; edited 1 time in total
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1786

PostPosted: Sat Sep 04, 2010 8:26 pm    Post subject: Reply with quote

Laszlo wrote:
What AHK script do you use to call these? Try to strip it to the minimum, so the debugging could be easier.


its in the zip i attached along with the image it uses and the latest gdi+ library
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Sat Sep 04, 2010 8:29 pm    Post subject: Reply with quote

In your script you pass parameters as "int", but some C compilers use int as 16-bit integers. This is why I used in my AHK sample "short" parameters. Or use "long" in the C code... Make sure the operands are of the same type.
Back to top
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1786

PostPosted: Sat Sep 04, 2010 8:34 pm    Post subject: Reply with quote

Laszlo wrote:
In your script you pass parameters as "int", but some C compilers use int as 16-bit integers. This is why I used in my AHK sample "short" parameters. Or use "long" in the C code... Make sure the operands are of the same type.


i have tested that and it also does not work. also, that would not explain why some examples work fine, but if i remove some code then it stops working. the w and h parameters work fine and loop the correct number of times. try the Gdip_PixelateBitmap example and you can see that the same maths works fine
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4710
Location: Boulder, CO

PostPosted: Sat Sep 04, 2010 8:43 pm    Post subject: Reply with quote

The next thing to check would be the machine code conversion. Sometimes the function code does not end at the return instruction. The example I posted above worked for me with any of your dummy instructions.
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Sun Sep 05, 2010 1:41 am    Post subject: Reply with quote

ddk wrote:
What the heck really? After reinstall of windows none of the machine code functions hasn't worked.
I would guess that Data Execution Prevention got enabled. Try this:
Code:
MCode(ByRef code, hex) {
   VarSetCapacity(code,StrLen(hex)//2)
   Loop % StrLen(hex)//2
      NumPut("0x" . SubStr(hex,2*A_Index-1,2), code, A_Index-1, "Char")
   DllCall("VirtualProtect", "uint", &code, "uint", VarSetCapacity(code), "uint", 0x40, "uint*", 0)
}

tic wrote:
Sorry, am I being dumb, but why doesnt the following work?
How did you generate that code? It doesn't seem to actually correspond to your C source code. In particular, it has a hard-coded NULL pointer:
Code:
DD 44 24 04          fld         qword ptr [esp+4] 
DC 0D 00 00 00 00    fmul        qword ptr ds:[0]
C3                   ret 
This should be the address of a double-precision floating-point number (3.0). To use it with MCode, you would need to calculate the address at run-time and overwrite that part of the machine code. Most (or all?) floating-point operations don't accept their operand directly, only via a memory operand or the floating-point stack.

For integer factors, I would suggest something like this instead:
Code:
DD 44 24 04        fld   qword ptr [esp+4]  ; load param onto FP stack => ST(0)
6A 03              push  3                  ; push integer onto stack => [esp]
DA 0C 24           fimul dword ptr [esp]    ; multiply ST(0) by [esp] (integer promoted to double)
59                 pop   ecx                ; pop integer and discard
C3                 ret
Floating-point factors are a little more complicated. Here's an example:
Code:
DD 44 24 04        fld  qword ptr [esp+4]
68 00 00 0C 40     push 0x400C0000  ; push second half of (double)3.5
6A 00              push 0x00000000  ; push first half
DC 0C 24           fmul qword ptr [esp]
83 C4 08           add  esp, 8
C3                 ret
Note that push 0 can also be encoded as 68 00 00 00 00.
Back to top
View user's profile Send private message Visit poster's website
tic



Joined: 22 Apr 2007
Posts: 1786

PostPosted: Sun Sep 05, 2010 11:16 am    Post subject: Reply with quote

youre absolutely right Lex....

Code:
DD4424046A03DA0C2459C3


works perfectly from:

Code:
DD 44 24 04        fld   qword ptr [esp+4]  ; load param onto FP stack => ST(0)
6A 03              push  3                  ; push integer onto stack => [esp]
DA 0C 24           fimul dword ptr [esp]    ; multiply ST(0) by [esp] (integer promoted to double)
59                 pop   ecx                ; pop integer and discard
C3                 ret


Im confused why my machine code is wrong

I compile with flags:

/TC /c /FAc /Facode.cod /O2 /W1

to generate machine and assebly code with /FAc and get:

Code:
; Listing generated by Microsoft (R) Optimizing Compiler Version 15.00.30729.01

   TITLE   J:\My Dropbox\MCodeCreator\tempCode.c
   .686P
   .XMM
   include listing.inc
   .model   flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC   __real@4008000000000000
PUBLIC   _Test
EXTRN   __fltused:DWORD
;   COMDAT __real@4008000000000000
; File j:\my dropbox\mcodecreator\tempcode.c
CONST   SEGMENT
__real@4008000000000000 DQ 04008000000000000r   ; 3
; Function compile flags: /Ogtpy
CONST   ENDS
;   COMDAT _Test
_TEXT   SEGMENT
_N1$ = 8                  ; size = 8
_Test   PROC                  ; COMDAT
; Line 4
  00000   dd 44 24 04    fld    QWORD PTR _N1$[esp-4]
  00004   dc 0d 00 00 00
   00       fmul    QWORD PTR __real@4008000000000000
; Line 5
  0000a   c3       ret    0
_Test   ENDP
_TEXT   ENDS
END


what is:

Code:
QWORD PTR __real@4008000000000000
?
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3 ... 20, 21, 22, 23, 24  Next
Page 21 of 24

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group