gpt4 book ai didi

c - int *q = p++ 和 int c = a++ 的汇编 lea 指令

转载 作者:太空狗 更新时间:2023-10-29 15:01:51 26 4
gpt4 key购买 nike

为了加深对“(*p)++”是如何工作的印象,我写了一些测试代码如下:

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);
}

输出是:a = 5, b = 3, c = 5, d = 4, p = 0xc6dc3490, q = 0xc6dc348c

但我的问题是关于程序集(代码是按顺序排列的,而不是断断续续的):

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)

请注意让我感到困惑的“Flagx”行。
从上面我们知道
当指针:int *q = p++ :

lea     rdx, [rax+4]    ;Flag3

在这里,“lea”似乎读取了“rax”和 +4 中存储的地址值。然后传递给“rdx”。

while: int c = a++int d = c++ :

lea     edx, [rax+1]    ;Flag4/Flag5

这里'lea'好像读取了'rax'中addr值存储的内容(这里是3),+1,得出4,传给'edx'。

但是!关键是这两个语句中的“rax”是同一个。他们都来自

mov     rax, QWORD PTR [rbp-8]   ;Flag2

正如我们所见,它们(Flag3 和 Flag4/Flag5)看起来非常相似,但基于相同的“rax”,它们的工作方式却截然不同,这是怎么回事? “lea”指令能否区分“rdx”和“edx/ecx”并得出不同的结果?
非常感谢。

最佳答案

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'.

不,你错了。 lea edx, [rax+1] 不会改变 rax。在评估 lea 指令之前,rax 已经是 3

But! the point is that 'rax' in these two statments are the same one. They're all from mov rax, QWORD PTR [rbp-8]

不,你错了。 raxmov eax, DWORD PTR [rbp-36] 设置。

通用寄存器的不同部分可以使用不同的名称来引用。

   64                  32        16    8    0
| | | | |
v v v v v
+----+----+----+----+----+----+----+----+
| | | | | | | | |
+----+----+----+----+----+----+----+----+

|<------------------------------------->| rax
|<----------------->| eax
|<------->| ax
|<-->| ah
|<-->| al

这意味着当您写入 eax 时,您也在写入 rax 的下半部分(并且上半部分归零)。

所以,

                                         ; 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 |
; +----+----+----+----+ +----+----+----+----+

关于c - int *q = p++ 和 int c = a++ 的汇编 lea 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44773658/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com