NASM - The Netwide Assembler
NASM Forum => Programming with NASM => Topic started by: aVoX on July 24, 2011, 09:57:10 PM
-
Hello!
I am relatively new to assembler programming and have a simple question: How do I change the values of a structured pointer "object"?
In C/C++ it would be something like this:
typedef struct
{
int a;
int b;
int c;
} myType;
void Foo( myType *obj )
{
obj->a = [something];
obj->b = [something];
obj->c = [something];
}
int main( void )
{
myType m;
Foo( &m );
return 0;
}
How would I do the function Foo in NAsm? I did some tries but none of them really worked.
Thanking you in anticipation,
aVoX.
-
I dunno... something like...
global _start
struc obj
.a resd 1
.b resd 1
.c resd 1
endstruc
section .bss
myobj resb obj_size
section .text
_start:
push myobj
call foo
add esp, 4
exit:
mov eax, 1
xor ebx, ebx
int 80h
foo:
mov esi, [esp + 4]
mov [esi + obj.a], dword 1
mov [esi + obj.b], dword 2
mov [esi + obj.c], dword 3
ret
? Or do you need something more complicated?
Best,
Frank
-
> Or do you need something more complicated?
No, it was rally that easy. Thank you!
I messed something up with the prologue and used the wrong offset (12 for 3 integers instead of 4 for a pointer)... just some beginner mistakes I guess :-\
-
Sorry for this massive push but I thought it wouldn't be necessary to create a new thread.
When I write a dll which uses code like this and call the Procedure from a highlevel language (in my case C++) then something strange happens: When I run the code in a the "Debug" setting the debugger tells me that ESP wasn't saved properly or something like this.
The called code looks like this:
Struc VersionInfo
.Stepping resd 1
.Model resd 1
.Family resd 1
.ExModel resd 1
.ExFamily resd 1
.CpuId resd 1
EndStruc
GLOBAL _GetCpuInfo@4
EXTERN _GetCpuInfo@4
_GetCpuInfo@4:
MOV esi, [esp+4]
MOV eax, 1h
CPUID
MOV [esi+VersionInfo.CpuId], eax
MOV ecx, eax
AND ecx, 1111b ;Stepping
MOV [esi+VersionInfo.Stepping], ecx
MOV ecx, eax
SHR ecx, 8
AND ecx, 1111b ;Family
MOV [esi+VersionInfo.Family], ecx
CMP ecx, 0Fh ;ExFamily supported?
JB .exfamily
MOV edx, eax
SHR edx, 20
AND edx, 11111111b
ADD ecx, edx
.exfamily:
MOV [esi+VersionInfo.ExFamily], ecx
MOV ecx, eax
SHR ecx, 4
AND ecx, 1111b
MOV [esi+VersionInfo.Model], ecx
CMP dword [esi+VersionInfo.Family], 0Fh
JE .new_exmodel
CMP dword [g_vendorId], INTEL
JNE .store_exmodel
CMP dword [esi+VersionInfo.Family], 6
JNE .store_exmodel
.new_exmodel:
MOV edx, eax
SHR edx, 16
AND edx, 1111b
SHL edx, 4
ADD ecx, edx
.store_exmodel:
MOV dword [esi+VersionInfo.ExModel], ecx
RET 4
When I write a pseudo-prologue (push esi and esp) and a pseudo-epilogue (pop esi and esp) I get no runtime errors, but the value stored in the structure are extremely strange.
Some things I can assure: The C++ mapped structure looks exactly the same (resd -> int32_t) and I handled the calling convention right (STDCALL)
Thanks in advance, aVoX.
-
I'm not that familiar with STDCALL, but I'm pretty sure we're supposed to preserve esi. I don't know if cpuid with eax=1 trashes ebx (does with eax=0!), but that's supposed to be preserved too, I think. I'd save it to be on the safe side. I don't see what's wrong with esp like your debugger says. If it were getting corrupted, I don't see that pushing it and popping it would do any good - you'd be popping the wrong thing! A "full" prologue and epilogue shouldn't hurt, but I don't think you need it.
My only experience with C++ was trying to help a guy use the "CXB" library - an alternative to Xlib. C++ was generating some really strange (I would almost say "evil"!) code. Some, but not all, functions appeared to be taking a "hidden" parameter besides the ones showing in the C++ code. This "extra" parameter appeared to be removed with "ret 4", even though it was mostly CDECL, not STDCALL. We finally got it working as far as creating a window, but I was never able to write "hello world" to it. Never figured out how to tell if the "extra" parameter was used or not, except by disassembling the C++ code. If, in fact, C++ is pushing a "hidden" parameter in your code, it just might be that you need to end with "ret 8", even though you've only got one parameter "showing". That doesn't seem likely, but is the only possible reason I can think of that your debugger would think that esp was screwed up.
I'm quite sure that you want to preserve esi, though, and possibly ebx, too. That should put your parameter at [esp + 12]... or use the conventional prologue and get it at [ebp + 8], as usual.
Let us know if you find the solution to it.
Best,
Frank
-
I'm quite sure that you want to preserve esi, though, and possibly ebx, too. That should put your parameter at [esp + 12]
That's it!
Thank you master.