In order to deepen the impression about how the " (*p)++ " works, I wrote some test codes like:
int main()
{
int a = 3;
int *p = &a;
int b = (*p)++;
int *q = p++;
int c = a++;
int d = c++;
printf("a = %d, b = %d, c = %d, d = %d, p = %#x, q = %#x\n",a, b, c, d, p, q);
}
OUTPUT IS: a = 5, b = 3, c = 5, d = 4, p = 0xc6dc3490, q = 0xc6dc348c
But my question is about the assembly (codes are in orders and not off and on):
main:
push rbp
mov rbp, rsp
sub rsp, 48
;int a = 3 :
mov DWORD PTR [rbp-36], 3
;int *p = &a :
lea rax, [rbp-36]
mov QWORD PTR [rbp-8], rax
;int b = (*p)++ :
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax]
lea ecx, [rax+1] ;Flag1
mov rdx, QWORD PTR [rbp-8]
mov DWORD PTR [rdx], ecx
mov DWORD PTR [rbp-12], eax
;int *q = p++ :
mov rax, QWORD PTR [rbp-8] ;Flag2
lea rdx, [rax+4] ;Flag3
mov QWORD PTR [rbp-8], rdx
mov QWORD PTR [rbp-24], rax
;int c = a++;
mov eax, DWORD PTR [rbp-36]
lea edx, [rax+1] ;Flag4
mov DWORD PTR [rbp-36], edx
mov DWORD PTR [rbp-28], eax
;int d = c++;
mov eax, DWORD PTR [rbp-28]
lea edx, [rax+1] ;Flag5
mov DWORD PTR [rbp-28], edx
mov DWORD PTR [rbp-32], eax
... ... (ignore some)
Please pay attention to the "Flagx" lines which make me confused.
From above , we know that
when pointer: int *q = p++ :
lea rdx, [rax+4] ;Flag3
Here, 'lea' seems to read the addr value store in 'rax' and +4. then pass to 'rdx'.
while: int c = a++ or int d = c++ :
lea edx, [rax+1] ;Flag4/Flag5
Here, 'lea' seems to read the content of the addr value store in 'rax' (which is 3 here), and +1, come to 4 and pass to 'edx'.
But! the point is that 'rax' in these two statments are the same one. They're all from
mov rax, QWORD PTR [rbp-8] ;Flag2
As we can see, they ( Flag3 and Flag4/Flag5 ) look very similar, but they work very differently base on a same 'rax', how come ? Can the 'lea' instruction distinguish between 'rdx' and 'edx / ecx' and turn out different results ?
Thank you very much.
The lea instruction places the address specified by its first operand into the register specified by its second operand. Note, the contents of the memory location are not loaded, only the effective address is computed and placed into the register.
LEA − Used to load the address of operand into the provided register. LES − Used to load ES register and other provided register from the memory.
The lea instruction copies an “effective address” from one place to another. Unlike mov, which copies data at the address src to the destination, lea copies the value of src itself to the destination. The syntax for the destinations is the same as mov. The difference is how it handles the src.
qword ptr is a hint for the assembler to create a move op-code (machine code) using a 64bit constant address. The value that is provided is a 32bit value (8 hex-digits => 8 times a hex-digit/letter => 8 * 4bits => 32bit).
Here, 'lea' seems to read the content of the addr value store in 'rax' (which is 3 here), and +1, come to 4 and pass to 'edx'.
No, you are mistaken. lea edx, [rax+1]
doesn't change rax
. rax
is already 3
before the lea
instruction is evaluated.
But! the point is that 'rax' in these two statments are the same one. They're all from
mov rax, QWORD PTR [rbp-8]
No, you are mistaken. rax
is being set by mov eax, DWORD PTR [rbp-36]
.
Different parts of the general purpose registers can be referenced using different names.
64 32 16 8 0
| | | | |
v v v v v
+----+----+----+----+----+----+----+----+
| | | | | | | | |
+----+----+----+----+----+----+----+----+
|<------------------------------------->| rax
|<----------------->| eax
|<------->| ax
|<-->| ah
|<-->| al
This means that when you write to eax
, you are also writing to the bottom half of rax
(and the top half gets zeroed).
So,
; rax eax rdx edx
; q = p++ ; +----+----+----+----+ +----+----+----+----+
A1 mov rax, QWORD PTR [rbp-8] ; | p | | ??? |
A2 lea rdx, [rax+4] ; | p | | p+4 |
A3 mov QWORD PTR [rbp-8], rdx ; | p | | p+4 |
A4 mov QWORD PTR [rbp-24], rax ; | p | | p+4 |
; c = a++ ; | p | | p+4 |
B1 mov eax, DWORD PTR [rbp-40] ; | 0 | a | | p+4 |
B2 lea edx, [rax+1] ; | 0 | a | | 0 | a+1 |
B3 mov DWORD PTR [rbp-40], edx ; | 0 | a | | 0 | a+1 |
B4 mov DWORD PTR [rbp-28], eax ; | 0 | a | | 0 | a+1 |
; +----+----+----+----+ +----+----+----+----+
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With