0

I'm trying to get the hang of Assembly for class. So for this C code:

int a = 10;
int b = 20;
int *aPtr = &a;
int *bPtr = &b;
b += a;
*aPtr = *aPtr + *bPtr; //dereference
printf(“aPtr points to value: %d\n”, *aPtr);

*** Updated

I tried this in Assembly:

.data
    var1 DWORD 10
    var2 DWORD 20
    var3 DWORD ?
.code
    main PROC 
        mov eax, 10
        mov ebx, 20
        add ebx, eax
        mov var3, ebx
        mov eax, offset var1
        mov ebx, offset var3
        mov ecx, [eax]
        mov edx, [ebx]
        add ecx, edx
        mov var3, ecx
        INVOKE ExitProcess, 0
    main endp
end

But I know that the pointers can't simply be deferenced and added together like that. We also can't use lea, so I'm at a loss on how to add a dereferenced value to another dereferenced value in Assembly; I'm also not sure how I would convert the printf statement correctly. Could I get some help?

  • 1
    What assembly instruction set are you using? What specific step are you stuck on? Do you know how to dereference a pointer, putting its value into a register? Do you know how to do that a second time for another pointer? Do you know how to add the two register values together? Do you know how to take the register that contains the sum and store it at the address pointed to by a pointer? What specifically happened when you tried the code you posted? – David Grayson Nov 20 '22 at 01:52
  • I'm using MASM. The line that's giving me problems is converting `*aPtr = *aPtr + *bPtr;` into Assembly. To dereference, you use brackets right? So like `mov eax, [ebx]`. Something else that confuses me though is that, aren't var1 and var2 already pointers? So could I just dereference those instead? Also, what if I need more registers than just eax, ebx, ecx, and edx? – idontknowanygoodusernames Nov 20 '22 at 01:57
  • Registers cannot have their addresses taken, so `offset eax` doesn't work. You can only take the address of a memory location. `var1` and `var2` refer to memory locations, and can be used to initialize pointers. The first addition computes b+a,, but not b = b+ a; – Erik Eidt Nov 20 '22 at 01:59
  • @ErikEidt OH...I'll re-edit it then, that definitely clarified some stuff up a bit! – idontknowanygoodusernames Nov 20 '22 at 02:01
  • Ask a compiler: https://godbolt.org/z/b8hYYdE76 shows a function that takes two pointer args (already in registers since I used MSVC `-Gv` to use fastcall), and another function that returns the address of a global. Also a function that passes the address of a local var to another function, or assigning it to a volatile `int *`. This lets everything else optimize away, leaving just the interesting instructions: [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116). You can of course compiler your whole C function including the printf call. – Peter Cordes Nov 20 '22 at 02:22
  • @ErikEidt Do you think my new updated solution attempt solution makes sense? For some reason, my build keeps failing in Visual Studio so I can't check the registers myself – idontknowanygoodusernames Nov 20 '22 at 02:27

1 Answers1

0

Your code is not yet updating the a and b variables with the results from the operations.

int a = 10;
int b = 20;
int *aPtr = &a;
int *bPtr = &b;
a    SDWORD 10
b    SDWORD 20
aPtr DWORD offset a
bPtr DWORD offset b
b += a;
mov  eax, a
add  b, eax      ; Result in b (30)
*aPtr = *aPtr + *bPtr;
mov  edi, aPtr
mov  esi, bPtr
mov  eax, [edi]
add  eax, [esi]
mov  [edi], eax  ; Result in a (40)
printf(“aPtr points to value: %d\n”, *aPtr);
msg  db 'aPtr points to value: %d\n', 0
...
mov  edi, aPtr
mov  eax, [edi]
push eax
push offset msg
call _printf
add  esp, 8
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • x86 has efficient memory-destination `add`. Might as well use it unless you want the sum in a register for later use. (Especially when the C expression is written `+=` instead of two separate derefs, but there's no difference in meaning of the C, just appearance.) – Peter Cordes Nov 20 '22 at 16:28
  • @PeterCordes So would `mov eax, a` `add b, eax` be faster than my 3 instructions? I thought I should avoid Read-Modify-Write. – Sep Roland Nov 20 '22 at 16:37
  • 1
    Not since P5, or for `adc` / `sbb` specifically because of complicated reasons involving lack of TLB coherency between uops and that they have to read FLAGS as well as write it. [Why doesn't clang use memory-destination x86 instructions when I compile with optimization disabled? Are they efficient?](https://stackoverflow.com/q/54391268) – Peter Cordes Nov 20 '22 at 16:46