What's new

Assembly!

Doomulation

?????????????????????????
Finally, I'm messing with assembly on my own :whistling
But, I couldn't get some things to work. Maybe you can help me out here...
See, I'm using a threaded approach with trying to communicate over functions by returning a value by processor registers. It doesn't work very well, though.
The thread is run for 1000 ms, then terminated by the TerminateThread api.
This is my approach to the asm within the function. Note that I've tried several registers without any luck. Here's my typical code so far:


Code:
...create thread...
...set priority & resume...
Sleep(1000);
TerminateThread(hThread);
int var;
__asm mov var, edi;

void func()
{
__asm pop edi;
for(;;) __asm inc edi;
}

Either the register will be used for something else or it will be nullified when trying to access the data. I suppose I could push it onto the stack when done, but then I will have to use a more refined method than TerminateThread. And I'm not too terribly good at using check instructions in asm. It would also mean to add one other instruction in the loop.

Any suggestions? And ideas?
 

BGNG

New member
A lot depends, here... Firstly, are you using C/C++ as a compiler? Secondly, make sure you're ASM-ing for the right processor... Thirdly, are you sure all your ASM code fits in a block and isn't thinking it goes somewhere else?
 

smcd

Active member
I dont understand your question or what you want to do, aside from storing a value in a register to be accessed elsewhere?
 

euphoria

Emutalk Member
Functions return a value in (e)ax register. I think that it is the only register that is guaranteed to be untouched. And pushing to stack might not work because then it cannot find the return address because of it.
All this is what i recall from the x86 assembler programming that i did years ago, so this might not be 100% accurate.
Please, correct if im wrong since this a interesting topic.

Btw. why not just allocate memory and use a global pointer to it and use it to communicate?

Edit: i just noticed that your mov is wrong. it should be:
mov edi, var
because target is the left parameter.
 
Last edited:

smcd

Active member
To put something on the stack to save for later from inside a function you'd need to pop the return address & store it somewhere temporarily, push on the value you want to save, then push the return address back onto the stack.

