Author Topic: Structure modification  (Read 16066 times)

Offline aVoX

  • Jr. Member
  • *
  • Posts: 13
Structure modification
« 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:
Code: [Select]
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.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Structure modification
« Reply #1 on: July 25, 2011, 07:41:45 AM »
I dunno... something like...

Code: [Select]
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



Offline aVoX

  • Jr. Member
  • *
  • Posts: 13
Re: Structure modification
« Reply #2 on: July 25, 2011, 10:47:06 AM »
> 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  :-\

Offline aVoX

  • Jr. Member
  • *
  • Posts: 13
Re: Structure modification
« Reply #3 on: February 14, 2012, 07:06:36 AM »
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:
Code: [Select]
    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.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Structure modification
« Reply #4 on: February 14, 2012, 03:55:58 PM »
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


Offline aVoX

  • Jr. Member
  • *
  • Posts: 13
Re: Structure modification
« Reply #5 on: February 14, 2012, 09:17:11 PM »
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.