However (I'm not sure) since this is between 2 threads, it might be handled differently and this might not work properly...
 
OP
Doomulation

Doomulation

?????????????????????????
Okay time to answer some questions here...
I did a lot of experimenting when ET was down and have some new clues, however...

BGNG said:
A lot depends, here... Firstly, are you using C/C++ as a compiler? Secondly, make sure you're ASM-ing for the right processor... Thirdly, are you sure all your ASM code fits in a block and isn't thinking it goes somewhere else?
Yes, it's Visual C++ NET. Lol, this is typical x86 asm afaik. No, the asm is correct wher it is ;)

I dont understand your question or what you want to do, aside from storing a value in a register to be accessed elsewhere?
Trying to store the value in a register to access it outside the function when it's terminated is what I'm trying to do.

Functions return a value in (e)ax register. I think that it is the only register that is guaranteed to be untouched. And pushing to stack might not work because then it cannot find the return address because of it.
All this is what i recall from the x86 assembler programming that i did years ago, so this might not be 100% accurate.
Please, correct if im wrong since this a interesting topic.
Hmm well, I dunno much about the stack...I never really tried this approach though so may be right. But you know that the eax register is an all-purpose register and is used all the time. It is gauranteed TO BE altered.

Btw. why not just allocate memory and use a global pointer to it and use it to communicate?
The soley purpose of the asm code and storing in register is speed. Reading/writing memory is a LOT SLOWER than writing to registers.

Edit: i just noticed that your mov is wrong. it should be:
mov edi, var
because target is the left parameter.
You are right on how it's done, but the code is correct I assure you. I'm trying to move the value of edi into a variable.

To put something on the stack to save for later from inside a function you'd need to pop the return address & store it somewhere temporarily, push on the value you want to save, then push the return address back onto the stack.

However (I'm not sure) since this is between 2 threads, it might be handled differently and this might not work properly...
Hmm, so at the end of the function, the return address must be on top of the stack, correct?

Btw...I've thought about this and found some intresting facts as well.
It seems that diffrent threads have their diffrent stack (this I knew) AND registers. Modifying a register in a diffrent thread doesn't affect the register in another. I tried...
So, this absolutely makes writing to a register in the thread and getting it later impossible... however, I talked to dave and he suggested a variable... oh indeed, I'd use a test condition to terminate to loop and then move the value to a global variable... the only thing we didn't think about was the registers on diffrent threads approach...

Now I'm clueless... I don't want to write to memory if possible. I don't want any function calls if possible (this is even worse than writing to memory!). And I don't want to get rid of the thread if possible.

Anyone has an idea? Or is it the impossible I ask for?
 

Cyberman

Moderator
Moderator
Well yes you can do that to a global, IF you use thread synchronization.

Now threads are basically SEPERATE processes within the same application. Think of them as coroutines. This is why they have seperate stacks and 'registers' because they have a seperate memory space. When one thread is stoped and another executed (the just SEEM simultaneous but they aren't), the information for the one threads state must be preserved. Make sense?

In order to access the same information between two threads you should look at thread safe manners to do this. You should never have two threads modify the same variable unless you are CERTAIN they will never try to do so at the same time. However it's just plain stupid to try it. You have a chicken egg problem with this. You should only modify the variable in ONE thread and read it in many, that is thread safe.

It's draconian rule but it will save you a LOT of grief ;)

Cyb
 
OP
Doomulation

Doomulation

?????????????????????????
Yeah I know about thread synchronization and issues... but it still doesn't solve me problem =)
I need somehow to avoid writing memory and calling functions to do the operations, if possible :evil:
But I suppose I could rid the thread by turning up the process priority. But the real problem still remains.

And I do get your point. Perfecly clear.
 
Last edited:

euphoria

Emutalk Member
Doomulation said:
Hmm well, I dunno much about the stack...I never really tried this approach though so may be right. But you know that the eax register is an all-purpose register and is used all the time. It is gauranteed TO BE altered.
Yes i know how eax is used, but after a return from function the "return'ed" value is in the eax register and ofcourse you lose it if you don't save to somewhere.

Here's C code
Code:
int func(void)
{
	return 0x66666666;
}

int main(int argc, char **args)
{
	int a = func();
}
Here's the assembly generated by MSVC6
Code:
; Listing generated by Microsoft (R) Optimizing Compiler Version 12.00.9044.0 

	TITLE	C:\devel\C\src\projects\MSVC\ret_val.c
	.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT	SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA	ENDS
CONST	SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS	ENDS
$$SYMBOLS	SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS	ENDS
$$TYPES	SEGMENT BYTE USE32 'DEBTYP'
$$TYPES	ENDS
_TLS	SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS	ENDS
;	COMDAT _func
_TEXT	SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT	ENDS
;	COMDAT _main
_TEXT	SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT	ENDS
FLAT	GROUP _DATA, CONST, _BSS
	ASSUME	CS: FLAT, DS: FLAT, SS: FLAT
endif

INCLUDELIB LIBCD
INCLUDELIB OLDNAMES

PUBLIC	_func
; Function compile flags: /Odt /GZ /ZI
; File C:\devel\C\src\projects\MSVC\ret_val.c
;	COMDAT _func
_TEXT	SEGMENT
_func	PROC NEAR					; COMDAT

; 4    : {

	push	ebp
	mov	ebp, esp
	sub	esp, 64					; 00000040H
	push	ebx
	push	esi
	push	edi
	lea	edi, DWORD PTR [ebp-64]
	mov	ecx, 16					; 00000010H
	mov	eax, -858993460				; ccccccccH
	rep stosd

; 5    : 	return 0x66666666;

	mov	eax, 1717986918				; 66666666H

; 6    : }

	pop	edi
	pop	esi
	pop	ebx
	mov	esp, ebp
	pop	ebp
	ret	0
_func	ENDP
_TEXT	ENDS
PUBLIC	_main
EXTRN	__chkesp:NEAR
; Function compile flags: /Odt /GZ /ZI
;	COMDAT _main
_TEXT	SEGMENT
_a$ = -4
_main	PROC NEAR					; COMDAT

; 9    : {

	push	ebp
	mov	ebp, esp
	sub	esp, 68					; 00000044H
	push	ebx
	push	esi
	push	edi
	lea	edi, DWORD PTR [ebp-68]
	mov	ecx, 17					; 00000011H
	mov	eax, -858993460				; ccccccccH
	rep stosd

; 10   : 	int a = func();

	call	_func
	mov	DWORD PTR _a$[ebp], eax

; 11   : }

	xor	eax, eax
	pop	edi
	pop	esi
	pop	ebx
	add	esp, 68					; 00000044H
	cmp	ebp, esp
	call	__chkesp
	mov	esp, ebp
	pop	ebp
	ret	0
_main	ENDP
_TEXT	ENDS
END
Here you can see how the value 0x66666666 is returned through eax. This uses __cdecl calling convention... don't know about the others.

One thing that comes to mind is that you could write the pointer of the thread context of the 1st thread to some global variable. Then when you want to give a variable of another thread to 1st thread you take the context pointer and write to the location of say eax register. This way you would save a few memory read's.

Ofcourse the chances that this would work are quite slim. And you'd have to make sure that the 1st thread is not changing it's context (it would have to be stopped, i suppose)

It looks like you're out of luck...
 
OP
Doomulation

Doomulation

?????????????????????????
Yes it does, doesn't it?
Hmmmm... but, but, but, but... if I do a simple test of how many loops per second it does with normal memory writes and then do it with registers... i could use the previous information and multiply it with two or something and count the loops (like a normal loop), break later and save the information...

I suppose this would be the best way to do it, huh?

Ie:
Code:
int i = 0; // Global var
...
// Here starts some thread
for(; i < 10000000; i++) { } // 10 million
// end thread

I'd terminate this after 1000 ms. Then multiply the value with two. When doing the rest, I use this.

Code:
mov eax, i;
inc eax;
; some test code to check if loop condition has been met

That's what I can think of now, and seems the best solution to this problem?
I'd simply time how long it takes.
 

Top